Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / net / data / verify_name_match_unittest / scripts / generate-names.py
blobc49a4321a13f01e07886c313254a1a91fc6798a8
1 #!/usr/bin/env python
2 # Copyright 2015 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.
6 import base64
7 import copy
8 import os
9 import subprocess
10 import tempfile
13 class RDN:
14 def __init__(self):
15 self.attrs = []
17 def add_attr(self, attr_type, attr_value_type, attr_value,
18 attr_modifier=None):
19 self.attrs.append((attr_type, attr_value_type, attr_value, attr_modifier))
20 return self
22 def __str__(self):
23 s = ''
24 for n, attr in enumerate(self.attrs):
25 s += 'attrTypeAndValue%i=SEQUENCE:attrTypeAndValueSequence%i_%i\n' % (
26 n, id(self), n)
28 s += '\n'
29 for n, attr in enumerate(self.attrs):
30 attr_type, attr_value_type, attr_value, attr_modifier = attr
31 s += '[attrTypeAndValueSequence%i_%i]\n' % (id(self), n)
32 # Note the quotes around the string value here, which is necessary for
33 # trailing whitespace to be included by openssl.
34 s += 'type=OID:%s\n' % attr_type
35 s += 'value='
36 if attr_modifier:
37 s += attr_modifier + ','
38 s += '%s:"%s"\n' % (attr_value_type, attr_value)
40 return s
43 class NameGenerator:
44 def __init__(self):
45 self.rdns = []
47 def add_rdn(self):
48 rdn = RDN()
49 self.rdns.append(rdn)
50 return rdn
52 def __str__(self):
53 s = 'asn1 = SEQUENCE:rdnSequence\n\n[rdnSequence]\n'
54 for n, rdn in enumerate(self.rdns):
55 s += 'rdn%i = SET:rdnSet%i\n' % (n, n)
57 s += '\n'
59 for n, rdn in enumerate(self.rdns):
60 s += '[rdnSet%i]\n%s\n' % (n, rdn)
62 return s
65 def generate(s, fn):
66 out_fn = os.path.join('..', 'names', fn + '.pem')
67 conf_tempfile = tempfile.NamedTemporaryFile()
68 conf_tempfile.write(str(s))
69 conf_tempfile.flush()
70 der_tmpfile = tempfile.NamedTemporaryFile()
71 description_tmpfile = tempfile.NamedTemporaryFile()
72 subprocess.check_call(['openssl', 'asn1parse', '-genconf', conf_tempfile.name,
73 '-i', '-out', der_tmpfile.name],
74 stdout=description_tmpfile)
75 conf_tempfile.close()
77 output_file = open(out_fn, 'w')
78 description_tmpfile.seek(0)
79 output_file.write(description_tmpfile.read())
80 output_file.write('-----BEGIN NAME-----\n')
81 output_file.write(base64.encodestring(der_tmpfile.read()))
82 output_file.write('-----END NAME-----\n')
83 output_file.close()
86 def unmangled(s):
87 return s
90 def extra_whitespace(s):
91 return ' ' + s.replace(' ', ' ') + ' '
94 def case_swap(s):
95 return s.swapcase()
98 def main():
99 for valuetype in ('PRINTABLESTRING', 'T61STRING', 'UTF8', 'BMPSTRING',
100 'UNIVERSALSTRING'):
101 for string_mangler in (unmangled, extra_whitespace, case_swap):
102 n=NameGenerator()
103 n.add_rdn().add_attr('countryName', 'PRINTABLESTRING', 'US')
104 n.add_rdn().add_attr('stateOrProvinceName',
105 valuetype,
106 string_mangler('New York'))
107 n.add_rdn().add_attr('localityName',
108 valuetype,
109 string_mangler("ABCDEFGHIJKLMNOPQRSTUVWXYZ "
110 "abcdefghijklmnopqrstuvwxyz "
111 "0123456789 '()+,-./:=?"))
113 n_extra_attr = copy.deepcopy(n)
114 n_extra_attr.rdns[-1].add_attr('organizationName',
115 valuetype,
116 string_mangler('Name of company'))
118 n_dupe_attr = copy.deepcopy(n)
119 n_dupe_attr.rdns[-1].add_attr(*n_dupe_attr.rdns[-1].attrs[-1])
121 n_extra_rdn = copy.deepcopy(n)
122 n_extra_rdn.add_rdn().add_attr('organizationName',
123 valuetype,
124 string_mangler('Name of company'))
126 filename_base = 'ascii-' + valuetype + '-' + string_mangler.__name__
128 generate(n, filename_base)
129 generate(n_extra_attr, filename_base + '-extra_attr')
130 generate(n_dupe_attr, filename_base + '-dupe_attr')
131 generate(n_extra_rdn, filename_base + '-extra_rdn')
133 for valuetype in ('UTF8', 'BMPSTRING', 'UNIVERSALSTRING'):
134 n=NameGenerator()
135 n.add_rdn().add_attr('countryName', 'PRINTABLESTRING', 'JP')
136 n.add_rdn().add_attr('localityName',
137 valuetype,
138 "\xe6\x9d\xb1\xe4\xba\xac",
139 "FORMAT:UTF8")
141 filename_base = 'unicode_bmp-' + valuetype + '-' + 'unmangled'
142 generate(n, filename_base)
144 for valuetype in ('UTF8', 'UNIVERSALSTRING'):
145 n=NameGenerator()
146 n.add_rdn().add_attr('countryName', 'PRINTABLESTRING', 'JP')
147 n.add_rdn().add_attr('localityName',
148 valuetype,
149 "\xf0\x9d\x90\x80\xf0\x9d\x90\x99",
150 "FORMAT:UTF8")
152 filename_base = 'unicode_supplementary-' + valuetype + '-' + 'unmangled'
153 generate(n, filename_base)
155 generate("""asn1 = SEQUENCE:rdnSequence
156 [rdnSequence]
157 rdn0 = SET:rdnSet0
158 [rdnSet0]
159 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
160 [attrTypeAndValueSequence0_0]
161 type=OID:countryName
162 value=PRINTABLESTRING:"US"
163 extra=PRINTABLESTRING:"hello world"
164 """, "invalid-AttributeTypeAndValue-extradata")
166 generate("""asn1 = SEQUENCE:rdnSequence
167 [rdnSequence]
168 rdn0 = SET:rdnSet0
169 [rdnSet0]
170 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
171 [attrTypeAndValueSequence0_0]
172 type=OID:countryName
173 """, "invalid-AttributeTypeAndValue-onlyOneElement")
175 generate("""asn1 = SEQUENCE:rdnSequence
176 [rdnSequence]
177 rdn0 = SET:rdnSet0
178 [rdnSet0]
179 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
180 [attrTypeAndValueSequence0_0]
181 """, "invalid-AttributeTypeAndValue-empty")
183 generate("""asn1 = SEQUENCE:rdnSequence
184 [rdnSequence]
185 rdn0 = SET:rdnSet0
186 [rdnSet0]
187 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
188 [attrTypeAndValueSequence0_0]
189 type=PRINTABLESTRING:"hello world"
190 value=PRINTABLESTRING:"US"
191 """, "invalid-AttributeTypeAndValue-badAttributeType")
193 generate("""asn1 = SEQUENCE:rdnSequence
194 [rdnSequence]
195 rdn0 = SET:rdnSet0
196 [rdnSet0]
197 attrTypeAndValue0=SET:attrTypeAndValueSequence0_0
198 [attrTypeAndValueSequence0_0]
199 type=OID:countryName
200 value=PRINTABLESTRING:"US"
201 """, "invalid-AttributeTypeAndValue-setNotSequence")
203 generate("""asn1 = SEQUENCE:rdnSequence
204 [rdnSequence]
205 rdn0 = SEQUENCE:rdnSet0
206 [rdnSet0]
207 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
208 [attrTypeAndValueSequence0_0]
209 type=OID:countryName
210 value=PRINTABLESTRING:"US"
211 """, "invalid-RDN-sequenceInsteadOfSet")
213 generate("""asn1 = SEQUENCE:rdnSequence
214 [rdnSequence]
215 rdn0 = SET:rdnSet0
216 [rdnSet0]
217 """, "invalid-RDN-empty")
219 generate("""asn1 = SET:rdnSequence
220 [rdnSequence]
221 rdn0 = SET:rdnSet0
222 [rdnSet0]
223 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
224 [attrTypeAndValueSequence0_0]
225 type=OID:countryName
226 value=PRINTABLESTRING:"US"
227 """, "invalid-Name-setInsteadOfSequence")
229 generate("""asn1 = SEQUENCE:rdnSequence
230 [rdnSequence]
231 """, "valid-Name-empty")
233 # Certs with a RDN that is sorted differently due to length of the values, but
234 # which should compare equal when normalized.
235 generate("""asn1 = SEQUENCE:rdnSequence
236 [rdnSequence]
237 rdn0 = SET:rdnSet0
238 [rdnSet0]
239 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
240 attrTypeAndValue1=SEQUENCE:attrTypeAndValueSequence0_1
241 [attrTypeAndValueSequence0_0]
242 type=OID:stateOrProvinceName
243 value=PRINTABLESTRING:" state"
244 [attrTypeAndValueSequence0_1]
245 type=OID:localityName
246 value=PRINTABLESTRING:"locality"
247 """, "ascii-PRINTABLESTRING-rdn_sorting_1")
249 generate("""asn1 = SEQUENCE:rdnSequence
250 [rdnSequence]
251 rdn0 = SET:rdnSet0
252 [rdnSet0]
253 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
254 attrTypeAndValue1=SEQUENCE:attrTypeAndValueSequence0_1
255 [attrTypeAndValueSequence0_0]
256 type=OID:stateOrProvinceName
257 value=PRINTABLESTRING:"state"
258 [attrTypeAndValueSequence0_1]
259 type=OID:localityName
260 value=PRINTABLESTRING:" locality"
261 """, "ascii-PRINTABLESTRING-rdn_sorting_2")
263 # Certs with a RDN that is sorted differently due to length of the values, and
264 # also contains multiple values with the same type.
265 generate("""asn1 = SEQUENCE:rdnSequence
266 [rdnSequence]
267 rdn0 = SET:rdnSet0
268 [rdnSet0]
269 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
270 attrTypeAndValue1=SEQUENCE:attrTypeAndValueSequence0_1
271 attrTypeAndValue2=SEQUENCE:attrTypeAndValueSequence0_2
272 attrTypeAndValue3=SEQUENCE:attrTypeAndValueSequence0_3
273 attrTypeAndValue4=SEQUENCE:attrTypeAndValueSequence0_4
274 [attrTypeAndValueSequence0_0]
275 type=OID:domainComponent
276 value=IA5STRING:" cOm"
277 [attrTypeAndValueSequence0_1]
278 type=OID:domainComponent
279 value=IA5STRING:"eXaMple"
280 [attrTypeAndValueSequence0_2]
281 type=OID:domainComponent
282 value=IA5STRING:"wWw"
283 [attrTypeAndValueSequence0_3]
284 type=OID:localityName
285 value=PRINTABLESTRING:"NEw"
286 [attrTypeAndValueSequence0_4]
287 type=OID:localityName
288 value=PRINTABLESTRING:" yORk "
289 """, "ascii-mixed-rdn_dupetype_sorting_1")
291 generate("""asn1 = SEQUENCE:rdnSequence
292 [rdnSequence]
293 rdn0 = SET:rdnSet0
294 [rdnSet0]
295 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
296 attrTypeAndValue1=SEQUENCE:attrTypeAndValueSequence0_1
297 attrTypeAndValue2=SEQUENCE:attrTypeAndValueSequence0_2
298 attrTypeAndValue3=SEQUENCE:attrTypeAndValueSequence0_3
299 attrTypeAndValue4=SEQUENCE:attrTypeAndValueSequence0_4
300 [attrTypeAndValueSequence0_0]
301 type=OID:domainComponent
302 value=IA5STRING:"cOM"
303 [attrTypeAndValueSequence0_1]
304 type=OID:domainComponent
305 value=IA5STRING:"eXampLE"
306 [attrTypeAndValueSequence0_2]
307 type=OID:domainComponent
308 value=IA5STRING:" Www "
309 [attrTypeAndValueSequence0_3]
310 type=OID:localityName
311 value=PRINTABLESTRING:" nEw "
312 [attrTypeAndValueSequence0_4]
313 type=OID:localityName
314 value=PRINTABLESTRING:"yoRK"
315 """, "ascii-mixed-rdn_dupetype_sorting_2")
317 # Minimal valid config. Copy and modify this one when generating new invalid
318 # configs.
319 generate("""asn1 = SEQUENCE:rdnSequence
320 [rdnSequence]
321 rdn0 = SET:rdnSet0
322 [rdnSet0]
323 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
324 [attrTypeAndValueSequence0_0]
325 type=OID:countryName
326 value=PRINTABLESTRING:"US"
327 """, "valid-minimal")
329 if __name__ == '__main__':
330 main()