| Index: net/data/verify_name_match_unittest/scripts/generate-names.py
|
| diff --git a/net/data/verify_name_match_unittest/scripts/generate-names.py b/net/data/verify_name_match_unittest/scripts/generate-names.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..ea0e0fd14541988bf7c81f118b3e6773de497315
|
| --- /dev/null
|
| +++ b/net/data/verify_name_match_unittest/scripts/generate-names.py
|
| @@ -0,0 +1,326 @@
|
| +#!/usr/bin/env python
|
| +# Copyright 2015 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +import base64
|
| +import copy
|
| +import os
|
| +import subprocess
|
| +import tempfile
|
| +
|
| +
|
| +class RDN:
|
| + def __init__(self):
|
| + self.attrs = []
|
| +
|
| + def add_attr(self, attr_type, attr_value_type, attr_value,
|
| + attr_modifier=None):
|
| + self.attrs.append((attr_type, attr_value_type, attr_value, attr_modifier))
|
| + return self
|
| +
|
| + def __str__(self):
|
| + s = ''
|
| + for n, attr in enumerate(self.attrs):
|
| + s += 'attrTypeAndValue%i=SEQUENCE:attrTypeAndValueSequence%i_%i\n' % (
|
| + n, id(self), n)
|
| +
|
| + s += '\n'
|
| + for n, attr in enumerate(self.attrs):
|
| + attr_type, attr_value_type, attr_value, attr_modifier = attr
|
| + s += '[attrTypeAndValueSequence%i_%i]\n' % (id(self), n)
|
| + # Note the quotes around the string value here, which is necessary for
|
| + # trailing whitespace to be included by openssl.
|
| + s += 'type=OID:%s\n' % attr_type
|
| + s += 'value='
|
| + if attr_modifier:
|
| + s += attr_modifier + ','
|
| + s += '%s:"%s"\n' % (attr_value_type, attr_value)
|
| +
|
| + return s
|
| +
|
| +
|
| +class NameGenerator:
|
| + def __init__(self):
|
| + self.rdns = []
|
| +
|
| + def add_rdn(self):
|
| + rdn = RDN()
|
| + self.rdns.append(rdn)
|
| + return rdn
|
| +
|
| + def __str__(self):
|
| + s = 'asn1 = SEQUENCE:rdnSequence\n\n[rdnSequence]\n'
|
| + for n, rdn in enumerate(self.rdns):
|
| + s += 'rdn%i = SET:rdnSet%i\n' % (n, n)
|
| +
|
| + s += '\n'
|
| +
|
| + for n, rdn in enumerate(self.rdns):
|
| + s += '[rdnSet%i]\n%s\n' % (n, rdn)
|
| +
|
| + return s
|
| +
|
| +
|
| +def generate(s, fn):
|
| + out_fn = os.path.join('..', 'names', fn + '.pem')
|
| + conf_tempfile = tempfile.NamedTemporaryFile()
|
| + conf_tempfile.write(str(s))
|
| + conf_tempfile.flush()
|
| + der_tmpfile = tempfile.NamedTemporaryFile()
|
| + description_tmpfile = tempfile.NamedTemporaryFile()
|
| + subprocess.check_call(['openssl', 'asn1parse', '-genconf', conf_tempfile.name,
|
| + '-i', '-out', der_tmpfile.name],
|
| + stdout=description_tmpfile)
|
| + conf_tempfile.close()
|
| +
|
| + output_file = open(out_fn, 'w')
|
| + description_tmpfile.seek(0)
|
| + output_file.write(description_tmpfile.read())
|
| + output_file.write('-----BEGIN NAME-----\n')
|
| + output_file.write(base64.encodestring(der_tmpfile.read()))
|
| + output_file.write('-----END NAME-----\n')
|
| + output_file.close()
|
| +
|
| +
|
| +def unmangled(s):
|
| + return s
|
| +
|
| +
|
| +def extra_whitespace(s):
|
| + return ' ' + s.replace(' ', ' ') + ' '
|
| +
|
| +
|
| +def case_swap(s):
|
| + return s.swapcase()
|
| +
|
| +
|
| +def main():
|
| + for valuetype in ('PRINTABLESTRING', 'T61STRING', 'UTF8', 'BMPSTRING',
|
| + 'UNIVERSALSTRING'):
|
| + for string_mangler in (unmangled, extra_whitespace, case_swap):
|
| + n=NameGenerator()
|
| + n.add_rdn().add_attr('countryName', 'PRINTABLESTRING', 'US')
|
| + n.add_rdn().add_attr('stateOrProvinceName',
|
| + valuetype,
|
| + string_mangler('New York'))
|
| + n.add_rdn().add_attr('localityName',
|
| + valuetype,
|
| + string_mangler("ABCDEFGHIJKLMNOPQRSTUVWXYZ "
|
| + "abcdefghijklmnopqrstuvwxyz "
|
| + "0123456789 '()+,-./:=?"))
|
| +
|
| + n_extra_attr = copy.deepcopy(n)
|
| + n_extra_attr.rdns[-1].add_attr('organizationName',
|
| + valuetype,
|
| + string_mangler('Name of company'))
|
| +
|
| + n_extra_rdn = copy.deepcopy(n)
|
| + n_extra_rdn.add_rdn().add_attr('organizationName',
|
| + valuetype,
|
| + string_mangler('Name of company'))
|
| +
|
| + filename_base = 'ascii-' + valuetype + '-' + string_mangler.__name__
|
| +
|
| + generate(n, filename_base)
|
| + generate(n_extra_attr, filename_base + '-extra_attr')
|
| + generate(n_extra_rdn, filename_base + '-extra_rdn')
|
| +
|
| + for valuetype in ('UTF8', 'BMPSTRING', 'UNIVERSALSTRING'):
|
| + n=NameGenerator()
|
| + n.add_rdn().add_attr('countryName', 'PRINTABLESTRING', 'JP')
|
| + n.add_rdn().add_attr('localityName',
|
| + valuetype,
|
| + "\xe6\x9d\xb1\xe4\xba\xac",
|
| + "FORMAT:UTF8")
|
| +
|
| + filename_base = 'unicode_bmp-' + valuetype + '-' + 'unmangled'
|
| + generate(n, filename_base)
|
| +
|
| + for valuetype in ('UTF8', 'UNIVERSALSTRING'):
|
| + n=NameGenerator()
|
| + n.add_rdn().add_attr('countryName', 'PRINTABLESTRING', 'JP')
|
| + n.add_rdn().add_attr('localityName',
|
| + valuetype,
|
| + "\xf0\x9d\x90\x80\xf0\x9d\x90\x99",
|
| + "FORMAT:UTF8")
|
| +
|
| + filename_base = 'unicode_supplementary-' + valuetype + '-' + 'unmangled'
|
| + generate(n, filename_base)
|
| +
|
| + generate("""asn1 = SEQUENCE:rdnSequence
|
| +[rdnSequence]
|
| +rdn0 = SET:rdnSet0
|
| +[rdnSet0]
|
| +attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
|
| +[attrTypeAndValueSequence0_0]
|
| +type=OID:countryName
|
| +value=PRINTABLESTRING:"US"
|
| +extra=PRINTABLESTRING:"hello world"
|
| +""", "invalid-AttributeTypeAndValue-extradata")
|
| +
|
| + generate("""asn1 = SEQUENCE:rdnSequence
|
| +[rdnSequence]
|
| +rdn0 = SET:rdnSet0
|
| +[rdnSet0]
|
| +attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
|
| +[attrTypeAndValueSequence0_0]
|
| +type=OID:countryName
|
| +""", "invalid-AttributeTypeAndValue-onlyOneElement")
|
| +
|
| + generate("""asn1 = SEQUENCE:rdnSequence
|
| +[rdnSequence]
|
| +rdn0 = SET:rdnSet0
|
| +[rdnSet0]
|
| +attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
|
| +[attrTypeAndValueSequence0_0]
|
| +""", "invalid-AttributeTypeAndValue-empty")
|
| +
|
| + generate("""asn1 = SEQUENCE:rdnSequence
|
| +[rdnSequence]
|
| +rdn0 = SET:rdnSet0
|
| +[rdnSet0]
|
| +attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
|
| +[attrTypeAndValueSequence0_0]
|
| +type=PRINTABLESTRING:"hello world"
|
| +value=PRINTABLESTRING:"US"
|
| +""", "invalid-AttributeTypeAndValue-badAttributeType")
|
| +
|
| + generate("""asn1 = SEQUENCE:rdnSequence
|
| +[rdnSequence]
|
| +rdn0 = SET:rdnSet0
|
| +[rdnSet0]
|
| +attrTypeAndValue0=SET:attrTypeAndValueSequence0_0
|
| +[attrTypeAndValueSequence0_0]
|
| +type=OID:countryName
|
| +value=PRINTABLESTRING:"US"
|
| +""", "invalid-AttributeTypeAndValue-setNotSequence")
|
| +
|
| + generate("""asn1 = SEQUENCE:rdnSequence
|
| +[rdnSequence]
|
| +rdn0 = SEQUENCE:rdnSet0
|
| +[rdnSet0]
|
| +attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
|
| +[attrTypeAndValueSequence0_0]
|
| +type=OID:countryName
|
| +value=PRINTABLESTRING:"US"
|
| +""", "invalid-RDN-sequenceInsteadOfSet")
|
| +
|
| + generate("""asn1 = SEQUENCE:rdnSequence
|
| +[rdnSequence]
|
| +rdn0 = SET:rdnSet0
|
| +[rdnSet0]
|
| +""", "invalid-RDN-empty")
|
| +
|
| + generate("""asn1 = SET:rdnSequence
|
| +[rdnSequence]
|
| +rdn0 = SET:rdnSet0
|
| +[rdnSet0]
|
| +attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
|
| +[attrTypeAndValueSequence0_0]
|
| +type=OID:countryName
|
| +value=PRINTABLESTRING:"US"
|
| +""", "invalid-Name-setInsteadOfSequence")
|
| +
|
| + generate("""asn1 = SEQUENCE:rdnSequence
|
| +[rdnSequence]
|
| +""", "valid-Name-empty")
|
| +
|
| + # Certs with a RDN that is sorted differently due to length of the values, but
|
| + # which should compare equal when normalized.
|
| + generate("""asn1 = SEQUENCE:rdnSequence
|
| +[rdnSequence]
|
| +rdn0 = SET:rdnSet0
|
| +[rdnSet0]
|
| +attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
|
| +attrTypeAndValue1=SEQUENCE:attrTypeAndValueSequence0_1
|
| +[attrTypeAndValueSequence0_0]
|
| +type=OID:stateOrProvinceName
|
| +value=PRINTABLESTRING:" state"
|
| +[attrTypeAndValueSequence0_1]
|
| +type=OID:localityName
|
| +value=PRINTABLESTRING:"locality"
|
| +""", "ascii-PRINTABLESTRING-rdn_sorting_1")
|
| +
|
| + generate("""asn1 = SEQUENCE:rdnSequence
|
| +[rdnSequence]
|
| +rdn0 = SET:rdnSet0
|
| +[rdnSet0]
|
| +attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
|
| +attrTypeAndValue1=SEQUENCE:attrTypeAndValueSequence0_1
|
| +[attrTypeAndValueSequence0_0]
|
| +type=OID:stateOrProvinceName
|
| +value=PRINTABLESTRING:"state"
|
| +[attrTypeAndValueSequence0_1]
|
| +type=OID:localityName
|
| +value=PRINTABLESTRING:" locality"
|
| +""", "ascii-PRINTABLESTRING-rdn_sorting_2")
|
| +
|
| + # Certs with a RDN that is sorted differently due to length of the values, and
|
| + # also contains multiple values with the same type.
|
| + generate("""asn1 = SEQUENCE:rdnSequence
|
| +[rdnSequence]
|
| +rdn0 = SET:rdnSet0
|
| +[rdnSet0]
|
| +attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
|
| +attrTypeAndValue1=SEQUENCE:attrTypeAndValueSequence0_1
|
| +attrTypeAndValue2=SEQUENCE:attrTypeAndValueSequence0_2
|
| +attrTypeAndValue3=SEQUENCE:attrTypeAndValueSequence0_3
|
| +attrTypeAndValue4=SEQUENCE:attrTypeAndValueSequence0_4
|
| +[attrTypeAndValueSequence0_0]
|
| +type=OID:domainComponent
|
| +value=IA5STRING:" cOm"
|
| +[attrTypeAndValueSequence0_1]
|
| +type=OID:domainComponent
|
| +value=IA5STRING:"eXaMple"
|
| +[attrTypeAndValueSequence0_2]
|
| +type=OID:domainComponent
|
| +value=IA5STRING:"wWw"
|
| +[attrTypeAndValueSequence0_3]
|
| +type=OID:localityName
|
| +value=PRINTABLESTRING:"NEw"
|
| +[attrTypeAndValueSequence0_4]
|
| +type=OID:localityName
|
| +value=PRINTABLESTRING:" yORk "
|
| +""", "ascii-mixed-rdn_dupetype_sorting_1")
|
| +
|
| + generate("""asn1 = SEQUENCE:rdnSequence
|
| +[rdnSequence]
|
| +rdn0 = SET:rdnSet0
|
| +[rdnSet0]
|
| +attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
|
| +attrTypeAndValue1=SEQUENCE:attrTypeAndValueSequence0_1
|
| +attrTypeAndValue2=SEQUENCE:attrTypeAndValueSequence0_2
|
| +attrTypeAndValue3=SEQUENCE:attrTypeAndValueSequence0_3
|
| +attrTypeAndValue4=SEQUENCE:attrTypeAndValueSequence0_4
|
| +[attrTypeAndValueSequence0_0]
|
| +type=OID:domainComponent
|
| +value=IA5STRING:"cOM"
|
| +[attrTypeAndValueSequence0_1]
|
| +type=OID:domainComponent
|
| +value=IA5STRING:"eXampLE"
|
| +[attrTypeAndValueSequence0_2]
|
| +type=OID:domainComponent
|
| +value=IA5STRING:" Www "
|
| +[attrTypeAndValueSequence0_3]
|
| +type=OID:localityName
|
| +value=PRINTABLESTRING:" nEw "
|
| +[attrTypeAndValueSequence0_4]
|
| +type=OID:localityName
|
| +value=PRINTABLESTRING:"yoRK"
|
| +""", "ascii-mixed-rdn_dupetype_sorting_2")
|
| +
|
| + # Minimal valid config. Copy and modify this one when generating new invalid
|
| + # configs.
|
| + generate("""asn1 = SEQUENCE:rdnSequence
|
| +[rdnSequence]
|
| +rdn0 = SET:rdnSet0
|
| +[rdnSet0]
|
| +attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
|
| +[attrTypeAndValueSequence0_0]
|
| +type=OID:countryName
|
| +value=PRINTABLESTRING:"US"
|
| +""", "valid-minimal")
|
| +
|
| +if __name__ == '__main__':
|
| + main()
|
|
|