aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/x509/reference.rst21
-rw-r--r--src/cryptography/x509/__init__.py3
-rw-r--r--src/cryptography/x509/extensions.py31
-rw-r--r--tests/test_x509_ext.py51
4 files changed, 105 insertions, 1 deletions
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
index bbea490e..14727e76 100644
--- a/docs/x509/reference.rst
+++ b/docs/x509/reference.rst
@@ -1880,6 +1880,27 @@ X.509 Extensions
:type: int
+.. class:: UnrecognizedExtension
+
+ .. versionadded:: 1.2
+
+ A generic extension class used to hold the raw value of **non-critical**
+ extensions that ``cryptography`` does not know how to parse. Extensions
+ marked critical will still raise
+ :class:`~cryptography.x509.UnsupportedExtension`.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns the OID associated with this extension.
+
+ .. attribute:: value
+
+ :type: byte
+
+ Returns the DER encoded bytes payload of the extension.
+
.. class:: CertificatePolicies(policies)
.. versionadded:: 0.9
diff --git a/src/cryptography/x509/__init__.py b/src/cryptography/x509/__init__.py
index dc19161e..a1deb7f4 100644
--- a/src/cryptography/x509/__init__.py
+++ b/src/cryptography/x509/__init__.py
@@ -21,7 +21,7 @@ from cryptography.x509.extensions import (
InhibitAnyPolicy, InvalidityDate, IssuerAlternativeName, KeyUsage,
NameConstraints, NoticeReference, OCSPNoCheck, PolicyInformation,
ReasonFlags, SubjectAlternativeName, SubjectKeyIdentifier,
- UnsupportedExtension, UserNotice
+ UnrecognizedExtension, UnsupportedExtension, UserNotice
)
from cryptography.x509.general_name import (
DNSName, DirectoryName, GeneralName, IPAddress, OtherName, RFC822Name,
@@ -169,4 +169,5 @@ __all__ = [
"CertificateIssuer",
"CRLReason",
"InvalidityDate",
+ "UnrecognizedExtension",
]
diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py
index 4e7a53b6..0c5b5523 100644
--- a/src/cryptography/x509/extensions.py
+++ b/src/cryptography/x509/extensions.py
@@ -1065,3 +1065,34 @@ class InvalidityDate(object):
return hash(self.invalidity_date)
invalidity_date = utils.read_only_property("_invalidity_date")
+
+
+@utils.register_interface(ExtensionType)
+class UnrecognizedExtension(object):
+ def __init__(self, oid, value):
+ if not isinstance(oid, ObjectIdentifier):
+ raise TypeError("oid must be an ObjectIdentifier")
+ self._oid = oid
+ self._value = value
+
+ oid = utils.read_only_property("_oid")
+ value = utils.read_only_property("_value")
+
+ def __repr__(self):
+ return (
+ "<UnrecognizedExtension(oid={0.oid}, value={0.value!r})>".format(
+ self
+ )
+ )
+
+ def __eq__(self, other):
+ if not isinstance(other, UnrecognizedExtension):
+ return NotImplemented
+
+ return self.oid == other.oid and self.value == other.value
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __hash__(self):
+ return hash((self.oid, self.value))
diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py
index 7cd24a69..258be12d 100644
--- a/tests/test_x509_ext.py
+++ b/tests/test_x509_ext.py
@@ -75,6 +75,57 @@ class TestExtension(object):
assert ext1 != object()
+class TestUnrecognizedExtension(object):
+ def test_invalid_oid(self):
+ with pytest.raises(TypeError):
+ x509.UnrecognizedExtension("notanoid", b"somedata")
+
+ def test_eq(self):
+ ext1 = x509.UnrecognizedExtension(
+ x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x01"
+ )
+ ext2 = x509.UnrecognizedExtension(
+ x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x01"
+ )
+ assert ext1 == ext2
+
+ def test_ne(self):
+ ext1 = x509.UnrecognizedExtension(
+ x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x01"
+ )
+ ext2 = x509.UnrecognizedExtension(
+ x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x02"
+ )
+ ext3 = x509.UnrecognizedExtension(
+ x509.ObjectIdentifier("1.2.3.5"), b"\x03\x02\x01"
+ )
+ assert ext1 != ext2
+ assert ext1 != ext3
+ assert ext1 != object()
+
+ def test_repr(self):
+ ext1 = x509.UnrecognizedExtension(
+ x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x01"
+ )
+ assert repr(ext1) == (
+ "<UnrecognizedExtension(oid=<ObjectIdentifier(oid=1.2.3.4, name="
+ "Unknown OID)>, value='\\x03\\x02\\x01')>"
+ )
+
+ def test_hash(self):
+ ext1 = x509.UnrecognizedExtension(
+ x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x01"
+ )
+ ext2 = x509.UnrecognizedExtension(
+ x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x01"
+ )
+ ext3 = x509.UnrecognizedExtension(
+ x509.ObjectIdentifier("1.2.3.5"), b"\x03\x02\x01"
+ )
+ assert hash(ext1) == hash(ext2)
+ assert hash(ext1) != hash(ext3)
+
+
class TestCertificateIssuer(object):
def test_iter_names(self):
ci = x509.CertificateIssuer([