aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2015-01-01 20:03:52 -0600
committerPaul Kehrer <paul.l.kehrer@gmail.com>2015-02-12 18:58:14 -0600
commit719d536dd691e84e208534798f2eb4f82aaa2e07 (patch)
treeecbe47cdda225afe629273d702d1ee2fd8d86811 /src
parentcd9bdcddf7ea7fe041ffcb01965a035e64ab719e (diff)
downloadcryptography-719d536dd691e84e208534798f2eb4f82aaa2e07.tar.gz
cryptography-719d536dd691e84e208534798f2eb4f82aaa2e07.tar.bz2
cryptography-719d536dd691e84e208534798f2eb4f82aaa2e07.zip
X509 distinguished name parsing support in the OpenSSL backend
Diffstat (limited to 'src')
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py42
-rw-r--r--src/cryptography/x509.py93
2 files changed, 135 insertions, 0 deletions
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.
+ """