18b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert#!/usr/bin/env python 28b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# 38b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# Copyright (C) 2009 The Android Open Source Project 48b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# 58b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# Licensed under the Apache License, Version 2.0 (the "License"); 68b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# you may not use this file except in compliance with the License. 78b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# You may obtain a copy of the License at 88b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# 98b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# http://www.apache.org/licenses/LICENSE-2.0 108b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# 118b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# Unless required by applicable law or agreed to in writing, software 128b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# distributed under the License is distributed on an "AS IS" BASIS, 138b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 148b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# See the License for the specific language governing permissions and 158b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# limitations under the License. 168b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 178b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert""" 188b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertCheck the signatures of all APKs in a target_files .zip file. With 198b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert-c, compare the signatures of each package to the ones in a separate 208b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Alberttarget_files (usually a previously distributed build for the same 218b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdevice) and flag any changes. 228b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 238b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertUsage: check_target_file_signatures [flags] target_files 248b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 258b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert -c (--compare_with) <other_target_files> 268b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Look for compatibility problems between the two sets of target 278b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert files (eg., packages whose keys have changed). 288b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 298b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert -l (--local_cert_dirs) <dir,dir,...> 308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Comma-separated list of top-level directories to scan for 318b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert .x509.pem files. Defaults to "vendor,build". Where cert files 328b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert can be found that match APK signatures, the filename will be 338b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert printed as the cert name, otherwise a hash of the cert plus its 348b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert subject string will be printed instead. 358b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 368b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert -t (--text) 378b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Dump the certificate information for both packages in comparison 388b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert mode (this output is normally suppressed). 398b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 408b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert""" 418b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 428b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertimport os 438b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertimport re 448b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertimport subprocess 45767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Baoimport sys 468b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertimport zipfile 478b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 488b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertimport common 498b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 50767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Baoif sys.hexversion < 0x02070000: 51767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao print >> sys.stderr, "Python 2.7 or newer is required." 52767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao sys.exit(1) 53767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao 54767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao 55d32e78fd3c447278cf5539164f8764fbe5ae1ccaTao Bao# Work around a bug in Python's zipfile module that prevents opening of zipfiles 56d32e78fd3c447278cf5539164f8764fbe5ae1ccaTao Bao# if any entry has an extra field of between 1 and 3 bytes (which is common with 57d32e78fd3c447278cf5539164f8764fbe5ae1ccaTao Bao# zipaligned APKs). This overrides the ZipInfo._decodeExtra() method (which 58d32e78fd3c447278cf5539164f8764fbe5ae1ccaTao Bao# contains the bug) with an empty version (since we don't need to decode the 59d32e78fd3c447278cf5539164f8764fbe5ae1ccaTao Bao# extra field anyway). 60d32e78fd3c447278cf5539164f8764fbe5ae1ccaTao Bao# Issue #14315: https://bugs.python.org/issue14315, fixed in Python 2.7.8 and 61d32e78fd3c447278cf5539164f8764fbe5ae1ccaTao Bao# Python 3.5.0 alpha 1. 628b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertclass MyZipInfo(zipfile.ZipInfo): 638b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def _decodeExtra(self): 648b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert pass 658b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertzipfile.ZipInfo = MyZipInfo 668b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 678b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS = common.OPTIONS 688b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 698b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.text = False 708b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.compare_with = None 718b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.local_cert_dirs = ("vendor", "build") 728b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 738b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertPROBLEMS = [] 748b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertPROBLEM_PREFIX = [] 758b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 768b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef AddProblem(msg): 778b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert PROBLEMS.append(" ".join(PROBLEM_PREFIX) + " " + msg) 788b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef Push(msg): 798b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert PROBLEM_PREFIX.append(msg) 808b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef Pop(): 818b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert PROBLEM_PREFIX.pop() 828b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 838b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 848b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef Banner(msg): 858b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print "-" * 70 868b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print " ", msg 878b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print "-" * 70 888b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 898b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 908b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef GetCertSubject(cert): 918b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert p = common.Run(["openssl", "x509", "-inform", "DER", "-text"], 928b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert stdin=subprocess.PIPE, 938b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert stdout=subprocess.PIPE) 948b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert out, err = p.communicate(cert) 958b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if err and not err.strip(): 968b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return "(error reading cert subject)" 978b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for line in out.split("\n"): 988b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert line = line.strip() 998b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if line.startswith("Subject:"): 1008b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return line[8:].strip() 1018b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return "(unknown cert subject)" 1028b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1038b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1048b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertclass CertDB(object): 1058b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def __init__(self): 1068b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.certs = {} 1078b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1088b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def Add(self, cert, name=None): 1098b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if cert in self.certs: 1108b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if name: 1118b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.certs[cert] = self.certs[cert] + "," + name 1128b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 1138b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if name is None: 1148b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert name = "unknown cert %s (%s)" % (common.sha1(cert).hexdigest()[:12], 1158b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert GetCertSubject(cert)) 1168b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.certs[cert] = name 1178b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1188b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def Get(self, cert): 1198b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert """Return the name for a given cert.""" 1208b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return self.certs.get(cert, None) 1218b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1228b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def FindLocalCerts(self): 1238b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert to_load = [] 1248b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for top in OPTIONS.local_cert_dirs: 1258b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for dirpath, _, filenames in os.walk(top): 1268b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert certs = [os.path.join(dirpath, i) 1278b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for i in filenames if i.endswith(".x509.pem")] 1288b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if certs: 1298b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert to_load.extend(certs) 1308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1318b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for i in to_load: 1328b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert f = open(i) 1338b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert cert = common.ParseCertificate(f.read()) 1348b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert f.close() 1358b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert name, _ = os.path.splitext(i) 1368b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert name, _ = os.path.splitext(name) 1378b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.Add(cert, name) 1388b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1398b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertALL_CERTS = CertDB() 1408b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1418b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1428b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef CertFromPKCS7(data, filename): 1438b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert """Read the cert out of a PKCS#7-format file (which is what is 1448b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert stored in a signed .apk).""" 1458b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Push(filename + ":") 1468b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert try: 1478b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert p = common.Run(["openssl", "pkcs7", 1488b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "-inform", "DER", 1498b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "-outform", "PEM", 1508b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "-print_certs"], 1518b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert stdin=subprocess.PIPE, 1528b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert stdout=subprocess.PIPE) 1538b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert out, err = p.communicate(data) 1548b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if err and not err.strip(): 1558b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert AddProblem("error reading cert:\n" + err) 1568b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return None 1578b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1588b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert cert = common.ParseCertificate(out) 1598b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if not cert: 1608b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert AddProblem("error parsing cert output") 1618b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return None 1628b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return cert 1638b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert finally: 1648b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Pop() 1658b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1668b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1678b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertclass APK(object): 1688b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def __init__(self, full_filename, filename): 1698b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.filename = filename 1708b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.certs = None 1718b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.shared_uid = None 1728b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.package = None 1738b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1748b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Push(filename+":") 1758b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert try: 1768b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.RecordCerts(full_filename) 1778b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.ReadManifest(full_filename) 1788b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert finally: 1798b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Pop() 1808b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1818b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def RecordCerts(self, full_filename): 1828b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert out = set() 1838b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert try: 1848b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert f = open(full_filename) 1858b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert apk = zipfile.ZipFile(f, "r") 1868b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert pkcs7 = None 1878b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for info in apk.infolist(): 1888b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if info.filename.startswith("META-INF/") and \ 1898b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert (info.filename.endswith(".DSA") or info.filename.endswith(".RSA")): 1908b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert pkcs7 = apk.read(info.filename) 1918b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert cert = CertFromPKCS7(pkcs7, info.filename) 1928b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert out.add(cert) 1938b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert ALL_CERTS.Add(cert) 1948b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if not pkcs7: 1958b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert AddProblem("no signature") 1968b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert finally: 1978b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert f.close() 1988b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.certs = frozenset(out) 1998b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 2008b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def ReadManifest(self, full_filename): 2018b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert p = common.Run(["aapt", "dump", "xmltree", full_filename, 2028b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "AndroidManifest.xml"], 2038b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert stdout=subprocess.PIPE) 2048b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert manifest, err = p.communicate() 2058b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if err: 2068b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert AddProblem("failed to read manifest") 2078b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return 2088b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 2098b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.shared_uid = None 2108b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.package = None 2118b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 2128b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for line in manifest.split("\n"): 2138b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert line = line.strip() 2148b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert m = re.search(r'A: (\S*?)(?:\(0x[0-9a-f]+\))?="(.*?)" \(Raw', line) 2158b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if m: 2168b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert name = m.group(1) 2178b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if name == "android:sharedUserId": 2188b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if self.shared_uid is not None: 2198b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert AddProblem("multiple sharedUserId declarations") 2208b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.shared_uid = m.group(2) 2218b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif name == "package": 2228b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if self.package is not None: 2238b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert AddProblem("multiple package declarations") 2248b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.package = m.group(2) 2258b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 2268b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if self.package is None: 2278b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert AddProblem("no package declaration") 2288b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 2298b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 2308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertclass TargetFiles(object): 2318b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def __init__(self): 2328b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.max_pkg_len = 30 2338b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.max_fn_len = 20 2348b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.apks = None 2358b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.apks_by_basename = None 2368b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.certmap = None 2378b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 2388b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def LoadZipFile(self, filename): 239a07bf049b9ac92b9c4f82092ac0b10f78c762998Narayan Kamath # First read the APK certs file to figure out whether there are compressed 240a07bf049b9ac92b9c4f82092ac0b10f78c762998Narayan Kamath # APKs in the archive. If we do have compressed APKs in the archive, then we 241a07bf049b9ac92b9c4f82092ac0b10f78c762998Narayan Kamath # must decompress them individually before we perform any analysis. 242a07bf049b9ac92b9c4f82092ac0b10f78c762998Narayan Kamath 243a07bf049b9ac92b9c4f82092ac0b10f78c762998Narayan Kamath # This is the list of wildcards of files we extract from |filename|. 244a07bf049b9ac92b9c4f82092ac0b10f78c762998Narayan Kamath apk_extensions = ['*.apk'] 245a07bf049b9ac92b9c4f82092ac0b10f78c762998Narayan Kamath 246767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao self.certmap, compressed_extension = common.ReadApkCerts( 247767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao zipfile.ZipFile(filename, "r")) 248a07bf049b9ac92b9c4f82092ac0b10f78c762998Narayan Kamath if compressed_extension: 249a07bf049b9ac92b9c4f82092ac0b10f78c762998Narayan Kamath apk_extensions.append("*.apk" + compressed_extension) 250a07bf049b9ac92b9c4f82092ac0b10f78c762998Narayan Kamath 251dba59eeabd21c91d67d6a6ce365141deb56ed0f7Tao Bao d = common.UnzipTemp(filename, apk_extensions) 252767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao self.apks = {} 253767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao self.apks_by_basename = {} 254767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao for dirpath, _, filenames in os.walk(d): 255767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao for fn in filenames: 256767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao # Decompress compressed APKs before we begin processing them. 257767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao if compressed_extension and fn.endswith(compressed_extension): 258767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao # First strip the compressed extension from the file. 259767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao uncompressed_fn = fn[:-len(compressed_extension)] 260767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao 261767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao # Decompress the compressed file to the output file. 262767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao common.Gunzip(os.path.join(dirpath, fn), 263767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao os.path.join(dirpath, uncompressed_fn)) 264767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao 265767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao # Finally, delete the compressed file and use the uncompressed file 266767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao # for further processing. Note that the deletion is not strictly 267767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao # required, but is done here to ensure that we're not using too much 268767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao # space in the temporary directory. 269767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao os.remove(os.path.join(dirpath, fn)) 270767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao fn = uncompressed_fn 271767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao 272767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao if fn.endswith(".apk"): 273767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao fullname = os.path.join(dirpath, fn) 274767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao displayname = fullname[len(d)+1:] 275767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao apk = APK(fullname, displayname) 276767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao self.apks[apk.filename] = apk 277767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao self.apks_by_basename[os.path.basename(apk.filename)] = apk 278767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao 279767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao self.max_pkg_len = max(self.max_pkg_len, len(apk.package)) 280767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao self.max_fn_len = max(self.max_fn_len, len(apk.filename)) 2818b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 2828b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def CheckSharedUids(self): 2838b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert """Look for any instances where packages signed with different 2848b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert certs request the same sharedUserId.""" 2858b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert apks_by_uid = {} 2868b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for apk in self.apks.itervalues(): 2878b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if apk.shared_uid: 2888b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert apks_by_uid.setdefault(apk.shared_uid, []).append(apk) 2898b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 290767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao for uid in sorted(apks_by_uid): 2918b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert apks = apks_by_uid[uid] 2928b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for apk in apks[1:]: 2938b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if apk.certs != apks[0].certs: 2948b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert break 2958b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 2968b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # all packages have the same set of certs; this uid is fine. 2978b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert continue 2988b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 2998b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert AddProblem("different cert sets for packages with uid %s" % (uid,)) 3008b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3018b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print "uid %s is shared by packages with different cert sets:" % (uid,) 3028b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for apk in apks: 3038b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print "%-*s [%s]" % (self.max_pkg_len, apk.package, apk.filename) 3048b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for cert in apk.certs: 3058b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print " ", ALL_CERTS.Get(cert) 3068b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print 3078b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3088b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def CheckExternalSignatures(self): 3098b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for apk_filename, certname in self.certmap.iteritems(): 3108b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if certname == "EXTERNAL": 3118b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # Apps marked EXTERNAL should be signed with the test key 3128b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # during development, then manually re-signed after 3138b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # predexopting. Consider it an error if this app is now 3148b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # signed with any key that is present in our tree. 3158b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert apk = self.apks_by_basename[apk_filename] 3168b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert name = ALL_CERTS.Get(apk.cert) 3178b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if not name.startswith("unknown "): 3188b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Push(apk.filename) 3198b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert AddProblem("hasn't been signed with EXTERNAL cert") 3208b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Pop() 3218b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3228b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def PrintCerts(self): 3238b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert """Display a table of packages grouped by cert.""" 3248b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert by_cert = {} 3258b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for apk in self.apks.itervalues(): 3268b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for cert in apk.certs: 3278b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert by_cert.setdefault(cert, []).append((apk.package, apk)) 3288b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3298b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert order = [(-len(v), k) for (k, v) in by_cert.iteritems()] 3308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert order.sort() 3318b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3328b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for _, cert in order: 3338b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print "%s:" % (ALL_CERTS.Get(cert),) 3348b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert apks = by_cert[cert] 3358b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert apks.sort() 3368b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for _, apk in apks: 3378b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if apk.shared_uid: 3388b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print " %-*s %-*s [%s]" % (self.max_fn_len, apk.filename, 3398b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.max_pkg_len, apk.package, 3408b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert apk.shared_uid) 3418b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 3426a54299fbd16a3bd2051f08d5dbdaf94b95bf485Tao Bao print " %-*s %s" % (self.max_fn_len, apk.filename, apk.package) 3438b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print 3448b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3458b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def CompareWith(self, other): 3468b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert """Look for instances where a given package that exists in both 3478b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self and other have different certs.""" 3488b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3498b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert all_apks = set(self.apks.keys()) 3508b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert all_apks.update(other.apks.keys()) 3518b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3528b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert max_pkg_len = max(self.max_pkg_len, other.max_pkg_len) 3538b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3548b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert by_certpair = {} 3558b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 356726b7f338f32ca6d18e9961b0a2da3ef385f7e34Tao Bao for i in all_apks: 3578b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if i in self.apks: 3588b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if i in other.apks: 3598b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # in both; should have same set of certs 3608b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if self.apks[i].certs != other.apks[i].certs: 3618b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert by_certpair.setdefault((other.apks[i].certs, 3628b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert self.apks[i].certs), []).append(i) 3638b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 3648b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print "%s [%s]: new APK (not in comparison target_files)" % ( 3658b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert i, self.apks[i].filename) 3668b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 3678b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if i in other.apks: 3688b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print "%s [%s]: removed APK (only in comparison target_files)" % ( 3698b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert i, other.apks[i].filename) 3708b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3718b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if by_certpair: 3728b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert AddProblem("some APKs changed certs") 3738b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Banner("APK signing differences") 3748b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for (old, new), packages in sorted(by_certpair.items()): 3758b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for i, o in enumerate(old): 3768b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if i == 0: 3778b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print "was", ALL_CERTS.Get(o) 3788b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 3798b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print " ", ALL_CERTS.Get(o) 3808b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for i, n in enumerate(new): 3818b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if i == 0: 3828b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print "now", ALL_CERTS.Get(n) 3838b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 3848b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print " ", ALL_CERTS.Get(n) 3858b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for i in sorted(packages): 3868b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert old_fn = other.apks[i].filename 3878b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert new_fn = self.apks[i].filename 3888b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if old_fn == new_fn: 3898b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print " %-*s [%s]" % (max_pkg_len, i, old_fn) 3908b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 3918b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print " %-*s [was: %s; now: %s]" % (max_pkg_len, i, 3928b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert old_fn, new_fn) 3938b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print 3948b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3958b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3968b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef main(argv): 3978b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def option_handler(o, a): 3988b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if o in ("-c", "--compare_with"): 3998b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.compare_with = a 4008b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif o in ("-l", "--local_cert_dirs"): 4018b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.local_cert_dirs = [i.strip() for i in a.split(",")] 4028b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif o in ("-t", "--text"): 4038b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.text = True 4048b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 4058b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return False 4068b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return True 4078b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4088b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert args = common.ParseOptions(argv, __doc__, 4098b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert extra_opts="c:l:t", 4108b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert extra_long_opts=["compare_with=", 4118b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "local_cert_dirs="], 4128b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert extra_option_handler=option_handler) 4138b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4148b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if len(args) != 1: 4158b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert common.Usage(__doc__) 4168b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert sys.exit(1) 4178b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4188b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert ALL_CERTS.FindLocalCerts() 4198b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4208b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Push("input target_files:") 4218b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert try: 4228b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_files = TargetFiles() 4238b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_files.LoadZipFile(args[0]) 4248b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert finally: 4258b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Pop() 4268b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4278b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert compare_files = None 4288b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.compare_with: 4298b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Push("comparison target_files:") 4308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert try: 4318b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert compare_files = TargetFiles() 4328b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert compare_files.LoadZipFile(OPTIONS.compare_with) 4338b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert finally: 4348b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Pop() 4358b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4368b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.text or not compare_files: 4378b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Banner("target files") 4388b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_files.PrintCerts() 4398b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_files.CheckSharedUids() 4408b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_files.CheckExternalSignatures() 4418b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if compare_files: 4428b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.text: 4438b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Banner("comparison files") 4448b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert compare_files.PrintCerts() 4458b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_files.CompareWith(compare_files) 4468b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4478b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if PROBLEMS: 4488b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print "%d problem(s) found:\n" % (len(PROBLEMS),) 4498b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for p in PROBLEMS: 4508b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print p 4518b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return 1 4528b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4538b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return 0 4548b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4558b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4568b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertif __name__ == '__main__': 4578b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert try: 4588b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert r = main(sys.argv[1:]) 4598b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert sys.exit(r) 4608b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert except common.ExternalError as e: 4618b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print 4628b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print " ERROR: %s" % (e,) 4638b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert print 4648b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert sys.exit(1) 465767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao finally: 466767543a6598a3aa92b023ca9d97e6a5c6fb526ecTao Bao common.Cleanup() 467