Repository: pyca/pyopenssl
Pull request #1336 (2024-08-04 18:53:25)

Deprecated passing X509 objects to add_extra_chain_cert
Added support for passing cryptography.x509.Certificate


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5b80ee3..3eb11e1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -16,8 +16,8 @@ jobs:
           - {VERSION: "3.10", TOXENV: "py310"}
           - {VERSION: "3.11", TOXENV: "py311"}
           - {VERSION: "3.12", TOXENV: "py312"}
-          - {VERSION: "pypy-3.8", TOXENV: "pypy3"}
           - {VERSION: "pypy-3.9", TOXENV: "pypy3"}
+          - {VERSION: "pypy-3.10", TOXENV: "pypy3"}
           - {VERSION: "3.11", TOXENV: "py311-useWheel", OS: "windows-2022" }
           # -cryptographyMain
           - {VERSION: "3.7", TOXENV: "py37-cryptographyMain"}
@@ -26,8 +26,8 @@ jobs:
           - {VERSION: "3.10", TOXENV: "py310-cryptographyMain"}
           - {VERSION: "3.11", TOXENV: "py311-cryptographyMain"}
           - {VERSION: "3.12", TOXENV: "py312-cryptographyMain"}
-          - {VERSION: "pypy-3.8", TOXENV: "pypy3-cryptographyMain"}
           - {VERSION: "pypy-3.9", TOXENV: "pypy3-cryptographyMain"}
+          - {VERSION: "pypy-3.10", TOXENV: "pypy3-cryptographyMain"}
           # -cryptographyMinimum
           - {VERSION: "3.7", TOXENV: "py37-cryptographyMinimum"}
           - {VERSION: "3.8", TOXENV: "py38-cryptographyMinimum"}
@@ -35,7 +35,7 @@ jobs:
           - {VERSION: "3.10", TOXENV: "py310-cryptographyMinimum"}
           - {VERSION: "3.11", TOXENV: "py311-cryptographyMinimum"}
           - {VERSION: "3.12", TOXENV: "py312-cryptographyMinimum"}
-          - {VERSION: "pypy-3.8", TOXENV: "pypy3-cryptographyMinimum"}
+          - {VERSION: "pypy-3.10", TOXENV: "pypy3-cryptographyMinimum"}
           # Cryptography wheels
           - {VERSION: "3.9", TOXENV: "py39-cryptographyMinimum-useWheel"}
           - {VERSION: "3.9", TOXENV: "py39-useWheel"}
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 5ac7029..587c8fd 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -15,7 +15,7 @@ Deprecations:
 
 - Deprecated ``OpenSSL.rand`` - callers should use ``os.urandom()`` instead.
 - Deprecated ``OpenSSL.crypto.get_elliptic_curves`` and ``OpenSSL.crypto.get_elliptic_curve``, as well as passing the reult of them to ``OpenSSL.SSL.Context.set_tmp_ecdh``, users should instead pass curves from ``cryptography``.
-- Deprecated passing ``X509`` objects to ``OpenSSL.SSL.Context.use_certificate`` and ``OpenSSL.SSL.Connection.use_certificate``, users should instead pass ``cryptography.x509.Certificate`` instances. This is in preparation for deprecating pyOpenSSL's ``X509`` entirely.
+- Deprecated passing ``X509`` objects to ``OpenSSL.SSL.Context.use_certificate``, ``OpenSSL.SSL.Connection.use_certificate``, and ``OpenSSL.SSL.Context.add_extra_chain_cert``, users should instead pass ``cryptography.x509.Certificate`` instances. This is in preparation for deprecating pyOpenSSL's ``X509`` entirely.
 
 Changes:
 ^^^^^^^^
diff --git a/src/OpenSSL/SSL.py b/src/OpenSSL/SSL.py
index 5946330..5bd2ad3 100644
--- a/src/OpenSSL/SSL.py
+++ b/src/OpenSSL/SSL.py
@@ -1151,7 +1151,7 @@ class Context:
         if not use_result:
             _raise_current_error()
 
-    def add_extra_chain_cert(self, certobj: X509) -> None:
+    def add_extra_chain_cert(self, certobj: X509 | x509.Certificate) -> None:
         """
         Add certificate to chain
 
@@ -1159,7 +1159,16 @@ class Context:
         :return: None
         """
         if not isinstance(certobj, X509):
-            raise TypeError("certobj must be an X509 instance")
+            certobj = X509.from_cryptography(certobj)
+        else:
+            warnings.warn(
+                (
+                    "Passing pyOpenSSL X509 objects is deprecated. You "
+                    "should use a cryptography.x509.Certificate instead."
+                ),
+                DeprecationWarning,
+                stacklevel=2,
+            )
 
         copy = _lib.X509_dup(certobj._x509)
         add_result = _lib.SSL_CTX_add_extra_chain_cert(self._context, copy)


Test patch:
diff --git a/tests/test_crypto.py b/tests/test_crypto.py
index 253e602..91cca32 100644
--- a/tests/test_crypto.py
+++ b/tests/test_crypto.py
@@ -4050,9 +4050,6 @@ class TestEllipticCurveEquality(EqualityTestsMixin):
 
     curve_factory = EllipticCurveFactory()
 
-    if curve_factory.curve_name is None:
-        skip = "There are no curves available there can be no curve objects."
-
     def anInstance(self):
         """
         Get the curve object for an arbitrary curve supported by the system.
@@ -4075,9 +4072,6 @@ class TestEllipticCurveHash:
 
     curve_factory = EllipticCurveFactory()
 
-    if curve_factory.curve_name is None:
-        skip = "There are no curves available there can be no curve objects."
-
     def test_contains(self):
         """
         The ``in`` operator reports that a `set` containing a curve does
diff --git a/tests/test_ssl.py b/tests/test_ssl.py
index 7173655..392673e 100644
--- a/tests/test_ssl.py
+++ b/tests/test_ssl.py
@@ -2586,7 +2586,7 @@ class TestConnection:
         serverContext.use_privatekey(skey)
         serverContext.use_certificate(scert)
         serverContext.add_extra_chain_cert(icert)
-        serverContext.add_extra_chain_cert(cacert)
+        serverContext.add_extra_chain_cert(cacert.to_cryptography())
         server = Connection(serverContext, None)
         server.set_accept_state()
 
@@ -2630,7 +2630,7 @@ class TestConnection:
         serverContext = Context(SSLv23_METHOD)
         serverContext.use_privatekey(skey)
         serverContext.use_certificate(scert)
-        serverContext.add_extra_chain_cert(icert)
+        serverContext.add_extra_chain_cert(icert.to_cryptography())
         serverContext.add_extra_chain_cert(cacert)
         server = Connection(serverContext, None)
         server.set_accept_state()
@@ -4506,15 +4506,9 @@ class TestDTLS:
 
         # Check that the MTU set/query functions are doing *something*
         c.set_ciphertext_mtu(1000)
-        try:
-            assert 500 < c.get_cleartext_mtu() < 1000
-        except NotImplementedError:  # OpenSSL 1.1.0 and earlier
-            pass
+        assert 500 < c.get_cleartext_mtu() < 1000
         c.set_ciphertext_mtu(500)
-        try:
-            assert 0 < c.get_cleartext_mtu() < 500
-        except NotImplementedError:  # OpenSSL 1.1.0 and earlier
-            pass
+        assert 0 < c.get_cleartext_mtu() < 500
 
     def test_it_works_at_all(self):
         self._test_handshake_and_data(srtp_profile=None)