diff options
author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2015-04-22 16:04:24 -0500 |
---|---|---|
committer | Paul Kehrer <paul.l.kehrer@gmail.com> | 2015-04-28 09:41:26 -0500 |
commit | b8ef82e3f7aba8c1fce95a4f65bd655790ad1e45 (patch) | |
tree | 3671edb28f83ee32cdfd539261ffd46272ea20ea | |
parent | 2a5bb537fbfbc8ca59c6032c0a70c6e1e327701d (diff) | |
download | cryptography-b8ef82e3f7aba8c1fce95a4f65bd655790ad1e45.tar.gz cryptography-b8ef82e3f7aba8c1fce95a4f65bd655790ad1e45.tar.bz2 cryptography-b8ef82e3f7aba8c1fce95a4f65bd655790ad1e45.zip |
add URI general name support
-rw-r--r-- | docs/x509.rst | 7 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/x509.py | 28 | ||||
-rw-r--r-- | tests/test_x509_ext.py | 21 |
3 files changed, 55 insertions, 1 deletions
diff --git a/docs/x509.rst b/docs/x509.rst index 035fa87f..5f36a921 100644 --- a/docs/x509.rst +++ b/docs/x509.rst @@ -452,7 +452,12 @@ General Name Classes .. versionadded:: 0.9 This corresponds to a uniform resource identifier. For example, - ``https://cryptography.io``. + ``https://cryptography.io``. The URI is parsed and IDNA decoded (see + :rfc:`5895`). + + .. note:: + + URIs that do not contain ``://`` in them will not be decoded. .. attribute:: value diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index c21aeeb1..3a660d81 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -17,6 +17,10 @@ import datetime import idna +import six + +from six.moves import urllib_parse + from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.primitives import hashes @@ -63,6 +67,30 @@ def _build_general_name(backend, gn): if gn.type == backend._lib.GEN_DNS: data = backend._ffi.buffer(gn.d.dNSName.data, gn.d.dNSName.length)[:] return x509.DNSName(idna.decode(data)) + elif gn.type == backend._lib.GEN_URI: + data = backend._ffi.buffer( + gn.d.uniformResourceIdentifier.data, + gn.d.uniformResourceIdentifier.length + )[:].decode("ascii") + parsed = urllib_parse.urlparse(data) + hostname = idna.decode(parsed.hostname) + if parsed.port: + netloc = hostname + u":" + six.text_type(parsed.port) + else: + netloc = hostname + + # Note that building a URL in this fashion means it should be + # semantically indistinguishable from the original but is not + # guaranteed to be exactly the same. + uri = urllib_parse.urlunparse(( + parsed.scheme, + netloc, + parsed.path, + parsed.params, + parsed.query, + parsed.fragment + )) + return x509.UniformResourceIdentifier(uri) elif gn.type == backend._lib.GEN_RID: oid = _obj2txt(backend, gn.d.registeredID) return x509.RegisteredID(x509.ObjectIdentifier(oid)) diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index bce6781f..820e96b9 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -788,3 +788,24 @@ class TestRSASubjectAlternativeNameExtension(object): san = ext.value rid = san.get_values_for_type(x509.RegisteredID) assert rid == [x509.ObjectIdentifier("1.2.3.4")] + + def test_uri(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "san_uri_with_port.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + ext = cert.extensions.get_extension_for_oid( + x509.OID_SUBJECT_ALTERNATIVE_NAME + ) + assert ext is not None + uri = ext.value.get_values_for_type( + x509.UniformResourceIdentifier + ) + assert uri == [ + u"gopher://\u043f\u044b\u043a\u0430.cryptography:70/path?q=s#hel" + u"lo", + u"http://someregulardomain.com", + ] |