aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--setup.py1
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py30
-rw-r--r--src/cryptography/x509.py17
-rw-r--r--tests/test_x509_ext.py21
4 files changed, 69 insertions, 0 deletions
diff --git a/setup.py b/setup.py
index 6376a1f5..e0b57380 100644
--- a/setup.py
+++ b/setup.py
@@ -32,6 +32,7 @@ with open(os.path.join(src_dir, "cryptography", "__about__.py")) as f:
VECTORS_DEPENDENCY = "cryptography_vectors=={0}".format(about['__version__'])
requirements = [
+ "idna",
"pyasn1",
"six>=1.4.1",
"setuptools"
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index 57e6146b..363d3df1 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -15,6 +15,8 @@ from __future__ import absolute_import, division, print_function
import datetime
+import idna
+
from cryptography import utils, x509
from cryptography.exceptions import UnsupportedAlgorithm
from cryptography.hazmat.primitives import hashes
@@ -57,6 +59,14 @@ def _build_x509_name(backend, x509_name):
return x509.Name(attributes)
+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
+ )[:].decode("ascii")
+ return x509.DNSName(idna.decode(data))
+
+
@utils.register_interface(x509.Certificate)
class _Certificate(object):
def __init__(self, backend, x509):
@@ -173,6 +183,8 @@ class _Certificate(object):
value = self._build_subject_key_identifier(ext)
elif oid == x509.OID_KEY_USAGE:
value = self._build_key_usage(ext)
+ elif oid == x509.OID_SUBJECT_ALTERNATIVE_NAME:
+ value = self._build_subject_alt_name(ext)
elif critical:
raise x509.UnsupportedExtension(
"{0} is not currently supported".format(oid), oid
@@ -254,6 +266,24 @@ class _Certificate(object):
decipher_only
)
+ def _build_subject_alt_name(self, ext):
+ gns = self._backend._ffi.cast(
+ "GENERAL_NAMES *", self._backend._lib.X509V3_EXT_d2i(ext)
+ )
+ assert gns != self._backend._ffi.NULL
+ gns = self._backend._ffi.gc(gns, self._backend._lib.GENERAL_NAMES_free)
+ num = self._backend._lib.sk_GENERAL_NAME_num(gns)
+ general_names = []
+
+ for i in range(0, num):
+ gn = self._backend._lib.sk_GENERAL_NAME_value(gns, i)
+ assert gn != self._backend._ffi.NULL
+ value = _build_general_name(self._backend, gn)
+
+ general_names.append(value)
+
+ return x509.SubjectAlternativeName(general_names)
+
@utils.register_interface(x509.CertificateSigningRequest)
class _CertificateSigningRequest(object):
diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py
index cdc0e430..9e4b5eea 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -70,6 +70,19 @@ _OID_NAMES = {
}
+_GENERAL_NAMES = {
+ 0: "otherName",
+ 1: "rfc822Name",
+ 2: "dNSName",
+ 3: "x400Address",
+ 4: "directoryName",
+ 5: "ediPartyName",
+ 6: "uniformResourceIdentifier",
+ 7: "iPAddress",
+ 8: "registeredID",
+}
+
+
class Version(Enum):
v1 = 0
v3 = 2
@@ -115,6 +128,10 @@ class ExtensionNotFound(Exception):
self.oid = oid
+class UnsupportedGeneralNameType(Exception):
+ pass
+
+
class NameAttribute(object):
def __init__(self, oid, value):
if not isinstance(oid, ObjectIdentifier):
diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py
index 8516a339..2fa659ef 100644
--- a/tests/test_x509_ext.py
+++ b/tests/test_x509_ext.py
@@ -730,3 +730,24 @@ class TestSubjectAlternativeName(object):
assert repr(san) == (
"<SubjectAlternativeName([<DNSName(value=cryptography.io)>])>"
)
+
+
+@pytest.mark.requires_backend_interface(interface=RSABackend)
+@pytest.mark.requires_backend_interface(interface=X509Backend)
+class TestRSASubjectAlternativeNameExtension(object):
+ def test_dns_name(self, backend):
+ cert = _load_cert(
+ os.path.join("x509", "cryptography.io.pem"),
+ x509.load_pem_x509_certificate,
+ backend
+ )
+ ext = cert.extensions.get_extension_for_oid(
+ x509.OID_SUBJECT_ALTERNATIVE_NAME
+ )
+ assert ext is not None
+ assert ext.critical is False
+
+ san = ext.value
+
+ dns = san.get_values_for_type(x509.DNSName)
+ assert dns == [u"www.cryptography.io", u"cryptography.io"]