From fbb7ac804a769ff48cddde6fb1f36d8af0d56174 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 16 Mar 2015 19:26:29 -0500 Subject: add x509 extensions class and basic tests (no extensions supported) --- src/cryptography/hazmat/backends/openssl/x509.py | 36 ++++++++++++++++++++++++ src/cryptography/x509.py | 28 ++++++++++++++++++ 2 files changed, 64 insertions(+) (limited to 'src') diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 89db016b..3502d122 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -14,6 +14,7 @@ from __future__ import absolute_import, division, print_function import datetime +import warnings from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm @@ -151,3 +152,38 @@ class _Certificate(object): raise UnsupportedAlgorithm( "Signature algorithm OID:{0} not recognized".format(oid) ) + + @property + def extensions(self): + extensions = [] + seen_oids = set() + extcount = self._backend._lib.X509_get_ext_count(self._x509) + for i in range(0, extcount): + ext = self._backend._lib.X509_get_ext(self._x509, i) + assert ext != self._backend._ffi.NULL + crit = self._backend._lib.X509_EXTENSION_get_critical(ext) + critical = crit == 1 + oid = x509.ObjectIdentifier(_obj2txt(self._backend, ext.object)) + if oid in seen_oids: + raise x509.DuplicateExtension( + "Duplicate {0} extension found".format(oid), oid + ) + elif oid == x509.OID_BASIC_CONSTRAINTS and critical: + # TODO: remove this obviously. + warnings.warn( + "Extension support is not fully implemented. A basic " + "constraints extension with the critical flag was seen and" + " IGNORED." + ) + elif critical: + raise x509.UnsupportedExtension( + "{0} is not currently supported".format(oid), oid + ) + else: + # Unsupported non-critical extension, silently skipping for now + seen_oids.add(oid) + continue + + seen_oids.add(oid) + + return x509.Extensions(extensions) diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index 1ad7028d..29602b3e 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -43,6 +43,7 @@ _OID_NAMES = { "2.16.840.1.101.3.4.3.1": "dsa-with-sha224", "2.16.840.1.101.3.4.3.2": "dsa-with-sha256", "2.5.29.19": "basicConstraints", + "2.5.29.15": "keyUsage", } @@ -65,6 +66,18 @@ class InvalidVersion(Exception): self.parsed_version = parsed_version +class DuplicateExtension(Exception): + def __init__(self, msg, oid): + super(DuplicateExtension, self).__init__(msg) + self.oid = oid + + +class UnsupportedExtension(Exception): + def __init__(self, msg, oid): + super(UnsupportedExtension, self).__init__(msg) + self.oid = oid + + class NameAttribute(object): def __init__(self, oid, value): if not isinstance(oid, ObjectIdentifier): @@ -113,6 +126,9 @@ class ObjectIdentifier(object): _OID_NAMES.get(self._dotted_string, "Unknown OID") ) + def __hash__(self): + return hash(self.dotted_string) + dotted_string = utils.read_only_property("_dotted_string") @@ -139,9 +155,21 @@ class Name(object): return len(self._attributes) +OID_KEY_USAGE = ObjectIdentifier("2.5.29.15") OID_BASIC_CONSTRAINTS = ObjectIdentifier("2.5.29.19") +class Extensions(object): + def __init__(self, extensions): + self._extensions = extensions + + def __iter__(self): + return iter(self._extensions) + + def __len__(self): + return len(self._extensions) + + class Extension(object): def __init__(self, oid, critical, value): if not isinstance(oid, ObjectIdentifier): -- cgit v1.2.3