From 678c599aa0c1764eb01c50d2848d4aa5d0b51e96 Mon Sep 17 00:00:00 2001 From: lipengyu Date: Wed, 14 Oct 2026 10:29:08 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20TLS=201.0=E2=80=931.2=20availability=20de?= =?UTF-8?q?tection=20with=20OpenSSL=204.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenSSL 4.0 removed the version-specific methods but still supports TLS 1.0–1.2 through TLS_method(). Stop reporting these versions as unavailable, and expose legacy PROTOCOL_TLSv1* constants only when their corresponding methods exist. --- Lib/test/test_ssl.py | 2 ++ .../2026-10-14-10-26-10.gh-issue-159387.xMbQbB.rst | 2 ++ Modules/_ssl.c | 11 +++++------ 3 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-10-14-10-26-10.gh-issue-159387.xMbQbB.rst diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index d8eebc33deebfa..558c8830639f4c 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -4025,6 +4025,8 @@ def test_protocol_tlsv1_1(self): try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False) @requires_tls_version('TLSv1_2') + @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_TLSv1_2'), + 'needs ssl.PROTOCOL_TLSv1_2') def test_protocol_tlsv1_2(self): """Connecting to a TLSv1.2 server with various client options. Testing against older TLS versions.""" diff --git a/Misc/NEWS.d/next/Library/2026-10-14-10-26-10.gh-issue-159387.xMbQbB.rst b/Misc/NEWS.d/next/Library/2026-10-14-10-26-10.gh-issue-159387.xMbQbB.rst new file mode 100644 index 00000000000000..fddef6e097ba5c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-14-10-26-10.gh-issue-159387.xMbQbB.rst @@ -0,0 +1,2 @@ +Fix :mod:`ssl` reporting TLS 1.0, 1.1, and 1.2 as unavailable when built +with OpenSSL 4.0, despite support for these protocol versions. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 5fc029af24821a..63872df65ba9fe 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -142,10 +142,9 @@ static void _PySSLFixErrno(void) { #endif #if (OPENSSL_VERSION_NUMBER >= 0x40000000L) +/* OpenSSL 4.0 removed SSLv3 and the version-specific methods, + * but TLS 1.0, 1.1 and 1.2 are still available via TLS_method(). */ # 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 @@ -7012,13 +7011,13 @@ 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 +#if !defined(OPENSSL_NO_TLS1) && !defined(OPENSSL_NO_TLS1_METHOD) ADD_INT_CONST("PROTOCOL_TLSv1", PY_SSL_VERSION_TLS1); #endif -#ifndef OPENSSL_NO_TLS1_1 +#if !defined(OPENSSL_NO_TLS1_1) && !defined(OPENSSL_NO_TLS1_1_METHOD) ADD_INT_CONST("PROTOCOL_TLSv1_1", PY_SSL_VERSION_TLS1_1); #endif -#ifndef OPENSSL_NO_TLS1_2 +#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_2_METHOD) ADD_INT_CONST("PROTOCOL_TLSv1_2", PY_SSL_VERSION_TLS1_2); #endif