forked from openkylin/platform_build
make sure package keys are consistent with shared users
All APKs that want to share a given user id must be signed with the same key. Look inside each APK for what (if any) shared user id it requests, and error out if any with the same shared user are being signed with different keys.
This commit is contained in:
parent
87fc0fdc53
commit
eb338efd2e
|
@ -101,6 +101,85 @@ def GetApkCerts(tf_zip):
|
|||
return certmap
|
||||
|
||||
|
||||
def CheckAllApksSigned(input_tf_zip, apk_key_map):
|
||||
"""Check that all the APKs we want to sign have keys specified, and
|
||||
error out if they don't."""
|
||||
unknown_apks = []
|
||||
for info in input_tf_zip.infolist():
|
||||
if info.filename.endswith(".apk"):
|
||||
name = os.path.basename(info.filename)
|
||||
if name not in apk_key_map:
|
||||
unknown_apks.append(name)
|
||||
if unknown_apks:
|
||||
print "ERROR: no key specified for:\n\n ",
|
||||
print "\n ".join(unknown_apks)
|
||||
print "\nUse '-e <apkname>=' to specify a key (which may be an"
|
||||
print "empty string to not sign this apk)."
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def SharedUserForApk(data):
|
||||
tmp = tempfile.NamedTemporaryFile()
|
||||
tmp.write(data)
|
||||
tmp.flush()
|
||||
|
||||
p = common.Run(["aapt", "dump", "xmltree", tmp.name, "AndroidManifest.xml"],
|
||||
stdout=subprocess.PIPE)
|
||||
data, _ = p.communicate()
|
||||
if p.returncode != 0:
|
||||
raise ExternalError("failed to run aapt dump")
|
||||
lines = data.split("\n")
|
||||
for i in lines:
|
||||
m = re.match(r'^\s*A: android:sharedUserId\([0-9a-fx]*\)="([^"]*)" .*$', i)
|
||||
if m:
|
||||
return m.group(1)
|
||||
return None
|
||||
|
||||
|
||||
def CheckSharedUserIdsConsistent(input_tf_zip, apk_key_map):
|
||||
"""Check that all packages that request the same shared user id are
|
||||
going to be signed with the same key."""
|
||||
|
||||
shared_user_apks = {}
|
||||
maxlen = 0
|
||||
|
||||
for info in input_tf_zip.infolist():
|
||||
if info.filename.endswith(".apk"):
|
||||
data = input_tf_zip.read(info.filename)
|
||||
|
||||
name = os.path.basename(info.filename)
|
||||
shared_user = SharedUserForApk(data)
|
||||
key = apk_key_map[name]
|
||||
maxlen = max(maxlen, len(key))
|
||||
|
||||
if shared_user is not None:
|
||||
shared_user_apks.setdefault(
|
||||
shared_user, {}).setdefault(key, []).append(name)
|
||||
|
||||
errors = []
|
||||
for k, v in shared_user_apks.iteritems():
|
||||
# each shared user should have exactly one key used for all the
|
||||
# apks that want that user.
|
||||
if len(v) > 1:
|
||||
errors.append((k, v))
|
||||
|
||||
if not errors: return
|
||||
|
||||
print "ERROR: shared user inconsistency. All apks wanting to use"
|
||||
print " a given shared user must be signed with the same key."
|
||||
print
|
||||
errors.sort()
|
||||
for user, keys in errors:
|
||||
print 'shared user id "%s":' % (user,)
|
||||
for key, apps in keys.iteritems():
|
||||
print ' %-*s %s' % (maxlen, key, apps[0])
|
||||
for a in apps[1:]:
|
||||
print (' ' * (maxlen+5)) + a
|
||||
print
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def SignApk(data, keyname, pw):
|
||||
unsigned = tempfile.NamedTemporaryFile()
|
||||
unsigned.write(data)
|
||||
|
@ -117,31 +196,11 @@ def SignApk(data, keyname, pw):
|
|||
return data
|
||||
|
||||
|
||||
def SignApks(input_tf_zip, output_tf_zip):
|
||||
apk_key_map = GetApkCerts(input_tf_zip)
|
||||
|
||||
def SignApks(input_tf_zip, output_tf_zip, apk_key_map, key_passwords):
|
||||
maxsize = max([len(os.path.basename(i.filename))
|
||||
for i in input_tf_zip.infolist()
|
||||
if i.filename.endswith('.apk')])
|
||||
|
||||
# Check that all the APKs we want to sign have keys specified, and
|
||||
# error out if they don't. Do this before prompting for key
|
||||
# passwords in case we're going to fail anyway.
|
||||
unknown_apks = []
|
||||
for info in input_tf_zip.infolist():
|
||||
if info.filename.endswith(".apk"):
|
||||
name = os.path.basename(info.filename)
|
||||
if name not in apk_key_map:
|
||||
unknown_apks.append(name)
|
||||
if unknown_apks:
|
||||
print "ERROR: no key specified for:\n\n ",
|
||||
print "\n ".join(unknown_apks)
|
||||
print "\nUse '-e <apkname>=' to specify a key (which may be an"
|
||||
print "empty string to not sign this apk)."
|
||||
sys.exit(1)
|
||||
|
||||
key_passwords = common.GetKeyPasswords(set(apk_key_map.values()))
|
||||
|
||||
for info in input_tf_zip.infolist():
|
||||
data = input_tf_zip.read(info.filename)
|
||||
out_info = copy.copy(info)
|
||||
|
@ -289,7 +348,12 @@ def main(argv):
|
|||
input_zip = zipfile.ZipFile(args[0], "r")
|
||||
output_zip = zipfile.ZipFile(args[1], "w")
|
||||
|
||||
SignApks(input_zip, output_zip)
|
||||
apk_key_map = GetApkCerts(input_zip)
|
||||
CheckAllApksSigned(input_zip, apk_key_map)
|
||||
CheckSharedUserIdsConsistent(input_zip, apk_key_map)
|
||||
|
||||
key_passwords = common.GetKeyPasswords(set(apk_key_map.values()))
|
||||
SignApks(input_zip, output_zip, apk_key_map, key_passwords)
|
||||
|
||||
if OPTIONS.replace_ota_keys:
|
||||
ReplaceOtaKeys(input_zip, output_zip)
|
||||
|
|
Loading…
Reference in New Issue