aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJoshua Tauberer <jt@occams.info>2015-07-04 20:09:46 +0000
committerJoshua Tauberer <jt@occams.info>2015-07-06 23:01:22 +0000
commit2ee5e3c6240721120146d6d81c70e1b900029ee0 (patch)
tree1649fac07c5b6cd18a16ce86ca5f33a9cd27cf95 /src
parent0784a23d4ab15e98214ccdf07021d42568404c1c (diff)
downloadcryptography-2ee5e3c6240721120146d6d81c70e1b900029ee0.tar.gz
cryptography-2ee5e3c6240721120146d6d81c70e1b900029ee0.tar.bz2
cryptography-2ee5e3c6240721120146d6d81c70e1b900029ee0.zip
parse SAN otherNames into OtherName instances rather than raising an exception
Test added.
Diffstat (limited to 'src')
-rw-r--r--src/_cffi_src/openssl/asn1.py2
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py17
-rw-r--r--src/cryptography/x509.py28
3 files changed, 46 insertions, 1 deletions
diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py
index 5210c7c9..01d6f4c2 100644
--- a/src/_cffi_src/openssl/asn1.py
+++ b/src/_cffi_src/openssl/asn1.py
@@ -155,6 +155,8 @@ int ASN1_UTCTIME_check(ASN1_UTCTIME *);
/* Not a macro, const on openssl 1.0 */
int ASN1_STRING_set_default_mask_asc(char *);
+
+int i2d_ASN1_TYPE(ASN1_TYPE *, unsigned char **);
"""
CUSTOMIZATIONS = """
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index 80e5f2b1..e720bfdb 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -47,6 +47,17 @@ def _asn1_string_to_utf8(backend, asn1_string):
return backend._ffi.buffer(buf[0], res)[:].decode('utf8')
+def _asn1_to_der(backend, asn1_type):
+ buf = backend._ffi.new("unsigned char **")
+ res = backend._lib.i2d_ASN1_TYPE(asn1_type, buf)
+ assert res >= 0
+ assert buf[0] != backend._ffi.NULL
+ buf = backend._ffi.gc(
+ buf, lambda buffer: backend._lib.OPENSSL_free(buffer[0])
+ )
+ return backend._ffi.buffer(buf[0], res)[:]
+
+
def _decode_x509_name_entry(backend, x509_name_entry):
obj = backend._lib.X509_NAME_ENTRY_get_object(x509_name_entry)
assert obj != backend._ffi.NULL
@@ -157,8 +168,12 @@ def _decode_general_name(backend, gn):
return x509.RFC822Name(
parts[0] + u"@" + idna.decode(parts[1])
)
+ elif gn.type == backend._lib.GEN_OTHERNAME:
+ type_id = _obj2txt(backend, gn.d.otherName.type_id)
+ value = _asn1_to_der(backend, gn.d.otherName.value)
+ return x509.OtherName(x509.ObjectIdentifier(type_id), value)
else:
- # otherName, x400Address or ediPartyName
+ # x400Address or ediPartyName
raise x509.UnsupportedGeneralNameType(
"{0} is not a supported type".format(
x509._GENERAL_NAMES.get(gn.type, gn.type)
diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py
index afd28f20..48949b61 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -1045,6 +1045,34 @@ class IPAddress(object):
return not self == other
+@utils.register_interface(GeneralName)
+class OtherName(object):
+ def __init__(self, type_id, value):
+ if not isinstance(type_id, ObjectIdentifier):
+ raise TypeError("type_id must be an ObjectIdentifier")
+ if not isinstance(value, bytes):
+ raise TypeError("value must be a binary string")
+
+ self._type_id = type_id
+ self._value = value
+
+ type_id = utils.read_only_property("_type_id")
+ value = utils.read_only_property("_value")
+
+ def __repr__(self):
+ return "<OtherName(type_id={0}, value={1!r})>".format(
+ self.type_id, self.value)
+
+ def __eq__(self, other):
+ if not isinstance(other, OtherName):
+ return NotImplemented
+
+ return self.type_id == other.type_id and self.value == other.value
+
+ def __ne__(self, other):
+ return not self == other
+
+
class GeneralNames(object):
def __init__(self, general_names):
if not all(isinstance(x, GeneralName) for x in general_names):