From 719d536dd691e84e208534798f2eb4f82aaa2e07 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 1 Jan 2015 20:03:52 -0600 Subject: X509 distinguished name parsing support in the OpenSSL backend --- src/cryptography/hazmat/backends/openssl/x509.py | 42 +++++++++++ src/cryptography/x509.py | 93 ++++++++++++++++++++++++ 2 files changed, 135 insertions(+) (limited to 'src') diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 66c99c9f..e27d32f8 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -91,3 +91,45 @@ class _Certificate(object): ) ).decode("ascii") return datetime.datetime.strptime(time, "%Y%m%d%H%M%SZ") + + @property + def issuer(self): + issuer = self._backend._lib.X509_get_issuer_name(self._x509) + assert issuer != self._backend._ffi.NULL + return self._build_x509_name(issuer) + + @property + def subject(self): + subject = self._backend._lib.X509_get_subject_name(self._x509) + assert subject != self._backend._ffi.NULL + return self._build_x509_name(subject) + + def _build_x509_name(self, x509_name): + count = self._backend._lib.X509_NAME_entry_count(x509_name) + attributes = [] + for x in range(0, count): + entry = self._backend._lib.X509_NAME_get_entry(x509_name, x) + obj = self._backend._lib.X509_NAME_ENTRY_get_object(entry) + assert obj != self._backend._ffi.NULL + data = self._backend._lib.X509_NAME_ENTRY_get_data(entry) + assert data != self._backend._ffi.NULL + buf = self._backend._ffi.new("unsigned char **") + res = self._backend._lib.ASN1_STRING_to_UTF8(buf, data) + assert buf[0] != self._backend._ffi.NULL + buf = self._backend._ffi.gc( + buf, lambda buf: self._backend._lib.OPENSSL_free(buf[0]) + ) + value = self._backend._ffi.buffer(buf[0], res)[:].decode('utf8') + buf_len = 50 + buf = self._backend._ffi.new("char[]", buf_len) + res = self._backend._lib.OBJ_obj2txt(buf, buf_len, obj, 1) + assert res > 0 + oid = self._backend._ffi.buffer(buf, res)[:].decode() + + attributes.append( + x509.NameAttribute( + x509.ObjectIdentifier(oid), value + ) + ) + + return x509.Name(attributes) diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index 71062588..2371b36c 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -104,6 +104,87 @@ class ObjectIdentifier(object): dotted_string = utils.read_only_property("_dotted_string") +class Name(object): + def __init__(self, attributes): + self._attributes = attributes + + def _filter_attr_list(self, oid): + return [i for i in self._attributes if i.oid == oid] + + @property + def common_name(self): + return self._filter_attr_list(OID_COMMON_NAME) + + @property + def country_name(self): + return self._filter_attr_list(OID_COUNTRY_NAME) + + @property + def locality_name(self): + return self._filter_attr_list(OID_LOCALITY_NAME) + + @property + def state_or_province_name(self): + return self._filter_attr_list(OID_STATE_OR_PROVINCE_NAME) + + @property + def organization_name(self): + return self._filter_attr_list(OID_ORGANIZATION_NAME) + + @property + def organizational_unit_name(self): + return self._filter_attr_list(OID_ORGANIZATIONAL_UNIT_NAME) + + @property + def serial_number(self): + return self._filter_attr_list(OID_SERIAL_NUMBER) + + @property + def surname(self): + return self._filter_attr_list(OID_SURNAME) + + @property + def given_name(self): + return self._filter_attr_list(OID_GIVEN_NAME) + + @property + def title(self): + return self._filter_attr_list(OID_TITLE) + + @property + def generation_qualifier(self): + return self._filter_attr_list(OID_GENERATION_QUALIFIER) + + @property + def dn_qualifier(self): + return self._filter_attr_list(OID_DN_QUALIFIER) + + @property + def pseudonym(self): + return self._filter_attr_list(OID_PSEUDONYM) + + @property + def domain_component(self): + return self._filter_attr_list(OID_DOMAIN_COMPONENT) + + @property + def email_address(self): + return self._filter_attr_list(OID_EMAIL_ADDRESS) + + @property + def attributes(self): + return self._attributes[:] + + def __eq__(self, other): + if not isinstance(other, Name): + return NotImplemented + + return self.attributes == other.attributes + + def __ne__(self, other): + return not self == other + + OID_COMMON_NAME = ObjectIdentifier("2.5.4.3") OID_COUNTRY_NAME = ObjectIdentifier("2.5.4.6") OID_LOCALITY_NAME = ObjectIdentifier("2.5.4.7") @@ -158,3 +239,15 @@ class Certificate(object): """ Not after time (represented as UTC datetime) """ + + @abc.abstractproperty + def issuer(self): + """ + Returns the issuer name object. + """ + + @abc.abstractproperty + def subject(self): + """ + Returns the subject name object. + """ -- cgit v1.2.3 From e901d642548dd268dcdc2efa60087a3fa1774fa6 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 11 Feb 2015 18:50:58 -0600 Subject: refactor x509.Name to use get_attributes_by_oid --- src/cryptography/hazmat/backends/openssl/x509.py | 2 +- src/cryptography/x509.py | 62 +----------------------- 2 files changed, 2 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index e27d32f8..6bc7137c 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -107,7 +107,7 @@ class _Certificate(object): def _build_x509_name(self, x509_name): count = self._backend._lib.X509_NAME_entry_count(x509_name) attributes = [] - for x in range(0, count): + for x in range(count): entry = self._backend._lib.X509_NAME_get_entry(x509_name, x) obj = self._backend._lib.X509_NAME_ENTRY_get_object(entry) assert obj != self._backend._ffi.NULL diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index 2371b36c..7eb9a608 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -108,69 +108,9 @@ class Name(object): def __init__(self, attributes): self._attributes = attributes - def _filter_attr_list(self, oid): + def get_attributes_for_oid(self, oid): return [i for i in self._attributes if i.oid == oid] - @property - def common_name(self): - return self._filter_attr_list(OID_COMMON_NAME) - - @property - def country_name(self): - return self._filter_attr_list(OID_COUNTRY_NAME) - - @property - def locality_name(self): - return self._filter_attr_list(OID_LOCALITY_NAME) - - @property - def state_or_province_name(self): - return self._filter_attr_list(OID_STATE_OR_PROVINCE_NAME) - - @property - def organization_name(self): - return self._filter_attr_list(OID_ORGANIZATION_NAME) - - @property - def organizational_unit_name(self): - return self._filter_attr_list(OID_ORGANIZATIONAL_UNIT_NAME) - - @property - def serial_number(self): - return self._filter_attr_list(OID_SERIAL_NUMBER) - - @property - def surname(self): - return self._filter_attr_list(OID_SURNAME) - - @property - def given_name(self): - return self._filter_attr_list(OID_GIVEN_NAME) - - @property - def title(self): - return self._filter_attr_list(OID_TITLE) - - @property - def generation_qualifier(self): - return self._filter_attr_list(OID_GENERATION_QUALIFIER) - - @property - def dn_qualifier(self): - return self._filter_attr_list(OID_DN_QUALIFIER) - - @property - def pseudonym(self): - return self._filter_attr_list(OID_PSEUDONYM) - - @property - def domain_component(self): - return self._filter_attr_list(OID_DOMAIN_COMPONENT) - - @property - def email_address(self): - return self._filter_attr_list(OID_EMAIL_ADDRESS) - @property def attributes(self): return self._attributes[:] -- cgit v1.2.3 From 53d8d49454d7cef5cd41fc854116090ca78026ce Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 13 Feb 2015 18:47:30 -0600 Subject: make x509.Name iterable and address other review feedback --- src/cryptography/x509.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index 7eb9a608..21693ed4 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -111,19 +111,21 @@ class Name(object): def get_attributes_for_oid(self, oid): return [i for i in self._attributes if i.oid == oid] - @property - def attributes(self): - return self._attributes[:] - def __eq__(self, other): if not isinstance(other, Name): return NotImplemented - return self.attributes == other.attributes + return self._attributes == other._attributes def __ne__(self, other): return not self == other + def __iter__(self): + return iter(self._attributes[:]) + + def __len__(self): + return len(self._attributes) + OID_COMMON_NAME = ObjectIdentifier("2.5.4.3") OID_COUNTRY_NAME = ObjectIdentifier("2.5.4.6") -- cgit v1.2.3 From 5ab6d6a5c05572bd1c75f05baf264a2d0001894a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 13 Feb 2015 19:19:16 -0600 Subject: update buffer length for OBJ_obj2txt --- src/cryptography/hazmat/backends/openssl/x509.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 6bc7137c..ebfbf331 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -120,7 +120,9 @@ class _Certificate(object): buf, lambda buf: self._backend._lib.OPENSSL_free(buf[0]) ) value = self._backend._ffi.buffer(buf[0], res)[:].decode('utf8') - buf_len = 50 + # Set to 80 on the recommendation of + # https://www.openssl.org/docs/crypto/OBJ_nid2ln.html + buf_len = 80 buf = self._backend._ffi.new("char[]", buf_len) res = self._backend._lib.OBJ_obj2txt(buf, buf_len, obj, 1) assert res > 0 -- cgit v1.2.3 From 8b21a4a34a82ca0e73ca67bd3f148b25d6c7bdc6 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 14 Feb 2015 07:56:36 -0600 Subject: simplify things based on review feedback --- src/cryptography/hazmat/backends/openssl/x509.py | 1 + src/cryptography/x509.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index ebfbf331..76dcf32f 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -115,6 +115,7 @@ class _Certificate(object): assert data != self._backend._ffi.NULL buf = self._backend._ffi.new("unsigned char **") res = self._backend._lib.ASN1_STRING_to_UTF8(buf, data) + assert res >= 0 assert buf[0] != self._backend._ffi.NULL buf = self._backend._ffi.gc( buf, lambda buf: self._backend._lib.OPENSSL_free(buf[0]) diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index 21693ed4..8a888d2a 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -121,7 +121,7 @@ class Name(object): return not self == other def __iter__(self): - return iter(self._attributes[:]) + return iter(self._attributes) def __len__(self): return len(self._attributes) -- cgit v1.2.3