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 <asci-der values in here> | |
mattm
2016/09/22 02:48:19
ascii
eroman
2016/09/22 06:13:14
Done.
| |
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 """Find 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 (name, name), re.DOTALL) | |
mattm
2016/09/22 02:48:19
Shouldn't matter given the types of names being us
eroman
2016/09/22 06:13:14
Done.
| |
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: | |
mattm
2016/09/22 02:48:20
extra space
eroman
2016/09/22 06:13:14
Done.
| |
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 |