diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/_cffi_src/openssl/asn1.py | 2 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/x509.py | 17 | ||||
-rw-r--r-- | src/cryptography/x509.py | 36 |
3 files changed, 53 insertions, 2 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 68104e69..399e6a6e 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -55,6 +55,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 @@ -158,8 +169,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 f8134958..d9d6db4a 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): @@ -1062,7 +1090,13 @@ class GeneralNames(object): return len(self._general_names) def get_values_for_type(self, type): - return [i.value for i in self if isinstance(i, type)] + # Return the value of each GeneralName, except for OtherName instances + # which we return directly because it has two important properties not + # just one value. + objs = (i for i in self if isinstance(i, type)) + if type != OtherName: + objs = (i.value for i in objs) + return list(objs) def __repr__(self): return "<GeneralNames({0})>".format(self._general_names) |