OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/python |
| 2 # Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 """ |
| 7 Given a path to a XXX.pem file, re-generates a CERTIFICATE. |
| 8 |
| 9 The .pem file is expected to contain comments that resemble: |
| 10 |
| 11 #-----BEGIN XXX----- |
| 12 <ascii-der values in here> |
| 13 #-----END XXX----- |
| 14 |
| 15 These are interpreted as substitutions to make inside of the Certificate |
| 16 template (v3_certificate_template.txt) |
| 17 """ |
| 18 |
| 19 import sys |
| 20 import os |
| 21 import re |
| 22 import base64 |
| 23 import subprocess |
| 24 |
| 25 |
| 26 def read_file_to_string(path): |
| 27 """Reads a file entirely to a string""" |
| 28 with open(path, 'r') as f: |
| 29 return f.read() |
| 30 |
| 31 |
| 32 def write_string_to_file(data, path): |
| 33 """Writes a string to a file""" |
| 34 print "Writing file %s ..." % (path) |
| 35 with open(path, "w") as f: |
| 36 f.write(data) |
| 37 |
| 38 |
| 39 def replace_string(original, start, end, replacement): |
| 40 """Replaces the specified range of |original| with |replacement|""" |
| 41 return original[0:start] + replacement + original[end:] |
| 42 |
| 43 |
| 44 def apply_substitution(template, name, value): |
| 45 """Finds a section named |name| in |template| and replaces it with |value|.""" |
| 46 # Find the section |name| in |template|. |
| 47 regex = re.compile(r'#-----BEGIN %s-----(.*?)#-----END %s-----' % |
| 48 (re.escape(name), re.escape(name)), re.DOTALL) |
| 49 m = regex.search(template) |
| 50 if not m: |
| 51 print "Couldn't find a section named %s in the template" % (name) |
| 52 sys.exit(1) |
| 53 |
| 54 return replace_string(template, m.start(1), m.end(1), value) |
| 55 |
| 56 |
| 57 def main(): |
| 58 if len(sys.argv) != 2: |
| 59 print 'Usage: %s <PATH_TO_PEM>' % (sys.argv[0]) |
| 60 sys.exit(1) |
| 61 |
| 62 pem_path = sys.argv[1] |
| 63 orig = read_file_to_string(pem_path) |
| 64 |
| 65 cert_ascii = read_file_to_string("v3_certificate_template.txt") |
| 66 |
| 67 # Apply all substitutions described by comments in |orig| |
| 68 regex = re.compile(r'#-----BEGIN ([\w ]+)-----(.*?)#-----END \1-----', |
| 69 re.DOTALL) |
| 70 num_matches = 0 |
| 71 for m in regex.finditer(orig): |
| 72 num_matches += 1 |
| 73 cert_ascii = apply_substitution(cert_ascii, m.group(1), m.group(2)) |
| 74 |
| 75 if num_matches == 0: |
| 76 print "Input did not contain any substitutions" |
| 77 sys.exit(1) |
| 78 |
| 79 # Convert the ascii-der to actual DER binary. |
| 80 cert_der = None |
| 81 try: |
| 82 p = subprocess.Popen(['ascii2der'], stdout=subprocess.PIPE, |
| 83 stdin=subprocess.PIPE, stderr=subprocess.STDOUT) |
| 84 cert_der = p.communicate(input=cert_ascii)[0] |
| 85 except OSError as e: |
| 86 print ('ERROR: Failed executing ascii2der.\n' |
| 87 'Make sure this is in your path\n' |
| 88 'Obtain it from https://github.com/google/der-ascii') |
| 89 sys.exit(1) |
| 90 |
| 91 # Replace the CERTIFICATE block with the newly generated one. |
| 92 regex = re.compile(r'-----BEGIN CERTIFICATE-----\n(.*?)\n' |
| 93 '-----END CERTIFICATE-----', re.DOTALL) |
| 94 m = regex.search(orig) |
| 95 if not m: |
| 96 print "ERROR: Cannot find CERTIFICATE block in input" |
| 97 sys.exit(1) |
| 98 modified = replace_string(orig, m.start(1), m.end(1), |
| 99 base64.b64encode(cert_der)) |
| 100 |
| 101 # Write back the .pem file. |
| 102 write_string_to_file(modified, pem_path) |
| 103 |
| 104 main() |
OLD | NEW |