From 2ee5e3c6240721120146d6d81c70e1b900029ee0 Mon Sep 17 00:00:00 2001 From: Joshua Tauberer Date: Sat, 4 Jul 2015 20:09:46 +0000 Subject: parse SAN otherNames into OtherName instances rather than raising an exception Test added. --- src/_cffi_src/openssl/asn1.py | 2 ++ src/cryptography/hazmat/backends/openssl/x509.py | 17 +++++++++++++- src/cryptography/x509.py | 28 ++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) (limited to 'src') 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 "".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): -- cgit v1.2.3