gh-146207: Add support for OpenSSL 4.0.0 alpha1 (#146217)

OpenSSL 4.0.0 alpha1 removed these functions:

* SSLv3_method()
* TLSv1_method()
* TLSv1_1_method()
* TLSv1_2_method()

Other changes:

* Update test_openssl_version().
* Update multissltests.py for OpenSSL 4.
* Add const qualifier to fix compiler warnings.

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
Victor StinnerandBénédikt Tran authored and GitHub committed 2026-03-25 07:44:47 +01:00
1 parent 08f6b33bf3
commit 3364e7e62f
4 files changed
+58 -31

No files matched your search

+28 -24
View File
@@ -395,7 +395,7 @@ class BasicSocketTests(unittest.TestCase):
ssl.OP_NO_COMPRESSION
self.assertEqual(ssl.HAS_SNI, True)
self.assertEqual(ssl.HAS_ECDH, True)
self.assertEqual(ssl.HAS_TLSv1_2, True)
self.assertIsInstance(ssl.HAS_TLSv1_2, bool)
self.assertEqual(ssl.HAS_TLSv1_3, True)
ssl.OP_NO_SSLv2
ssl.OP_NO_SSLv3
@@ -586,11 +586,11 @@ class BasicSocketTests(unittest.TestCase):
# Some sanity checks follow
# >= 1.1.1
self.assertGreaterEqual(n, 0x10101000)
# < 4.0
self.assertLess(n, 0x40000000)
# < 5.0
self.assertLess(n, 0x50000000)
major, minor, fix, patch, status = t
self.assertGreaterEqual(major, 1)
self.assertLess(major, 4)
self.assertLess(major, 5)
self.assertGreaterEqual(minor, 0)
self.assertLess(minor, 256)
self.assertGreaterEqual(fix, 0)
@@ -656,12 +656,14 @@ class BasicSocketTests(unittest.TestCase):
ssl.OP_NO_TLSv1_2,
ssl.OP_NO_TLSv1_3
]
protocols = [
ssl.PROTOCOL_TLSv1,
ssl.PROTOCOL_TLSv1_1,
ssl.PROTOCOL_TLSv1_2,
ssl.PROTOCOL_TLS
]
protocols = []
if hasattr(ssl, 'PROTOCOL_TLSv1'):
protocols.append(ssl.PROTOCOL_TLSv1)
if hasattr(ssl, 'PROTOCOL_TLSv1_1'):
protocols.append(ssl.PROTOCOL_TLSv1_1)
if hasattr(ssl, 'PROTOCOL_TLSv1_2'):
protocols.append(ssl.PROTOCOL_TLSv1_2)
protocols.append(ssl.PROTOCOL_TLS)
versions = [
ssl.TLSVersion.SSLv3,
ssl.TLSVersion.TLSv1,
@@ -1205,6 +1207,7 @@ class ContextTests(unittest.TestCase):
ssl.TLSVersion.TLSv1,
ssl.TLSVersion.TLSv1_1,
ssl.TLSVersion.TLSv1_2,
ssl.TLSVersion.TLSv1_3,
ssl.TLSVersion.SSLv3,
}
)
@@ -1218,7 +1221,7 @@ class ContextTests(unittest.TestCase):
with self.assertRaises(ValueError):
ctx.minimum_version = 42
if has_tls_protocol(ssl.PROTOCOL_TLSv1_1):
if has_tls_protocol('PROTOCOL_TLSv1_1'):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
self.assertIn(
@@ -1675,23 +1678,24 @@ class ContextTests(unittest.TestCase):
self.assertFalse(ctx.check_hostname)
self._assert_context_options(ctx)
if has_tls_protocol(ssl.PROTOCOL_TLSv1):
if has_tls_protocol('PROTOCOL_TLSv1'):
with warnings_helper.check_warnings():
ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
self._assert_context_options(ctx)
with warnings_helper.check_warnings():
ctx = ssl._create_stdlib_context(
ssl.PROTOCOL_TLSv1_2,
cert_reqs=ssl.CERT_REQUIRED,
check_hostname=True
)
self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1_2)
self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
self.assertTrue(ctx.check_hostname)
self._assert_context_options(ctx)
if has_tls_protocol('PROTOCOL_TLSv1_2'):
with warnings_helper.check_warnings():
ctx = ssl._create_stdlib_context(
ssl.PROTOCOL_TLSv1_2,
cert_reqs=ssl.CERT_REQUIRED,
check_hostname=True
)
self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1_2)
self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
self.assertTrue(ctx.check_hostname)
self._assert_context_options(ctx)
ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
@@ -3654,10 +3658,10 @@ class ThreadedTests(unittest.TestCase):
client_options=ssl.OP_NO_TLSv1_2)
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
if has_tls_protocol(ssl.PROTOCOL_TLSv1):
if has_tls_protocol('PROTOCOL_TLSv1'):
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
if has_tls_protocol(ssl.PROTOCOL_TLSv1_1):
if has_tls_protocol('PROTOCOL_TLSv1_1'):
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
+22 -5
View File
@@ -164,6 +164,17 @@ static void _PySSLFixErrno(void) {
#error Unsupported OpenSSL version
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x40000000L)
# define OPENSSL_NO_SSL3
# define OPENSSL_NO_TLS1
# define OPENSSL_NO_TLS1_1
# define OPENSSL_NO_TLS1_2
# define OPENSSL_NO_SSL3_METHOD
# define OPENSSL_NO_TLS1_METHOD
# define OPENSSL_NO_TLS1_1_METHOD
# define OPENSSL_NO_TLS1_2_METHOD
#endif
/* OpenSSL API 1.1.0+ does not include version methods */
#ifndef OPENSSL_NO_SSL3_METHOD
extern const SSL_METHOD *SSLv3_method(void);
@@ -1151,7 +1162,7 @@ _asn1obj2py(_sslmodulestate *state, const ASN1_OBJECT *name, int no_name)
static PyObject *
_create_tuple_for_attribute(_sslmodulestate *state,
ASN1_OBJECT *name, ASN1_STRING *value)
const ASN1_OBJECT *name, const ASN1_STRING *value)
{
Py_ssize_t buflen;
PyObject *pyattr;
@@ -1180,16 +1191,16 @@ _create_tuple_for_attribute(_sslmodulestate *state,
}
static PyObject *
_create_tuple_for_X509_NAME (_sslmodulestate *state, X509_NAME *xname)
_create_tuple_for_X509_NAME(_sslmodulestate *state, const X509_NAME *xname)
{
PyObject *dn = NULL; /* tuple which represents the "distinguished name" */
PyObject *rdn = NULL; /* tuple to hold a "relative distinguished name" */
PyObject *rdnt;
PyObject *attr = NULL; /* tuple to hold an attribute */
int entry_count = X509_NAME_entry_count(xname);
X509_NAME_ENTRY *entry;
ASN1_OBJECT *name;
ASN1_STRING *value;
const X509_NAME_ENTRY *entry;
const ASN1_OBJECT *name;
const ASN1_STRING *value;
int index_counter;
int rdn_level = -1;
int retcode;
@@ -6967,9 +6978,15 @@ sslmodule_init_constants(PyObject *m)
ADD_INT_CONST("PROTOCOL_TLS", PY_SSL_VERSION_TLS);
ADD_INT_CONST("PROTOCOL_TLS_CLIENT", PY_SSL_VERSION_TLS_CLIENT);
ADD_INT_CONST("PROTOCOL_TLS_SERVER", PY_SSL_VERSION_TLS_SERVER);
#ifndef OPENSSL_NO_TLS1
ADD_INT_CONST("PROTOCOL_TLSv1", PY_SSL_VERSION_TLS1);
#endif
#ifndef OPENSSL_NO_TLS1_1
ADD_INT_CONST("PROTOCOL_TLSv1_1", PY_SSL_VERSION_TLS1_1);
#endif
#ifndef OPENSSL_NO_TLS1_2
ADD_INT_CONST("PROTOCOL_TLSv1_2", PY_SSL_VERSION_TLS1_2);
#endif
#define ADD_OPTION(NAME, VALUE) if (sslmodule_add_option(m, NAME, (VALUE)) < 0) return -1
+2 -1
View File
@@ -128,7 +128,8 @@ _ssl_Certificate_get_info_impl(PySSLCertificate *self)
}
static PyObject*
_x509name_print(_sslmodulestate *state, X509_NAME *name, int indent, unsigned long flags)
_x509name_print(_sslmodulestate *state, const X509_NAME *name,
int indent, unsigned long flags)
{
PyObject *res;
BIO *biobuf;
+6 -1
View File
@@ -429,9 +429,11 @@ class BuildOpenSSL(AbstractBuilder):
def _post_install(self):
if self.version.startswith("3."):
self._post_install_3xx()
elif self.version.startswith("4."):
self._post_install_4xx()
def _build_src(self, config_args=()):
if self.version.startswith("3."):
if self.version.startswith(("3.", "4.")):
config_args += ("enable-fips",)
super()._build_src(config_args)
@@ -447,6 +449,9 @@ class BuildOpenSSL(AbstractBuilder):
lib64 = self.lib_dir + "64"
os.symlink(lib64, self.lib_dir)
def _post_install_4xx(self):
self._post_install_3xx()
@property
def short_version(self):
"""Short version for OpenSSL download URL"""