check_target_files_signatures revision 278c9781ec5d2ef289fee635dfcfd8befcfe531b
175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker#!/usr/bin/env python 275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# 375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# Copyright (C) 2009 The Android Open Source Project 475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# 575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# Licensed under the Apache License, Version 2.0 (the "License"); 675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# you may not use this file except in compliance with the License. 775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# You may obtain a copy of the License at 875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# 975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# http://www.apache.org/licenses/LICENSE-2.0 1075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# 1175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# Unless required by applicable law or agreed to in writing, software 1275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# distributed under the License is distributed on an "AS IS" BASIS, 1375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# See the License for the specific language governing permissions and 1575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# limitations under the License. 1675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 1775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker""" 1875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug ZongkerCheck the signatures of all APKs in a target_files .zip file. With 1975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker-c, compare the signatures of each package to the ones in a separate 2075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkertarget_files (usually a previously distributed build for the same 2175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerdevice) and flag any changes. 2275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 2375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug ZongkerUsage: check_target_file_signatures [flags] target_files 2475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 2575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker -c (--compare_with) <other_target_files> 2675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker Look for compatibility problems between the two sets of target 2775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker files (eg., packages whose keys have changed). 2875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 2975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker -l (--local_cert_dirs) <dir,dir,...> 3075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker Comma-separated list of top-level directories to scan for 3175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker .x509.pem files. Defaults to "vendor,build". Where cert files 3275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker can be found that match APK signatures, the filename will be 3375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker printed as the cert name, otherwise a hash of the cert plus its 3475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker subject string will be printed instead. 3575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 3675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker -t (--text) 3775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker Dump the certificate information for both packages in comparison 3875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker mode (this output is normally suppressed). 3975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 4075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker""" 4175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 4275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerimport sys 4375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 4475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerif sys.hexversion < 0x02040000: 4575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print >> sys.stderr, "Python 2.4 or newer is required." 4675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker sys.exit(1) 4775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 4875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerimport os 4975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerimport re 5075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerimport shutil 5175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerimport subprocess 5275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerimport tempfile 5375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerimport zipfile 5475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 55cad0bb9f621ff1ccfb584e18249b09768c30a0c0davidtry: 56cad0bb9f621ff1ccfb584e18249b09768c30a0c0david from hashlib import sha1 as sha1 57cad0bb9f621ff1ccfb584e18249b09768c30a0c0davidexcept ImportError: 58cad0bb9f621ff1ccfb584e18249b09768c30a0c0david from sha import sha as sha1 59cad0bb9f621ff1ccfb584e18249b09768c30a0c0david 6075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerimport common 6175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 6275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# Work around a bug in python's zipfile module that prevents opening 6375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# of zipfiles if any entry has an extra field of between 1 and 3 bytes 6475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# (which is common with zipaligned APKs). This overrides the 6575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# ZipInfo._decodeExtra() method (which contains the bug) with an empty 6675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker# version (since we don't need to decode the extra field anyway). 6775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerclass MyZipInfo(zipfile.ZipInfo): 6875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker def _decodeExtra(self): 6975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker pass 7075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerzipfile.ZipInfo = MyZipInfo 7175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 7275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug ZongkerOPTIONS = common.OPTIONS 7375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 7475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug ZongkerOPTIONS.text = False 7575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug ZongkerOPTIONS.compare_with = None 7675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug ZongkerOPTIONS.local_cert_dirs = ("vendor", "build") 7775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 7875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug ZongkerPROBLEMS = [] 7975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug ZongkerPROBLEM_PREFIX = [] 8075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 8175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerdef AddProblem(msg): 8275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker PROBLEMS.append(" ".join(PROBLEM_PREFIX) + " " + msg) 8375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerdef Push(msg): 8475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker PROBLEM_PREFIX.append(msg) 8575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerdef Pop(): 8675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker PROBLEM_PREFIX.pop() 8775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 8875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 8975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerdef Banner(msg): 9075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print "-" * 70 9175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print " ", msg 9275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print "-" * 70 9375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 9475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 9575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerdef GetCertSubject(cert): 9675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker p = common.Run(["openssl", "x509", "-inform", "DER", "-text"], 9775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker stdin=subprocess.PIPE, 9875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker stdout=subprocess.PIPE) 9975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker out, err = p.communicate(cert) 10075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if err and not err.strip(): 10175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker return "(error reading cert subject)" 10275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for line in out.split("\n"): 10375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker line = line.strip() 10475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if line.startswith("Subject:"): 10575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker return line[8:].strip() 10675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker return "(unknown cert subject)" 10775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 10875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 10975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerclass CertDB(object): 11075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker def __init__(self): 11175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.certs = {} 11275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 11375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker def Add(self, cert, name=None): 11475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if cert in self.certs: 11575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if name: 11675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.certs[cert] = self.certs[cert] + "," + name 11775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker else: 11875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if name is None: 1196ae5381670a12f63b4f7a18166e0886898e2083bDoug Zongker name = "unknown cert %s (%s)" % (common.sha1(cert).hexdigest()[:12], 12075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker GetCertSubject(cert)) 12175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.certs[cert] = name 12275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 12375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker def Get(self, cert): 12475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker """Return the name for a given cert.""" 12575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker return self.certs.get(cert, None) 12675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 12775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker def FindLocalCerts(self): 12875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker to_load = [] 12975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for top in OPTIONS.local_cert_dirs: 13075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for dirpath, dirnames, filenames in os.walk(top): 13175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker certs = [os.path.join(dirpath, i) 13275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for i in filenames if i.endswith(".x509.pem")] 13375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if certs: 13475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker to_load.extend(certs) 13575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 13675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for i in to_load: 13775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker f = open(i) 13875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker cert = ParseCertificate(f.read()) 13975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker f.close() 14075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker name, _ = os.path.splitext(i) 14175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker name, _ = os.path.splitext(name) 14275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.Add(cert, name) 14375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 14475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug ZongkerALL_CERTS = CertDB() 14575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 14675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 14775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerdef ParseCertificate(data): 14875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker """Parse a PEM-format certificate.""" 14975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker cert = [] 15075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker save = False 15175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for line in data.split("\n"): 15275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if "--END CERTIFICATE--" in line: 15375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker break 15475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if save: 15575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker cert.append(line) 15675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if "--BEGIN CERTIFICATE--" in line: 15775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker save = True 15875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker cert = "".join(cert).decode('base64') 15975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker return cert 16075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 16175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 16275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerdef CertFromPKCS7(data, filename): 16375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker """Read the cert out of a PKCS#7-format file (which is what is 16475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker stored in a signed .apk).""" 16575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker Push(filename + ":") 16675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker try: 16775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker p = common.Run(["openssl", "pkcs7", 16875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker "-inform", "DER", 16975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker "-outform", "PEM", 17075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker "-print_certs"], 17175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker stdin=subprocess.PIPE, 17275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker stdout=subprocess.PIPE) 17375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker out, err = p.communicate(data) 17475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if err and not err.strip(): 17575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker AddProblem("error reading cert:\n" + err) 17675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker return None 17775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 17875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker cert = ParseCertificate(out) 17975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if not cert: 18075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker AddProblem("error parsing cert output") 18175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker return None 18275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker return cert 18375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker finally: 18475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker Pop() 18575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 18675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 18775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerclass APK(object): 18875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker def __init__(self, full_filename, filename): 18975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.filename = filename 190b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker self.certs = set() 19175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker Push(filename+":") 19275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker try: 19375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.RecordCert(full_filename) 19475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.ReadManifest(full_filename) 19575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker finally: 19675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker Pop() 19775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 19875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker def RecordCert(self, full_filename): 19975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker try: 20075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker f = open(full_filename) 20175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker apk = zipfile.ZipFile(f, "r") 20275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker pkcs7 = None 20375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for info in apk.infolist(): 20475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if info.filename.startswith("META-INF/") and \ 20575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker (info.filename.endswith(".DSA") or info.filename.endswith(".RSA")): 20675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker pkcs7 = apk.read(info.filename) 207b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker cert = CertFromPKCS7(pkcs7, info.filename) 208b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker self.certs.add(cert) 209b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker ALL_CERTS.Add(cert) 21075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if not pkcs7: 21175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker AddProblem("no signature") 21275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker finally: 21375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker f.close() 21475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 21575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker def ReadManifest(self, full_filename): 21675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker p = common.Run(["aapt", "dump", "xmltree", full_filename, 21775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker "AndroidManifest.xml"], 21875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker stdout=subprocess.PIPE) 21975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker manifest, err = p.communicate() 22075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if err: 22175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker AddProblem("failed to read manifest") 22275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker return 22375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 22475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.shared_uid = None 22575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.package = None 22675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 22775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for line in manifest.split("\n"): 22875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker line = line.strip() 22975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker m = re.search('A: (\S*?)(?:\(0x[0-9a-f]+\))?="(.*?)" \(Raw', line) 23075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if m: 23175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker name = m.group(1) 23275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if name == "android:sharedUserId": 23375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if self.shared_uid is not None: 23475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker AddProblem("multiple sharedUserId declarations") 23575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.shared_uid = m.group(2) 23675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker elif name == "package": 23775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if self.package is not None: 23875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker AddProblem("multiple package declarations") 23975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.package = m.group(2) 24075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 24175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if self.package is None: 24275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker AddProblem("no package declaration") 24375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 24475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 24575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerclass TargetFiles(object): 24675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker def __init__(self): 24775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.max_pkg_len = 30 24875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.max_fn_len = 20 24975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 25075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker def LoadZipFile(self, filename): 2516ae5381670a12f63b4f7a18166e0886898e2083bDoug Zongker d, z = common.UnzipTemp(filename, '*.apk') 25275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker try: 25375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.apks = {} 254f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker self.apks_by_basename = {} 25575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for dirpath, dirnames, filenames in os.walk(d): 25675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for fn in filenames: 25775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if fn.endswith(".apk"): 25875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker fullname = os.path.join(dirpath, fn) 25975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker displayname = fullname[len(d)+1:] 26075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker apk = APK(fullname, displayname) 26175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.apks[apk.package] = apk 262f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker self.apks_by_basename[os.path.basename(apk.filename)] = apk 26375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 26475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.max_pkg_len = max(self.max_pkg_len, len(apk.package)) 26575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.max_fn_len = max(self.max_fn_len, len(apk.filename)) 26675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker finally: 26775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker shutil.rmtree(d) 26875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 269f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker self.certmap = common.ReadApkCerts(z) 270f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker z.close() 271f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker 27275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker def CheckSharedUids(self): 27375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker """Look for any instances where packages signed with different 27475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker certs request the same sharedUserId.""" 27575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker apks_by_uid = {} 27675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for apk in self.apks.itervalues(): 27775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if apk.shared_uid: 27875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker apks_by_uid.setdefault(apk.shared_uid, []).append(apk) 27975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 28075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for uid in sorted(apks_by_uid.keys()): 28175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker apks = apks_by_uid[uid] 28275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for apk in apks[1:]: 283b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker if apk.certs != apks[0].certs: 28475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker break 28575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker else: 286b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker # all packages have the same set of certs; this uid is fine. 28775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker continue 28875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 289b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker AddProblem("different cert sets for packages with uid %s" % (uid,)) 290b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker 291b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker print "uid %s is shared by packages with different cert sets:" % (uid,) 292b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker for apk in apks: 293b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker print "%-*s [%s]" % (self.max_pkg_len, apk.package, apk.filename) 294b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker for cert in apk.certs: 295b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker print " ", ALL_CERTS.Get(cert) 29675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print 29775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 298f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker def CheckExternalSignatures(self): 299f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker for apk_filename, certname in self.certmap.iteritems(): 300f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker if certname == "EXTERNAL": 301f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker # Apps marked EXTERNAL should be signed with the test key 302f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker # during development, then manually re-signed after 303f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker # predexopting. Consider it an error if this app is now 304f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker # signed with any key that is present in our tree. 305f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker apk = self.apks_by_basename[apk_filename] 306f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker name = ALL_CERTS.Get(apk.cert) 307f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker if not name.startswith("unknown "): 308f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker Push(apk.filename) 309f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker AddProblem("hasn't been signed with EXTERNAL cert") 310f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker Pop() 311f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker 31275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker def PrintCerts(self): 31375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker """Display a table of packages grouped by cert.""" 31475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker by_cert = {} 31575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for apk in self.apks.itervalues(): 316b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker for cert in apk.certs: 317b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker by_cert.setdefault(cert, []).append((apk.package, apk)) 31875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 31975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker order = [(-len(v), k) for (k, v) in by_cert.iteritems()] 32075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker order.sort() 32175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 32275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for _, cert in order: 32375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print "%s:" % (ALL_CERTS.Get(cert),) 32475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker apks = by_cert[cert] 32575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker apks.sort() 32675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for _, apk in apks: 32775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if apk.shared_uid: 32875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print " %-*s %-*s [%s]" % (self.max_fn_len, apk.filename, 32975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.max_pkg_len, apk.package, 33075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker apk.shared_uid) 33175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker else: 33275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print " %-*s %-*s" % (self.max_fn_len, apk.filename, 33375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self.max_pkg_len, apk.package) 33475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print 33575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 33675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker def CompareWith(self, other): 33775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker """Look for instances where a given package that exists in both 33875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker self and other have different certs.""" 33975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 34075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker all = set(self.apks.keys()) 34175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker all.update(other.apks.keys()) 34275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 34375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker max_pkg_len = max(self.max_pkg_len, other.max_pkg_len) 34475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 34575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker by_certpair = {} 34675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 34775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for i in all: 34875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if i in self.apks: 34975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if i in other.apks: 350278c9781ec5d2ef289fee635dfcfd8befcfe531bDoug Zongker # in both; should have same set of certs 351278c9781ec5d2ef289fee635dfcfd8befcfe531bDoug Zongker if self.apks[i].certs != other.apks[i].certs: 352b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker by_certpair.setdefault((other.apks[i].certs, 353b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker self.apks[i].certs), []).append(i) 35475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker else: 35575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print "%s [%s]: new APK (not in comparison target_files)" % ( 35675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker i, self.apks[i].filename) 35775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker else: 35875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if i in other.apks: 35975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print "%s [%s]: removed APK (only in comparison target_files)" % ( 36075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker i, other.apks[i].filename) 36175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 36275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if by_certpair: 36375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker AddProblem("some APKs changed certs") 36475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker Banner("APK signing differences") 36575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for (old, new), packages in sorted(by_certpair.items()): 366b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker for i, o in enumerate(old): 367b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker if i == 0: 368b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker print "was", ALL_CERTS.Get(o) 369b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker else: 370b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker print " ", ALL_CERTS.Get(o) 371b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker for i, n in enumerate(new): 372b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker if i == 0: 373b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker print "now", ALL_CERTS.Get(n) 374b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker else: 375b40a58e4b3cdb6dd528c9b3f23890ef008732a89Doug Zongker print " ", ALL_CERTS.Get(n) 37675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for i in sorted(packages): 37775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker old_fn = other.apks[i].filename 37875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker new_fn = self.apks[i].filename 37975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if old_fn == new_fn: 38075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print " %-*s [%s]" % (max_pkg_len, i, old_fn) 38175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker else: 38275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print " %-*s [was: %s; now: %s]" % (max_pkg_len, i, 38375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker old_fn, new_fn) 38475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print 38575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 38675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 38775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerdef main(argv): 38875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker def option_handler(o, a): 38975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if o in ("-c", "--compare_with"): 39075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker OPTIONS.compare_with = a 39175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker elif o in ("-l", "--local_cert_dirs"): 39275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker OPTIONS.local_cert_dirs = [i.strip() for i in a.split(",")] 39375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker elif o in ("-t", "--text"): 39475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker OPTIONS.text = True 39575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker else: 39675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker return False 39775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker return True 39875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 39975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker args = common.ParseOptions(argv, __doc__, 40075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker extra_opts="c:l:t", 40175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker extra_long_opts=["compare_with=", 40275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker "local_cert_dirs="], 40375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker extra_option_handler=option_handler) 40475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 40575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if len(args) != 1: 40675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker common.Usage(__doc__) 40775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker sys.exit(1) 40875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 40975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker ALL_CERTS.FindLocalCerts() 41075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 41175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker Push("input target_files:") 41275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker try: 41375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker target_files = TargetFiles() 41475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker target_files.LoadZipFile(args[0]) 41575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker finally: 41675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker Pop() 41775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 41875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker compare_files = None 41975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if OPTIONS.compare_with: 42075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker Push("comparison target_files:") 42175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker try: 42275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker compare_files = TargetFiles() 42375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker compare_files.LoadZipFile(OPTIONS.compare_with) 42475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker finally: 42575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker Pop() 42675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 42775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if OPTIONS.text or not compare_files: 42875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker Banner("target files") 42975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker target_files.PrintCerts() 43075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker target_files.CheckSharedUids() 431f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker target_files.CheckExternalSignatures() 43275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if compare_files: 43375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if OPTIONS.text: 43475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker Banner("comparison files") 43575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker compare_files.PrintCerts() 43675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker target_files.CompareWith(compare_files) 43775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 43875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker if PROBLEMS: 43975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print "%d problem(s) found:\n" % (len(PROBLEMS),) 44075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker for p in PROBLEMS: 44175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print p 44275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker return 1 44375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 44475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker return 0 44575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 44675f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker 44775f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongkerif __name__ == '__main__': 44875f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker try: 44975f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker r = main(sys.argv[1:]) 45075f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker sys.exit(r) 45175f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker except common.ExternalError, e: 45275f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print 45375f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print " ERROR: %s" % (e,) 45475f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker print 45575f1736469d6ebfb51f7d2abfa74039d9be54d8dDoug Zongker sys.exit(1) 456