Merge "releasetools: Clean up check_target_files_signatures.py."
am: f6e8d46e2f
Change-Id: Ib38d151320c6c750986418a449970d1711f030a6
This commit is contained in:
@@ -39,8 +39,11 @@ Usage: check_target_file_signatures [flags] target_files
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import os.path
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
@@ -49,7 +52,7 @@ import zipfile
|
|||||||
import common
|
import common
|
||||||
|
|
||||||
if sys.hexversion < 0x02070000:
|
if sys.hexversion < 0x02070000:
|
||||||
print >> sys.stderr, "Python 2.7 or newer is required."
|
print("Python 2.7 or newer is required.", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
@@ -65,8 +68,10 @@ logger = logging.getLogger(__name__)
|
|||||||
class MyZipInfo(zipfile.ZipInfo):
|
class MyZipInfo(zipfile.ZipInfo):
|
||||||
def _decodeExtra(self):
|
def _decodeExtra(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
zipfile.ZipInfo = MyZipInfo
|
zipfile.ZipInfo = MyZipInfo
|
||||||
|
|
||||||
|
|
||||||
OPTIONS = common.OPTIONS
|
OPTIONS = common.OPTIONS
|
||||||
|
|
||||||
OPTIONS.text = False
|
OPTIONS.text = False
|
||||||
@@ -76,28 +81,34 @@ OPTIONS.local_cert_dirs = ("vendor", "build")
|
|||||||
PROBLEMS = []
|
PROBLEMS = []
|
||||||
PROBLEM_PREFIX = []
|
PROBLEM_PREFIX = []
|
||||||
|
|
||||||
|
|
||||||
def AddProblem(msg):
|
def AddProblem(msg):
|
||||||
PROBLEMS.append(" ".join(PROBLEM_PREFIX) + " " + msg)
|
PROBLEMS.append(" ".join(PROBLEM_PREFIX) + " " + msg)
|
||||||
|
|
||||||
|
|
||||||
def Push(msg):
|
def Push(msg):
|
||||||
PROBLEM_PREFIX.append(msg)
|
PROBLEM_PREFIX.append(msg)
|
||||||
|
|
||||||
|
|
||||||
def Pop():
|
def Pop():
|
||||||
PROBLEM_PREFIX.pop()
|
PROBLEM_PREFIX.pop()
|
||||||
|
|
||||||
|
|
||||||
def Banner(msg):
|
def Banner(msg):
|
||||||
print "-" * 70
|
print("-" * 70)
|
||||||
print " ", msg
|
print(" ", msg)
|
||||||
print "-" * 70
|
print("-" * 70)
|
||||||
|
|
||||||
|
|
||||||
def GetCertSubject(cert):
|
def GetCertSubject(cert):
|
||||||
p = common.Run(["openssl", "x509", "-inform", "DER", "-text"],
|
p = common.Run(["openssl", "x509", "-inform", "DER", "-text"],
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE)
|
stdout=subprocess.PIPE,
|
||||||
|
universal_newlines=False)
|
||||||
out, err = p.communicate(cert)
|
out, err = p.communicate(cert)
|
||||||
if err and not err.strip():
|
if err and not err.strip():
|
||||||
return "(error reading cert subject)"
|
return "(error reading cert subject)"
|
||||||
for line in out.split("\n"):
|
for line in out.decode().split("\n"):
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if line.startswith("Subject:"):
|
if line.startswith("Subject:"):
|
||||||
return line[8:].strip()
|
return line[8:].strip()
|
||||||
@@ -105,6 +116,7 @@ def GetCertSubject(cert):
|
|||||||
|
|
||||||
|
|
||||||
class CertDB(object):
|
class CertDB(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.certs = {}
|
self.certs = {}
|
||||||
|
|
||||||
@@ -132,13 +144,13 @@ class CertDB(object):
|
|||||||
to_load.extend(certs)
|
to_load.extend(certs)
|
||||||
|
|
||||||
for i in to_load:
|
for i in to_load:
|
||||||
f = open(i)
|
with open(i) as f:
|
||||||
cert = common.ParseCertificate(f.read())
|
cert = common.ParseCertificate(f.read())
|
||||||
f.close()
|
|
||||||
name, _ = os.path.splitext(i)
|
name, _ = os.path.splitext(i)
|
||||||
name, _ = os.path.splitext(name)
|
name, _ = os.path.splitext(name)
|
||||||
self.Add(cert, name)
|
self.Add(cert, name)
|
||||||
|
|
||||||
|
|
||||||
ALL_CERTS = CertDB()
|
ALL_CERTS = CertDB()
|
||||||
|
|
||||||
|
|
||||||
@@ -152,13 +164,14 @@ def CertFromPKCS7(data, filename):
|
|||||||
"-outform", "PEM",
|
"-outform", "PEM",
|
||||||
"-print_certs"],
|
"-print_certs"],
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE)
|
stdout=subprocess.PIPE,
|
||||||
|
universal_newlines=False)
|
||||||
out, err = p.communicate(data)
|
out, err = p.communicate(data)
|
||||||
if err and not err.strip():
|
if err and not err.strip():
|
||||||
AddProblem("error reading cert:\n" + err)
|
AddProblem("error reading cert:\n" + err.decode())
|
||||||
return None
|
return None
|
||||||
|
|
||||||
cert = common.ParseCertificate(out)
|
cert = common.ParseCertificate(out.decode())
|
||||||
if not cert:
|
if not cert:
|
||||||
AddProblem("error parsing cert output")
|
AddProblem("error parsing cert output")
|
||||||
return None
|
return None
|
||||||
@@ -184,22 +197,20 @@ class APK(object):
|
|||||||
|
|
||||||
def RecordCerts(self, full_filename):
|
def RecordCerts(self, full_filename):
|
||||||
out = set()
|
out = set()
|
||||||
try:
|
with zipfile.ZipFile(full_filename) as apk:
|
||||||
f = open(full_filename)
|
|
||||||
apk = zipfile.ZipFile(f, "r")
|
|
||||||
pkcs7 = None
|
pkcs7 = None
|
||||||
for info in apk.infolist():
|
for info in apk.infolist():
|
||||||
if info.filename.startswith("META-INF/") and \
|
filename = info.filename
|
||||||
(info.filename.endswith(".DSA") or info.filename.endswith(".RSA")):
|
if (filename.startswith("META-INF/") and
|
||||||
pkcs7 = apk.read(info.filename)
|
info.filename.endswith((".DSA", ".RSA"))):
|
||||||
cert = CertFromPKCS7(pkcs7, info.filename)
|
pkcs7 = apk.read(filename)
|
||||||
|
cert = CertFromPKCS7(pkcs7, filename)
|
||||||
out.add(cert)
|
out.add(cert)
|
||||||
ALL_CERTS.Add(cert)
|
ALL_CERTS.Add(cert)
|
||||||
if not pkcs7:
|
if not pkcs7:
|
||||||
AddProblem("no signature")
|
AddProblem("no signature")
|
||||||
finally:
|
|
||||||
f.close()
|
self.certs = frozenset(out)
|
||||||
self.certs = frozenset(out)
|
|
||||||
|
|
||||||
def ReadManifest(self, full_filename):
|
def ReadManifest(self, full_filename):
|
||||||
p = common.Run(["aapt", "dump", "xmltree", full_filename,
|
p = common.Run(["aapt", "dump", "xmltree", full_filename,
|
||||||
@@ -247,8 +258,8 @@ class TargetFiles(object):
|
|||||||
# This is the list of wildcards of files we extract from |filename|.
|
# This is the list of wildcards of files we extract from |filename|.
|
||||||
apk_extensions = ['*.apk', '*.apex']
|
apk_extensions = ['*.apk', '*.apex']
|
||||||
|
|
||||||
self.certmap, compressed_extension = common.ReadApkCerts(
|
with zipfile.ZipFile(filename) as input_zip:
|
||||||
zipfile.ZipFile(filename))
|
self.certmap, compressed_extension = common.ReadApkCerts(input_zip)
|
||||||
if compressed_extension:
|
if compressed_extension:
|
||||||
apk_extensions.append('*.apk' + compressed_extension)
|
apk_extensions.append('*.apk' + compressed_extension)
|
||||||
|
|
||||||
@@ -287,7 +298,7 @@ class TargetFiles(object):
|
|||||||
"""Look for any instances where packages signed with different
|
"""Look for any instances where packages signed with different
|
||||||
certs request the same sharedUserId."""
|
certs request the same sharedUserId."""
|
||||||
apks_by_uid = {}
|
apks_by_uid = {}
|
||||||
for apk in self.apks.itervalues():
|
for apk in self.apks.values():
|
||||||
if apk.shared_uid:
|
if apk.shared_uid:
|
||||||
apks_by_uid.setdefault(apk.shared_uid, []).append(apk)
|
apks_by_uid.setdefault(apk.shared_uid, []).append(apk)
|
||||||
|
|
||||||
@@ -302,15 +313,15 @@ class TargetFiles(object):
|
|||||||
|
|
||||||
AddProblem("different cert sets for packages with uid %s" % (uid,))
|
AddProblem("different cert sets for packages with uid %s" % (uid,))
|
||||||
|
|
||||||
print "uid %s is shared by packages with different cert sets:" % (uid,)
|
print("uid %s is shared by packages with different cert sets:" % (uid,))
|
||||||
for apk in apks:
|
for apk in apks:
|
||||||
print "%-*s [%s]" % (self.max_pkg_len, apk.package, apk.filename)
|
print("%-*s [%s]" % (self.max_pkg_len, apk.package, apk.filename))
|
||||||
for cert in apk.certs:
|
for cert in apk.certs:
|
||||||
print " ", ALL_CERTS.Get(cert)
|
print(" ", ALL_CERTS.Get(cert))
|
||||||
print
|
print()
|
||||||
|
|
||||||
def CheckExternalSignatures(self):
|
def CheckExternalSignatures(self):
|
||||||
for apk_filename, certname in self.certmap.iteritems():
|
for apk_filename, certname in self.certmap.items():
|
||||||
if certname == "EXTERNAL":
|
if certname == "EXTERNAL":
|
||||||
# Apps marked EXTERNAL should be signed with the test key
|
# Apps marked EXTERNAL should be signed with the test key
|
||||||
# during development, then manually re-signed after
|
# during development, then manually re-signed after
|
||||||
@@ -326,25 +337,25 @@ class TargetFiles(object):
|
|||||||
def PrintCerts(self):
|
def PrintCerts(self):
|
||||||
"""Display a table of packages grouped by cert."""
|
"""Display a table of packages grouped by cert."""
|
||||||
by_cert = {}
|
by_cert = {}
|
||||||
for apk in self.apks.itervalues():
|
for apk in self.apks.values():
|
||||||
for cert in apk.certs:
|
for cert in apk.certs:
|
||||||
by_cert.setdefault(cert, []).append((apk.package, apk))
|
by_cert.setdefault(cert, []).append((apk.package, apk))
|
||||||
|
|
||||||
order = [(-len(v), k) for (k, v) in by_cert.iteritems()]
|
order = [(-len(v), k) for (k, v) in by_cert.items()]
|
||||||
order.sort()
|
order.sort()
|
||||||
|
|
||||||
for _, cert in order:
|
for _, cert in order:
|
||||||
print "%s:" % (ALL_CERTS.Get(cert),)
|
print("%s:" % (ALL_CERTS.Get(cert),))
|
||||||
apks = by_cert[cert]
|
apks = by_cert[cert]
|
||||||
apks.sort()
|
apks.sort()
|
||||||
for _, apk in apks:
|
for _, apk in apks:
|
||||||
if apk.shared_uid:
|
if apk.shared_uid:
|
||||||
print " %-*s %-*s [%s]" % (self.max_fn_len, apk.filename,
|
print(" %-*s %-*s [%s]" % (self.max_fn_len, apk.filename,
|
||||||
self.max_pkg_len, apk.package,
|
self.max_pkg_len, apk.package,
|
||||||
apk.shared_uid)
|
apk.shared_uid))
|
||||||
else:
|
else:
|
||||||
print " %-*s %s" % (self.max_fn_len, apk.filename, apk.package)
|
print(" %-*s %s" % (self.max_fn_len, apk.filename, apk.package))
|
||||||
print
|
print()
|
||||||
|
|
||||||
def CompareWith(self, other):
|
def CompareWith(self, other):
|
||||||
"""Look for instances where a given package that exists in both
|
"""Look for instances where a given package that exists in both
|
||||||
@@ -365,12 +376,12 @@ class TargetFiles(object):
|
|||||||
by_certpair.setdefault((other.apks[i].certs,
|
by_certpair.setdefault((other.apks[i].certs,
|
||||||
self.apks[i].certs), []).append(i)
|
self.apks[i].certs), []).append(i)
|
||||||
else:
|
else:
|
||||||
print "%s [%s]: new APK (not in comparison target_files)" % (
|
print("%s [%s]: new APK (not in comparison target_files)" % (
|
||||||
i, self.apks[i].filename)
|
i, self.apks[i].filename))
|
||||||
else:
|
else:
|
||||||
if i in other.apks:
|
if i in other.apks:
|
||||||
print "%s [%s]: removed APK (only in comparison target_files)" % (
|
print("%s [%s]: removed APK (only in comparison target_files)" % (
|
||||||
i, other.apks[i].filename)
|
i, other.apks[i].filename))
|
||||||
|
|
||||||
if by_certpair:
|
if by_certpair:
|
||||||
AddProblem("some APKs changed certs")
|
AddProblem("some APKs changed certs")
|
||||||
@@ -378,23 +389,23 @@ class TargetFiles(object):
|
|||||||
for (old, new), packages in sorted(by_certpair.items()):
|
for (old, new), packages in sorted(by_certpair.items()):
|
||||||
for i, o in enumerate(old):
|
for i, o in enumerate(old):
|
||||||
if i == 0:
|
if i == 0:
|
||||||
print "was", ALL_CERTS.Get(o)
|
print("was", ALL_CERTS.Get(o))
|
||||||
else:
|
else:
|
||||||
print " ", ALL_CERTS.Get(o)
|
print(" ", ALL_CERTS.Get(o))
|
||||||
for i, n in enumerate(new):
|
for i, n in enumerate(new):
|
||||||
if i == 0:
|
if i == 0:
|
||||||
print "now", ALL_CERTS.Get(n)
|
print("now", ALL_CERTS.Get(n))
|
||||||
else:
|
else:
|
||||||
print " ", ALL_CERTS.Get(n)
|
print(" ", ALL_CERTS.Get(n))
|
||||||
for i in sorted(packages):
|
for i in sorted(packages):
|
||||||
old_fn = other.apks[i].filename
|
old_fn = other.apks[i].filename
|
||||||
new_fn = self.apks[i].filename
|
new_fn = self.apks[i].filename
|
||||||
if old_fn == new_fn:
|
if old_fn == new_fn:
|
||||||
print " %-*s [%s]" % (max_pkg_len, i, old_fn)
|
print(" %-*s [%s]" % (max_pkg_len, i, old_fn))
|
||||||
else:
|
else:
|
||||||
print " %-*s [was: %s; now: %s]" % (max_pkg_len, i,
|
print(" %-*s [was: %s; now: %s]" % (max_pkg_len, i,
|
||||||
old_fn, new_fn)
|
old_fn, new_fn))
|
||||||
print
|
print()
|
||||||
|
|
||||||
|
|
||||||
def main(argv):
|
def main(argv):
|
||||||
@@ -451,9 +462,9 @@ def main(argv):
|
|||||||
target_files.CompareWith(compare_files)
|
target_files.CompareWith(compare_files)
|
||||||
|
|
||||||
if PROBLEMS:
|
if PROBLEMS:
|
||||||
print "%d problem(s) found:\n" % (len(PROBLEMS),)
|
print("%d problem(s) found:\n" % (len(PROBLEMS),))
|
||||||
for p in PROBLEMS:
|
for p in PROBLEMS:
|
||||||
print p
|
print(p)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
@@ -464,9 +475,7 @@ if __name__ == '__main__':
|
|||||||
r = main(sys.argv[1:])
|
r = main(sys.argv[1:])
|
||||||
sys.exit(r)
|
sys.exit(r)
|
||||||
except common.ExternalError as e:
|
except common.ExternalError as e:
|
||||||
print
|
print("\n ERROR: %s\n" % (e,))
|
||||||
print " ERROR: %s" % (e,)
|
|
||||||
print
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
finally:
|
finally:
|
||||||
common.Cleanup()
|
common.Cleanup()
|
||||||
|
Reference in New Issue
Block a user