From 2a3da59244e8187a4bdf205fc71ef727a4c4ed97 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 28 Mar 2025 12:55:38 +0000 Subject: [PATCH 1/5] gh-131423: Update to OpenSSL 3.0.16. The bin tag is 3.0.16.1 because we rebuilt without uplink support to fix gh-131804. This PR also prevents making calls that are now unsafe without uplink, and updates the tests to property interpret these failures as unsupported. --- Lib/test/test_ssl.py | 52 +++++++++++++++++++++++++++--------- Modules/_ssl.c | 13 +++++++++ Modules/_ssl/debughelpers.c | 7 +++++ PCbuild/_ssl.vcxproj | 3 --- PCbuild/_ssl.vcxproj.filters | 3 --- PCbuild/get_externals.bat | 4 +-- PCbuild/openssl.vcxproj | 26 +----------------- 7 files changed, 62 insertions(+), 46 deletions(-) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 9863f3ffe97656..a69d89e81438a6 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1321,10 +1321,14 @@ def test_load_verify_cadata(self): with self.assertRaises(ssl.SSLError): ctx.load_verify_locations(cadata=cacert_der + b"A") - @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows") def test_load_dh_params(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) - ctx.load_dh_params(DHFILE) + try: + ctx.load_dh_params(DHFILE) + except RuntimeError: + if Py_DEBUG_WIN32: + self.skipTest("not supported on Win32 debug build") + raise ctx.load_dh_params(BYTES_DHFILE) self.assertRaises(TypeError, ctx.load_dh_params) self.assertRaises(TypeError, ctx.load_dh_params, None) @@ -1648,12 +1652,17 @@ def test_str(self): self.assertEqual(str(e), "foo") self.assertEqual(e.errno, 1) - @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows") def test_lib_reason(self): # Test the library and reason attributes ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - with self.assertRaises(ssl.SSLError) as cm: - ctx.load_dh_params(CERTFILE) + try: + with self.assertRaises(ssl.SSLError) as cm: + ctx.load_dh_params(CERTFILE) + except RuntimeError: + if Py_DEBUG_WIN32: + self.skipTest("not supported on Win32 debug build") + raise + self.assertEqual(cm.exception.library, 'PEM') regex = "(NO_START_LINE|UNSUPPORTED_PUBLIC_KEY_TYPE)" self.assertRegex(cm.exception.reason, regex) @@ -4032,13 +4041,17 @@ def test_no_legacy_server_connect(self): chatty=True, connectionchatty=True, sni_name=hostname) - @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows") def test_dh_params(self): # Check we can get a connection with ephemeral Diffie-Hellman client_context, server_context, hostname = testing_context() # test scenario needs TLS <= 1.2 client_context.maximum_version = ssl.TLSVersion.TLSv1_2 - server_context.load_dh_params(DHFILE) + try: + server_context.load_dh_params(DHFILE) + except RuntimeError: + if Py_DEBUG_WIN32: + self.skipTest("not supported on Win32 debug build") + raise server_context.set_ciphers("kEDH") server_context.maximum_version = ssl.TLSVersion.TLSv1_2 stats = server_params_test(client_context, server_context, @@ -4819,14 +4832,18 @@ def keylog_lines(self, fname=os_helper.TESTFN): return len(list(f)) @requires_keylog - @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows") def test_keylog_defaults(self): self.addCleanup(os_helper.unlink, os_helper.TESTFN) ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) self.assertEqual(ctx.keylog_filename, None) self.assertFalse(os.path.isfile(os_helper.TESTFN)) - ctx.keylog_filename = os_helper.TESTFN + try: + ctx.keylog_filename = os_helper.TESTFN + except RuntimeError: + if Py_DEBUG_WIN32: + self.skipTest("not supported on Win32 debug build") + raise self.assertEqual(ctx.keylog_filename, os_helper.TESTFN) self.assertTrue(os.path.isfile(os_helper.TESTFN)) self.assertEqual(self.keylog_lines(), 1) @@ -4843,12 +4860,17 @@ def test_keylog_defaults(self): ctx.keylog_filename = 1 @requires_keylog - @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows") def test_keylog_filename(self): self.addCleanup(os_helper.unlink, os_helper.TESTFN) client_context, server_context, hostname = testing_context() - client_context.keylog_filename = os_helper.TESTFN + try: + client_context.keylog_filename = os_helper.TESTFN + except RuntimeError: + if Py_DEBUG_WIN32: + self.skipTest("not supported on Win32 debug build") + raise + server = ThreadedEchoServer(context=server_context, chatty=False) with server: with client_context.wrap_socket(socket.socket(), @@ -4881,7 +4903,6 @@ def test_keylog_filename(self): @requires_keylog @unittest.skipIf(sys.flags.ignore_environment, "test is not compatible with ignore_environment") - @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows") def test_keylog_env(self): self.addCleanup(os_helper.unlink, os_helper.TESTFN) with unittest.mock.patch.dict(os.environ): @@ -4891,7 +4912,12 @@ def test_keylog_env(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) self.assertEqual(ctx.keylog_filename, None) - ctx = ssl.create_default_context() + try: + ctx = ssl.create_default_context() + except RuntimeError: + if Py_DEBUG_WIN32: + self.skipTest("not supported on Win32 debug build") + raise self.assertEqual(ctx.keylog_filename, os_helper.TESTFN) ctx = ssl._create_stdlib_context() diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 071524fa9d4195..dd9fdba46b04a7 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -73,6 +73,13 @@ # error "OPENSSL_THREADS is not defined, Python requires thread-safe OpenSSL" #endif +#ifdef FORCE_ASSERTS +#ifdef NDEBUG +#undef NDEBUG +#define _DEBUG +#endif +#include +#endif /* FORCE_ASSERTS */ struct py_ssl_error_code { @@ -4427,6 +4434,12 @@ _ssl__SSLContext_load_dh_params_impl(PySSLContext *self, PyObject *filepath) FILE *f; DH *dh; +#if defined(MS_WINDOWS) && defined(_DEBUG) + PyErr_SetString(PyExc_RuntimeError, + "unable to load_dh_params on Windows debug build"); + return NULL; +#endif + f = Py_fopen(filepath, "rb"); if (f == NULL) return NULL; diff --git a/Modules/_ssl/debughelpers.c b/Modules/_ssl/debughelpers.c index e4ff8b6e255adb..4eaea642e83bfa 100644 --- a/Modules/_ssl/debughelpers.c +++ b/Modules/_ssl/debughelpers.c @@ -174,6 +174,13 @@ _PySSLContext_set_keylog_filename(PyObject *op, PyObject *arg, { PySSLContext *self = PySSLContext_CAST(op); FILE *fp; + +#if defined(MS_WINDOWS) && defined(_DEBUG) + PyErr_SetString(PyExc_RuntimeError, + "unable to set_keylog_filename on Windows debug build"); + return -1; +#endif + /* Reset variables and callback first */ SSL_CTX_set_keylog_callback(self->ctx, NULL); Py_CLEAR(self->keylog_filename); diff --git a/PCbuild/_ssl.vcxproj b/PCbuild/_ssl.vcxproj index d4e1affab031d7..ce21f992ff8510 100644 --- a/PCbuild/_ssl.vcxproj +++ b/PCbuild/_ssl.vcxproj @@ -99,9 +99,6 @@ - - _CRT_SECURE_NO_WARNINGS;$(PreprocessorDefinitions) - diff --git a/PCbuild/_ssl.vcxproj.filters b/PCbuild/_ssl.vcxproj.filters index 716a69a41af351..8aef9e03fcc429 100644 --- a/PCbuild/_ssl.vcxproj.filters +++ b/PCbuild/_ssl.vcxproj.filters @@ -12,9 +12,6 @@ Source Files - - Source Files - diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index d7cb3f0a4fedbd..4e4d5c6b53aec9 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -53,7 +53,7 @@ echo.Fetching external libraries... set libraries= set libraries=%libraries% bzip2-1.0.8 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.4.4 -if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-3.0.15 +if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-3.0.16 set libraries=%libraries% mpdecimal-4.0.0 set libraries=%libraries% sqlite-3.45.3.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.15.0 @@ -77,7 +77,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.4.4 -if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-3.0.15 +if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-3.0.16.1 if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.15.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 diff --git a/PCbuild/openssl.vcxproj b/PCbuild/openssl.vcxproj index 0da6f6749584f1..7ca750dda8f5ef 100644 --- a/PCbuild/openssl.vcxproj +++ b/PCbuild/openssl.vcxproj @@ -67,47 +67,23 @@ set VCINSTALLDIR=$(VCInstallDir) if not exist "$(IntDir.TrimEnd('\'))" mkdir "$(IntDir.TrimEnd('\'))" cd /D "$(IntDir.TrimEnd('\'))" -$(Perl) "$(opensslDir)\configure" $(OpenSSLPlatform) no-asm +$(Perl) "$(opensslDir)\configure" $(OpenSSLPlatform) no-asm no-uplink nmake - - - $(opensslDir)\ms\uplink.c - ((h = GetModuleHandle(NULL)) == NULL) - ((h = GetModuleHandleA("_ssl.pyd")) == NULL) if ((h = GetModuleHandleA("_ssl_d.pyd")) == NULL) if ((h = GetModuleHandle(NULL)) == NULL /*patched*/) - - - - <_Original>$([System.IO.File]::ReadAllText($(Uplink))) - <_Patched>$(_Original.Replace($(BeforePatch), $(AfterPatch))) - false - true - - - - - - <_Built Include="$(opensslDir)\LICENSE" /> <_Built Include="$(IntDir)\libcrypto.lib;$(IntDir)\libcrypto-*.dll;$(IntDir)\libcrypto-*.pdb" /> <_Built Include="$(IntDir)\libssl.lib;$(IntDir)\libssl-*.dll;$(IntDir)\libssl-*.pdb" /> - <_AppLink Include="$(opensslDir)\ms\applink.c" /> <_Include Include="$(opensslDir)\Include\openssl\*.h" /> <_Include Include="$(IntDir)\include\openssl\*.h" /> - From 37c1d10f5741b8f03a6b8eb9048c3dba25c65df5 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 28 Mar 2025 13:02:59 +0000 Subject: [PATCH 2/5] Remove unused code from ssl.c --- Modules/_ssl.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Modules/_ssl.c b/Modules/_ssl.c index dd9fdba46b04a7..5572bd198c7679 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -73,13 +73,6 @@ # error "OPENSSL_THREADS is not defined, Python requires thread-safe OpenSSL" #endif -#ifdef FORCE_ASSERTS -#ifdef NDEBUG -#undef NDEBUG -#define _DEBUG -#endif -#include -#endif /* FORCE_ASSERTS */ struct py_ssl_error_code { From aa147604d3fb98c628ce7fdebeb475459833c319 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 28 Mar 2025 13:23:01 +0000 Subject: [PATCH 3/5] Add NEWS --- .../Windows/2025-03-28-13-22-55.gh-issue-131423.vI-LqV.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Windows/2025-03-28-13-22-55.gh-issue-131423.vI-LqV.rst diff --git a/Misc/NEWS.d/next/Windows/2025-03-28-13-22-55.gh-issue-131423.vI-LqV.rst b/Misc/NEWS.d/next/Windows/2025-03-28-13-22-55.gh-issue-131423.vI-LqV.rst new file mode 100644 index 00000000000000..6db1df77ad0108 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2025-03-28-13-22-55.gh-issue-131423.vI-LqV.rst @@ -0,0 +1,3 @@ +Update bundled version of OpenSSL to 3.0.16. The new build also disables +uplink support, which may be relevant to embedders but has no impact on +normal use. From dac6cfb18e9ed0bf4938e7c67ec7b2b1b1cdc32f Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 28 Mar 2025 13:31:21 +0000 Subject: [PATCH 4/5] Fix directory and SBOM --- Misc/externals.spdx.json | 8 ++++---- PCbuild/python.props | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Misc/externals.spdx.json b/Misc/externals.spdx.json index 5bd5177b613924..1ff2c8d7477313 100644 --- a/Misc/externals.spdx.json +++ b/Misc/externals.spdx.json @@ -70,21 +70,21 @@ "checksums": [ { "algorithm": "SHA256", - "checksumValue": "1550c87996a0858474a9dd179deab2c55eb73726b9a140b32865b02fd3d8a86b" + "checksumValue": "6bb739ecddbd2cfb6d255eb5898437a9b5739277dee931338d3275bac5d96ba2" } ], - "downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/openssl-3.0.15.tar.gz", + "downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/openssl-3.0.16.tar.gz", "externalRefs": [ { "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:a:openssl:openssl:3.0.15:*:*:*:*:*:*:*", + "referenceLocator": "cpe:2.3:a:openssl:openssl:3.0.16:*:*:*:*:*:*:*", "referenceType": "cpe23Type" } ], "licenseConcluded": "NOASSERTION", "name": "openssl", "primaryPackagePurpose": "SOURCE", - "versionInfo": "3.0.15" + "versionInfo": "3.0.16" }, { "SPDXID": "SPDXRef-PACKAGE-sqlite", diff --git a/PCbuild/python.props b/PCbuild/python.props index d1c4b5bda6c3d3..d923bfab8a13b4 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -81,8 +81,8 @@ $(libffiDir)$(ArchName)\ $(libffiOutDir)include $(ExternalsDir)\mpdecimal-4.0.0\ - $(ExternalsDir)openssl-3.0.15\ - $(ExternalsDir)openssl-bin-3.0.15\$(ArchName)\ + $(ExternalsDir)openssl-3.0.16\ + $(ExternalsDir)openssl-bin-3.0.16.1\$(ArchName)\ $(opensslOutDir)include $(ExternalsDir)\nasm-2.11.06\ $(ExternalsDir)\zlib-1.3.1\ From 9296a9c09b197cefab33dc0cd9f187a6ee46c215 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 28 Mar 2025 14:05:44 +0000 Subject: [PATCH 5/5] Better grammar and fix for other test using test_dh_params --- Lib/test/audit-tests.py | 10 +++++++++- Lib/test/test_audit.py | 1 + Modules/_ssl.c | 4 ++-- Modules/_ssl/debughelpers.c | 4 ++-- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Lib/test/audit-tests.py b/Lib/test/audit-tests.py index 6b9b21cf7f6a3c..af18ac2bb29c62 100644 --- a/Lib/test/audit-tests.py +++ b/Lib/test/audit-tests.py @@ -208,7 +208,15 @@ def test_open(testfn): if not fn: continue with assertRaises(RuntimeError): - fn(*args) + try: + fn(*args) + except NotImplementedError: + if fn == load_dh_params: + # Not callable in some builds + load_dh_params = None + raise RuntimeError + else: + raise actual_mode = [(a[0], a[1]) for e, a in hook.seen if e == "open" and a[1]] actual_flag = [(a[0], a[2]) for e, a in hook.seen if e == "open" and not a[1]] diff --git a/Lib/test/test_audit.py b/Lib/test/test_audit.py index ddd9f951143df7..b49938cb5008f3 100644 --- a/Lib/test/test_audit.py +++ b/Lib/test/test_audit.py @@ -23,6 +23,7 @@ def run_test_in_subprocess(self, *args): with subprocess.Popen( [sys.executable, "-X utf8", AUDIT_TESTS_PY, *args], encoding="utf-8", + errors="backslashreplace", stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) as p: diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 5572bd198c7679..6615d6d0b99802 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -4428,8 +4428,8 @@ _ssl__SSLContext_load_dh_params_impl(PySSLContext *self, PyObject *filepath) DH *dh; #if defined(MS_WINDOWS) && defined(_DEBUG) - PyErr_SetString(PyExc_RuntimeError, - "unable to load_dh_params on Windows debug build"); + PyErr_SetString(PyExc_NotImplementedError, + "load_dh_params: unavailable on Windows debug build"); return NULL; #endif diff --git a/Modules/_ssl/debughelpers.c b/Modules/_ssl/debughelpers.c index 4eaea642e83bfa..7c0b4876f4353a 100644 --- a/Modules/_ssl/debughelpers.c +++ b/Modules/_ssl/debughelpers.c @@ -176,8 +176,8 @@ _PySSLContext_set_keylog_filename(PyObject *op, PyObject *arg, FILE *fp; #if defined(MS_WINDOWS) && defined(_DEBUG) - PyErr_SetString(PyExc_RuntimeError, - "unable to set_keylog_filename on Windows debug build"); + PyErr_SetString(PyExc_NotImplementedError, + "set_keylog_filename: unavailable on Windows debug build"); return -1; #endif