From 00464bbed66e5f64bdad7f930b315a88d5afccae Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 8 Jul 2022 15:20:15 +0200 Subject: gh-94199: Remove the ssl.wrap_socket() function (#94203) Remove the ssl.wrap_socket() function, deprecated in Python 3.7: instead, create a ssl.SSLContext object and call its sl.SSLContext.wrap_socket() method. Any package that still uses ssl.wrap_socket() is broken and insecure. The function neither sends a SNI TLS extension nor validates server hostname. Code is subject to CWE-295 : Improper Certificate Validation. --- Doc/whatsnew/3.12.rst | 9 +++++++ Lib/ssl.py | 30 ---------------------- Lib/test/test_ssl.py | 30 ---------------------- .../2022-06-24-10-39-56.gh-issue-94199.MIuckY.rst | 7 +++++ 4 files changed, 16 insertions(+), 60 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-06-24-10-39-56.gh-issue-94199.MIuckY.rst diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index a095baa..85b576c 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -304,6 +304,15 @@ Removed :pep:`451` for the rationale. (Contributed by Victor Stinner in :gh:`94379`.) +* Remove the :func:`ssl.wrap_socket` function, deprecated in Python 3.7: + instead, create a :class:`ssl.SSLContext` object and call its + :class:`ssl.SSLContext.wrap_socket` method. Any package that still uses + :func:`ssl.wrap_socket` is broken and insecure. The function neither sends a + SNI TLS extension nor validates server hostname. Code is subject to `CWE-295 + `_: Improper Certificate + Validation. + (Contributed by Victor Stinner in :gh:`94199`.) + Porting to Python 3.12 ====================== diff --git a/Lib/ssl.py b/Lib/ssl.py index 02359a1..1d58737 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -1357,36 +1357,6 @@ SSLContext.sslsocket_class = SSLSocket SSLContext.sslobject_class = SSLObject -def wrap_socket(sock, keyfile=None, certfile=None, - server_side=False, cert_reqs=CERT_NONE, - ssl_version=PROTOCOL_TLS, ca_certs=None, - do_handshake_on_connect=True, - suppress_ragged_eofs=True, - ciphers=None): - warnings.warn( - "ssl.wrap_socket() is deprecated, use SSLContext.wrap_socket()", - category=DeprecationWarning, - stacklevel=2 - ) - if server_side and not certfile: - raise ValueError("certfile must be specified for server-side " - "operations") - if keyfile and not certfile: - raise ValueError("certfile must be specified") - context = SSLContext(ssl_version) - context.verify_mode = cert_reqs - if ca_certs: - context.load_verify_locations(ca_certs) - if certfile: - context.load_cert_chain(certfile, keyfile) - if ciphers: - context.set_ciphers(ciphers) - return context.wrap_socket( - sock=sock, server_side=server_side, - do_handshake_on_connect=do_handshake_on_connect, - suppress_ragged_eofs=suppress_ragged_eofs - ) - # some utility functions def cert_time_to_seconds(cert_time): diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 544adad..65f5d4a 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -629,36 +629,6 @@ class BasicSocketTests(unittest.TestCase): str(cm.warning) ) - @ignore_deprecation - def test_errors_sslwrap(self): - sock = socket.socket() - self.assertRaisesRegex(ValueError, - "certfile must be specified", - ssl.wrap_socket, sock, keyfile=CERTFILE) - self.assertRaisesRegex(ValueError, - "certfile must be specified for server-side operations", - ssl.wrap_socket, sock, server_side=True) - self.assertRaisesRegex(ValueError, - "certfile must be specified for server-side operations", - ssl.wrap_socket, sock, server_side=True, certfile="") - with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s: - self.assertRaisesRegex(ValueError, "can't connect in server-side mode", - s.connect, (HOST, 8080)) - with self.assertRaises(OSError) as cm: - with socket.socket() as sock: - ssl.wrap_socket(sock, certfile=NONEXISTINGCERT) - self.assertEqual(cm.exception.errno, errno.ENOENT) - with self.assertRaises(OSError) as cm: - with socket.socket() as sock: - ssl.wrap_socket(sock, - certfile=CERTFILE, keyfile=NONEXISTINGCERT) - self.assertEqual(cm.exception.errno, errno.ENOENT) - with self.assertRaises(OSError) as cm: - with socket.socket() as sock: - ssl.wrap_socket(sock, - certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT) - self.assertEqual(cm.exception.errno, errno.ENOENT) - def bad_cert_test(self, certfile): """Check that trying to use the given client certificate fails""" certfile = os.path.join(os.path.dirname(__file__) or os.curdir, diff --git a/Misc/NEWS.d/next/Library/2022-06-24-10-39-56.gh-issue-94199.MIuckY.rst b/Misc/NEWS.d/next/Library/2022-06-24-10-39-56.gh-issue-94199.MIuckY.rst new file mode 100644 index 0000000..e1fb163 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-06-24-10-39-56.gh-issue-94199.MIuckY.rst @@ -0,0 +1,7 @@ +Remove the :func:`ssl.wrap_socket` function, deprecated in Python 3.7: instead, +create a :class:`ssl.SSLContext` object and call its +:class:`ssl.SSLContext.wrap_socket` method. Any package that still uses +:func:`ssl.wrap_socket` is broken and insecure. The function neither sends a +SNI TLS extension nor validates server hostname. Code is subject to `CWE-295 +`_: Improper Certificate +Validation. Patch by Victor Stinner. -- cgit v0.12