1edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra#!/usr/bin/env python 2edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 3edf7b4c861144764d0bc17436064d52e7147f916Geremy Condrafrom xml.sax import saxutils, handler, make_parser 4edf7b4c861144764d0bc17436064d52e7147f916Geremy Condrafrom optparse import OptionParser 5edf7b4c861144764d0bc17436064d52e7147f916Geremy Condraimport ConfigParser 6edf7b4c861144764d0bc17436064d52e7147f916Geremy Condraimport logging 7edf7b4c861144764d0bc17436064d52e7147f916Geremy Condraimport base64 8edf7b4c861144764d0bc17436064d52e7147f916Geremy Condraimport sys 9edf7b4c861144764d0bc17436064d52e7147f916Geremy Condraimport os 10edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 11edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra__VERSION = (0, 1) 12edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 13edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra''' 14edf7b4c861144764d0bc17436064d52e7147f916Geremy CondraThis tool reads a mac_permissions.xml and replaces keywords in the signature 15edf7b4c861144764d0bc17436064d52e7147f916Geremy Condraclause with keys provided by pem files. 16edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra''' 17edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 18edf7b4c861144764d0bc17436064d52e7147f916Geremy Condraclass GenerateKeys(object): 19edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra def __init__(self, path): 20edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra ''' 21edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra Generates an object with Base16 and Base64 encoded versions of the keys 22edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra found in the supplied pem file argument. PEM files can contain multiple 23edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra certs, however this seems to be unused in Android as pkg manager grabs 24edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra the first cert in the APK. This will however support multiple certs in 25edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra the resulting generation with index[0] being the first cert in the pem 26edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra file. 27edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra ''' 28edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 29edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra self._base64Key = list() 30edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra self._base16Key = list() 31edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 32edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra if not os.path.isfile(path): 33edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra sys.exit("Path " + path + " does not exist or is not a file!") 34edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 35edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra pkFile = open(path, 'rb').readlines() 36edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra base64Key = "" 371ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts lineNo = 1 381ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts certNo = 1 39edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra inCert = False 40edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra for line in pkFile: 411ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts line = line.strip() 421ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts # Are we starting the certificate? 4314138335bd3c7204d5bff4690ffa2314dd4a0a9eWilliam Roberts if line == "-----BEGIN CERTIFICATE-----": 441ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts if inCert: 451ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts sys.exit("Encountered another BEGIN CERTIFICATE without END CERTIFICATE on " + 461ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts "line: " + str(lineNo)) 471ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts 481ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts inCert = True 491ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts 501ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts # Are we ending the ceritifcate? 5114138335bd3c7204d5bff4690ffa2314dd4a0a9eWilliam Roberts elif line == "-----END CERTIFICATE-----": 521ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts if not inCert: 531ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts sys.exit("Encountered END CERTIFICATE before BEGIN CERTIFICATE on line: " 541ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts + str(lineNo)) 551ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts 561ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts # If we ended the certificate trip the flag 571ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts inCert = False 581ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts 591ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts # Sanity check the input 601ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts if len(base64Key) == 0: 611ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts sys.exit("Empty certficate , certificate "+ str(certNo) + " found in file: " 621ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts + path) 631ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts 641ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts # ... and append the certificate to the list 651ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts # Base 64 includes uppercase. DO NOT tolower() 661ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts self._base64Key.append(base64Key) 671ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts try: 681ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts # Pkgmanager and setool see hex strings with lowercase, lets be consistent 691ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts self._base16Key.append(base64.b16encode(base64.b64decode(base64Key)).lower()) 701ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts except TypeError: 711ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts sys.exit("Invalid certificate, certificate "+ str(certNo) + " found in file: " 721ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts + path) 731ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts 741ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts # After adding the key, reset the accumulator as pem files may have subsequent keys 751ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts base64Key="" 761ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts 771ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts # And increment your cert number 781ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts certNo = certNo + 1 791ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts 801ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts # If we haven't started the certificate, then we should not encounter any data 811ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts elif not inCert: 82070c01f8f133dfc0da82beca6f747b679d27f904Mike Palmiotto if line is not "": 83070c01f8f133dfc0da82beca6f747b679d27f904Mike Palmiotto sys.exit("Detected erroneous line \""+ line + "\" on " + str(lineNo) 841ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts + " in pem file: " + path) 851ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts 861ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts # else we have started the certicate and need to append the data 871ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts elif inCert: 881ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts base64Key += line 891ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts 901ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts else: 911ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts # We should never hit this assert, if we do then an unaccounted for state 921ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts # was entered that was NOT addressed by the if/elif statements above 931ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts assert(False == True) 941ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts 951ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts # The last thing to do before looping up is to increment line number 961ecb4e8ad15a44347e0a2460c204d819e4ebd269William Roberts lineNo = lineNo + 1 97edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 98edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra def __len__(self): 99edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra return len(self._base16Key) 100edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 101edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra def __str__(self): 102edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra return str(self.getBase16Keys()) 103edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 104edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra def getBase16Keys(self): 105edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra return self._base16Key 106edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 107edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra def getBase64Keys(self): 108edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra return self._base64Key 109edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 110edf7b4c861144764d0bc17436064d52e7147f916Geremy Condraclass ParseConfig(ConfigParser.ConfigParser): 111edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 112edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra # This must be lowercase 113edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra OPTION_WILDCARD_TAG = "all" 114edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 115020b5ff6311044ef7a2200dd4db69f5cccf46213Geremy Condra def generateKeyMap(self, target_build_variant, key_directory): 116edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 117edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra keyMap = dict() 118edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 119edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra for tag in self.sections(): 120edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 121edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra options = self.options(tag) 122edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 123edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra for option in options: 124edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 125edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra # Only generate the key map for debug or release, 126edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra # not both! 127edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra if option != target_build_variant and \ 128edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra option != ParseConfig.OPTION_WILDCARD_TAG: 129edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra logging.info("Skipping " + tag + " : " + option + 130edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra " because target build variant is set to " + 131edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra str(target_build_variant)) 132edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra continue 133edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 134edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra if tag in keyMap: 135edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra sys.exit("Duplicate tag detected " + tag) 136edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 1371b46b2fe4723b0dda74c2f66a09df8259508fd4bRichard Haines tag_path = os.path.expandvars(self.get(tag, option)) 1381b46b2fe4723b0dda74c2f66a09df8259508fd4bRichard Haines path = os.path.join(key_directory, tag_path) 139edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 140edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra keyMap[tag] = GenerateKeys(path) 141edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 142edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra # Multiple certificates may exist in 143edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra # the pem file. GenerateKeys supports 144edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra # this however, the mac_permissions.xml 145edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra # as well as PMS do not. 146edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra assert len(keyMap[tag]) == 1 147edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 148edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra return keyMap 149edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 150edf7b4c861144764d0bc17436064d52e7147f916Geremy Condraclass ReplaceTags(handler.ContentHandler): 151edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 152edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra DEFAULT_TAG = "default" 153edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra PACKAGE_TAG = "package" 154edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra POLICY_TAG = "policy" 155edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra SIGNER_TAG = "signer" 156edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra SIGNATURE_TAG = "signature" 157edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 158edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra TAGS_WITH_CHILDREN = [ DEFAULT_TAG, PACKAGE_TAG, POLICY_TAG, SIGNER_TAG ] 159edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 160edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra XML_ENCODING_TAG = '<?xml version="1.0" encoding="iso-8859-1"?>' 161edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 162edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra def __init__(self, keyMap, out=sys.stdout): 163edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 164edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra handler.ContentHandler.__init__(self) 165edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra self._keyMap = keyMap 166edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra self._out = out 167edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra self._out.write(ReplaceTags.XML_ENCODING_TAG) 168edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra self._out.write("<!-- AUTOGENERATED FILE DO NOT MODIFY -->") 1697f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig self._out.write("<policy>") 1707f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig 1717f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig def __del__(self): 1727f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig self._out.write("</policy>") 173edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 174edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra def startElement(self, tag, attrs): 1757f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig if tag == ReplaceTags.POLICY_TAG: 1767f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig return 177edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 178edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra self._out.write('<' + tag) 179edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 180edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra for (name, value) in attrs.items(): 181edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 182edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra if name == ReplaceTags.SIGNATURE_TAG and value in self._keyMap: 183edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra for key in self._keyMap[value].getBase16Keys(): 184edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra logging.info("Replacing " + name + " " + value + " with " + key) 185edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra self._out.write(' %s="%s"' % (name, saxutils.escape(key))) 186edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra else: 187edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra self._out.write(' %s="%s"' % (name, saxutils.escape(value))) 188edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 189edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra if tag in ReplaceTags.TAGS_WITH_CHILDREN: 190edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra self._out.write('>') 191edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra else: 192edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra self._out.write('/>') 193edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 194edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra def endElement(self, tag): 1957f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig if tag == ReplaceTags.POLICY_TAG: 1967f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig return 1977f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig 198edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra if tag in ReplaceTags.TAGS_WITH_CHILDREN: 199edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra self._out.write('</%s>' % tag) 200edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 201edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra def characters(self, content): 202edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra if not content.isspace(): 203edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra self._out.write(saxutils.escape(content)) 204edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 205edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra def ignorableWhitespace(self, content): 206edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra pass 207edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 208edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra def processingInstruction(self, target, data): 209edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra self._out.write('<?%s %s?>' % (target, data)) 210edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 211edf7b4c861144764d0bc17436064d52e7147f916Geremy Condraif __name__ == "__main__": 212edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 213edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra # Intentional double space to line up equls signs and opening " for 214edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra # readability. 2157f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig usage = "usage: %prog [options] CONFIG_FILE MAC_PERMISSIONS_FILE [MAC_PERMISSIONS_FILE...]\n" 2167f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig usage += "This tool allows one to configure an automatic inclusion\n" 2177f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig usage += "of signing keys into the mac_permision.xml file(s) from the\n" 2187f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig usage += "pem files. If mulitple mac_permision.xml files are included\n" 2197f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig usage += "then they are unioned to produce a final version." 220edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 221edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra version = "%prog " + str(__VERSION) 222edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 223edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra parser = OptionParser(usage=usage, version=version) 224edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 225edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra parser.add_option("-v", "--verbose", 226edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra action="store_true", dest="verbose", default=False, 227edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra help="Print internal operations to stdout") 228edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 229edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra parser.add_option("-o", "--output", default="stdout", dest="output_file", 230edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra metavar="FILE", help="Specify an output file, default is stdout") 231edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 232edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra parser.add_option("-c", "--cwd", default=os.getcwd(), dest="root", 233edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra metavar="DIR", help="Specify a root (CWD) directory to run this from, it" \ 234edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra "chdirs' AFTER loading the config file") 235edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 236edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra parser.add_option("-t", "--target-build-variant", default="eng", dest="target_build_variant", 237edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra help="Specify the TARGET_BUILD_VARIANT, defaults to eng") 238edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 239020b5ff6311044ef7a2200dd4db69f5cccf46213Geremy Condra parser.add_option("-d", "--key-directory", default="", dest="key_directory", 240020b5ff6311044ef7a2200dd4db69f5cccf46213Geremy Condra help="Specify a parent directory for keys") 241020b5ff6311044ef7a2200dd4db69f5cccf46213Geremy Condra 242edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra (options, args) = parser.parse_args() 243edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 2447f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig if len(args) < 2: 2457f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig parser.error("Must specify a config file (keys.conf) AND mac_permissions.xml file(s)!") 246edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 247edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra logging.basicConfig(level=logging.INFO if options.verbose == True else logging.WARN) 248edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 249edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra # Read the config file 250edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra config = ParseConfig() 251edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra config.read(args[0]) 252edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 253edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra os.chdir(options.root) 254edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 255edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra output_file = sys.stdout if options.output_file == "stdout" else open(options.output_file, "w") 256edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra logging.info("Setting output file to: " + options.output_file) 257edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra 258edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra # Generate the key list 259020b5ff6311044ef7a2200dd4db69f5cccf46213Geremy Condra key_map = config.generateKeyMap(options.target_build_variant.lower(), options.key_directory) 260edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra logging.info("Generate key map:") 261edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra for k in key_map: 262edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra logging.info(k + " : " + str(key_map[k])) 263edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra # Generate the XML file with markup replaced with keys 264edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra parser = make_parser() 265edf7b4c861144764d0bc17436064d52e7147f916Geremy Condra parser.setContentHandler(ReplaceTags(key_map, output_file)) 2667f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig for f in args[1:]: 2677f2392eeb03eeb88f2699061f4adaeb1fcbd1de2Robert Craig parser.parse(f) 268