From 1ebcd1c82a24502f51a1c14e6536928c65ae5406 Mon Sep 17 00:00:00 2001 From: Nick Bastin Date: Sat, 12 Dec 2015 18:32:59 -0800 Subject: Allow any OID for access_method, validate OIDs at creation time, fix tests. --- src/cryptography/x509/extensions.py | 7 ++--- src/cryptography/x509/oid.py | 7 +++++ tests/test_x509.py | 54 ++++++++++++++++++------------------- tests/test_x509_ext.py | 19 ++++++------- 4 files changed, 46 insertions(+), 41 deletions(-) diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 46ba5a28..017e0989 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -238,11 +238,8 @@ class AuthorityInformationAccess(object): class AccessDescription(object): def __init__(self, access_method, access_location): - if not (access_method == AuthorityInformationAccessOID.OCSP or - access_method == AuthorityInformationAccessOID.CA_ISSUERS): - raise ValueError( - "access_method must be OID_OCSP or OID_CA_ISSUERS" - ) + if not isinstance(access_method, ObjectIdentifier): + raise TypeError("access_method must be an ObjectIdentifier") if not isinstance(access_location, GeneralName): raise TypeError("access_location must be a GeneralName") diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py index ead40169..977d770f 100644 --- a/src/cryptography/x509/oid.py +++ b/src/cryptography/x509/oid.py @@ -12,6 +12,13 @@ class ObjectIdentifier(object): def __init__(self, dotted_string): self._dotted_string = dotted_string + # Basic validation for being well-formed + for part in self._dotted_string.split("."): + try: + val = int(part, 0) + except ValueError: + raise ValueError("Malformed OID: %s" % (self._dotted_string)) + def __eq__(self, other): if not isinstance(other, ObjectIdentifier): return NotImplemented diff --git a/tests/test_x509.py b/tests/test_x509.py index 0a1870d5..02201a37 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -3188,15 +3188,15 @@ class TestNameAttribute(object): def test_init_bad_value(self): with pytest.raises(TypeError): x509.NameAttribute( - x509.ObjectIdentifier('oid'), + x509.ObjectIdentifier('2.999.1'), b'bytes' ) def test_eq(self): assert x509.NameAttribute( - x509.ObjectIdentifier('oid'), u'value' + x509.ObjectIdentifier('2.999.1'), u'value' ) == x509.NameAttribute( - x509.ObjectIdentifier('oid'), u'value' + x509.ObjectIdentifier('2.999.1'), u'value' ) def test_ne(self): @@ -3206,12 +3206,12 @@ class TestNameAttribute(object): x509.ObjectIdentifier('2.5.4.5'), u'value' ) assert x509.NameAttribute( - x509.ObjectIdentifier('oid'), u'value' + x509.ObjectIdentifier('2.999.1'), u'value' ) != x509.NameAttribute( - x509.ObjectIdentifier('oid'), u'value2' + x509.ObjectIdentifier('2.999.1'), u'value2' ) assert x509.NameAttribute( - x509.ObjectIdentifier('oid'), u'value' + x509.ObjectIdentifier('2.999.2'), u'value' ) != object() def test_repr(self): @@ -3230,64 +3230,64 @@ class TestNameAttribute(object): class TestObjectIdentifier(object): def test_eq(self): - oid1 = x509.ObjectIdentifier('oid') - oid2 = x509.ObjectIdentifier('oid') + oid1 = x509.ObjectIdentifier('2.999.1') + oid2 = x509.ObjectIdentifier('2.999.1') assert oid1 == oid2 def test_ne(self): - oid1 = x509.ObjectIdentifier('oid') - assert oid1 != x509.ObjectIdentifier('oid1') + oid1 = x509.ObjectIdentifier('2.999.1') + assert oid1 != x509.ObjectIdentifier('2.999.2') assert oid1 != object() def test_repr(self): oid = x509.ObjectIdentifier("2.5.4.3") assert repr(oid) == "" - oid = x509.ObjectIdentifier("oid1") - assert repr(oid) == "" + oid = x509.ObjectIdentifier("2.999.1") + assert repr(oid) == "" def test_name_property(self): oid = x509.ObjectIdentifier("2.5.4.3") assert oid._name == 'commonName' - oid = x509.ObjectIdentifier("oid1") + oid = x509.ObjectIdentifier("2.999.1") assert oid._name == 'Unknown OID' class TestName(object): def test_eq(self): name1 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), ]) name2 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), ]) assert name1 == name2 def test_ne(self): name1 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), ]) name2 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), ]) assert name1 != name2 assert name1 != object() def test_hash(self): name1 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), ]) name2 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), ]) name3 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), ]) assert hash(name1) == hash(name2) diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index 8f469366..8cbce10b 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -603,8 +603,8 @@ class TestAuthorityKeyIdentifier(object): def test_authority_cert_serial_number_not_integer(self): dirname = x509.DirectoryName( x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), ]) ) with pytest.raises(TypeError): @@ -617,8 +617,8 @@ class TestAuthorityKeyIdentifier(object): def test_authority_issuer_not_none_serial_none(self): dirname = x509.DirectoryName( x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), ]) ) with pytest.raises(ValueError): @@ -1166,10 +1166,10 @@ class TestDirectoryName(object): def test_eq(self): name = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1') + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1') ]) name2 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1') + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1') ]) gn = x509.DirectoryName(x509.Name([name])) gn2 = x509.DirectoryName(x509.Name([name2])) @@ -1177,10 +1177,10 @@ class TestDirectoryName(object): def test_ne(self): name = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1') + x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1') ]) name2 = x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value2') + x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2') ]) gn = x509.DirectoryName(x509.Name([name])) gn2 = x509.DirectoryName(x509.Name([name2])) @@ -1848,7 +1848,8 @@ class TestExtendedKeyUsageExtension(object): class TestAccessDescription(object): def test_invalid_access_method(self): - with pytest.raises(ValueError): + # access_method can be *any* valid OID + with pytest.raises(TypeError): x509.AccessDescription("notanoid", x509.DNSName(u"test")) def test_invalid_access_location(self): -- cgit v1.2.3 From 22e81726fe1a38b3100361f2e8dd120c89c512e3 Mon Sep 17 00:00:00 2001 From: Nick Bastin Date: Sat, 12 Dec 2015 18:54:12 -0800 Subject: Add test for arbitrary access_method --- tests/test_x509_ext.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index 8cbce10b..565cf571 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -1858,6 +1858,10 @@ class TestAccessDescription(object): AuthorityInformationAccessOID.CA_ISSUERS, "invalid" ) + def test_valid_nonstandard_method (self): + ad = x509.AccessDescription("2.999.1", x509.UniformResourceIdentifier(u"http://example.com")) + assert ad is not None + def test_repr(self): ad = x509.AccessDescription( AuthorityInformationAccessOID.OCSP, -- cgit v1.2.3 From b19ec5119db2e2549d7062717a0e10b66c91714a Mon Sep 17 00:00:00 2001 From: Nick Bastin Date: Sat, 12 Dec 2015 19:08:12 -0800 Subject: Style cleanup, missing import --- tests/test_x509_ext.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index 565cf571..fbd8b882 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -18,7 +18,8 @@ from cryptography.hazmat.backends.interfaces import ( ) from cryptography.hazmat.primitives.asymmetric import ec from cryptography.x509.oid import ( - AuthorityInformationAccessOID, ExtendedKeyUsageOID, ExtensionOID, NameOID + AuthorityInformationAccessOID, ExtendedKeyUsageOID, ExtensionOID, + NameOID, ObjectIdentifier ) from .hazmat.primitives.test_ec import _skip_curve_unsupported @@ -1859,7 +1860,10 @@ class TestAccessDescription(object): ) def test_valid_nonstandard_method (self): - ad = x509.AccessDescription("2.999.1", x509.UniformResourceIdentifier(u"http://example.com")) + ad = x509.AccessDescription( + ObjectIdentifier("2.999.1"), + x509.UniformResourceIdentifier(u"http://example.com") + ) assert ad is not None def test_repr(self): -- cgit v1.2.3 From 74021e97f842b7b5843863bc988f39710a9258f4 Mon Sep 17 00:00:00 2001 From: Nick Bastin Date: Sun, 13 Dec 2015 05:15:44 -0800 Subject: 4-space indent for this repo --- src/cryptography/x509/extensions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 017e0989..97d78266 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -239,7 +239,7 @@ class AuthorityInformationAccess(object): class AccessDescription(object): def __init__(self, access_method, access_location): if not isinstance(access_method, ObjectIdentifier): - raise TypeError("access_method must be an ObjectIdentifier") + raise TypeError("access_method must be an ObjectIdentifier") if not isinstance(access_location, GeneralName): raise TypeError("access_location must be a GeneralName") -- cgit v1.2.3 From a7f504fcd61eda90456366a7c7bf608fd03f5d47 Mon Sep 17 00:00:00 2001 From: Nick Bastin Date: Sun, 13 Dec 2015 05:37:04 -0800 Subject: PEP8 fixes --- src/cryptography/x509/extensions.py | 4 +--- src/cryptography/x509/oid.py | 2 +- tests/test_x509_ext.py | 21 ++++++++++++++++----- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 97d78266..71ce8a15 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -18,9 +18,7 @@ from cryptography import utils from cryptography.hazmat.primitives import constant_time, serialization from cryptography.x509.general_name import GeneralName, IPAddress, OtherName from cryptography.x509.name import Name -from cryptography.x509.oid import ( - AuthorityInformationAccessOID, ExtensionOID, ObjectIdentifier -) +from cryptography.x509.oid import ExtensionOID, ObjectIdentifier class _SubjectPublicKeyInfo(univ.Sequence): diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py index 977d770f..f2d84d31 100644 --- a/src/cryptography/x509/oid.py +++ b/src/cryptography/x509/oid.py @@ -15,7 +15,7 @@ class ObjectIdentifier(object): # Basic validation for being well-formed for part in self._dotted_string.split("."): try: - val = int(part, 0) + int(part, 0) except ValueError: raise ValueError("Malformed OID: %s" % (self._dotted_string)) diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index fbd8b882..bbdc6079 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -604,8 +604,14 @@ class TestAuthorityKeyIdentifier(object): def test_authority_cert_serial_number_not_integer(self): dirname = x509.DirectoryName( x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), + x509.NameAttribute( + x509.ObjectIdentifier('2.999.1'), + u'value1' + ), + x509.NameAttribute( + x509.ObjectIdentifier('2.999.2'), + u'value2' + ), ]) ) with pytest.raises(TypeError): @@ -618,8 +624,14 @@ class TestAuthorityKeyIdentifier(object): def test_authority_issuer_not_none_serial_none(self): dirname = x509.DirectoryName( x509.Name([ - x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'), - x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'), + x509.NameAttribute( + x509.ObjectIdentifier('2.999.1'), + u'value1' + ), + x509.NameAttribute( + x509.ObjectIdentifier('2.999.2'), + u'value2' + ), ]) ) with pytest.raises(ValueError): @@ -1849,7 +1861,6 @@ class TestExtendedKeyUsageExtension(object): class TestAccessDescription(object): def test_invalid_access_method(self): - # access_method can be *any* valid OID with pytest.raises(TypeError): x509.AccessDescription("notanoid", x509.DNSName(u"test")) -- cgit v1.2.3 From a73825bcfacd4c533de3c4490ff34a345f7f78f9 Mon Sep 17 00:00:00 2001 From: Nick Bastin Date: Sun, 13 Dec 2015 05:44:46 -0800 Subject: Dangling pep8 fix --- tests/test_x509_ext.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index bbdc6079..83145cd0 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -1870,7 +1870,7 @@ class TestAccessDescription(object): AuthorityInformationAccessOID.CA_ISSUERS, "invalid" ) - def test_valid_nonstandard_method (self): + def test_valid_nonstandard_method(self): ad = x509.AccessDescription( ObjectIdentifier("2.999.1"), x509.UniformResourceIdentifier(u"http://example.com") -- cgit v1.2.3 From 6581507f92ab43182cfa10510e6f9e16ebaf3793 Mon Sep 17 00:00:00 2001 From: Nick Bastin Date: Sun, 13 Dec 2015 06:46:15 -0800 Subject: Add bad input test for coverage of new validation --- tests/test_x509.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_x509.py b/tests/test_x509.py index 02201a37..c276f099 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -3251,6 +3251,10 @@ class TestObjectIdentifier(object): oid = x509.ObjectIdentifier("2.999.1") assert oid._name == 'Unknown OID' + def test_bad_input(self): + with pytest.raises(ValueError): + x509.ObjectIdentifier("notavalidform") + class TestName(object): def test_eq(self): -- cgit v1.2.3 From 9459d94585397d94d0f6fc4807e3316059275867 Mon Sep 17 00:00:00 2001 From: Nick Bastin Date: Sun, 13 Dec 2015 15:43:46 -0800 Subject: Test for non-standard AIA support in CertificateBuilder --- tests/test_x509.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/test_x509.py b/tests/test_x509.py index c276f099..8c354c2d 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -1293,6 +1293,38 @@ class TestCertificateBuilder(object): with pytest.raises(NotImplementedError): builder.sign(private_key, hashes.SHA1(), backend) + + @pytest.mark.requires_backend_interface(interface=RSABackend) + @pytest.mark.requires_backend_interface(interface=X509Backend) + def test_encode_nonstandard_aia(self, backend): + private_key = RSA_KEY_2048.private_key(backend) + + aia = x509.AuthorityInformationAccess([ + x509.AccessDescription( + x509.ObjectIdentifier("2.999.7"), + x509.UniformResourceIdentifier(u"http://example.com") + ), + ]) + + builder = x509.CertificateBuilder().subject_name(x509.Name([ + x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'), + ])).issuer_name(x509.Name([ + x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'), + ])).public_key( + private_key.public_key() + ).serial_number( + 777 + ).not_valid_before( + datetime.datetime(1999, 1, 1) + ).not_valid_after( + datetime.datetime(2020, 1, 1) + ).add_extension( + aia, False + ) + + builder.sign(private_key, hashes.SHA256(), backend) + + @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_subject_name(self, backend): -- cgit v1.2.3 From f77114acaba0a0cac7a84e0d4bfadbc7171a8c7b Mon Sep 17 00:00:00 2001 From: Nick Bastin Date: Mon, 14 Dec 2015 04:10:28 -0800 Subject: Dealing with the pedantry of pep8 --- tests/test_x509.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_x509.py b/tests/test_x509.py index 8c354c2d..88411227 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -1293,7 +1293,6 @@ class TestCertificateBuilder(object): with pytest.raises(NotImplementedError): builder.sign(private_key, hashes.SHA1(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) def test_encode_nonstandard_aia(self, backend): @@ -1324,7 +1323,6 @@ class TestCertificateBuilder(object): builder.sign(private_key, hashes.SHA256(), backend) - @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) def test_no_subject_name(self, backend): -- cgit v1.2.3