From 93a5f8b83d6092db510714af97b9e48d2582918e Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Thu, 8 Sep 2016 22:41:08 +0200 Subject: [PATCH] deprecate ssl.wrap_socket(), keyfile and certfile args --- Doc/library/ftplib.rst | 7 ++ Doc/library/http.client.rst | 18 +++-- Doc/library/imaplib.rst | 8 +++ Doc/library/smtplib.rst | 8 +++ Doc/library/ssl.rst | 16 ++++- Doc/library/urllib.request.rst | 6 ++ Lib/asyncio/test_utils.py | 8 +-- Lib/ftplib.py | 4 ++ Lib/http/client.py | 6 ++ Lib/imaplib.py | 5 +- Lib/poplib.py | 4 ++ Lib/smtplib.py | 8 +++ Lib/ssl.py | 4 +- Lib/test/test_ftplib.py | 10 +-- Lib/test/test_imaplib.py | 6 +- Lib/test/test_nntplib.py | 6 +- Lib/test/test_poplib.py | 10 +-- Lib/test/test_ssl.py | 136 +++++++++++++++++++++----------------- Lib/test/test_urllib.py | 9 +-- Lib/test/test_urllib2_localnet.py | 34 +++++----- Lib/urllib/request.py | 3 + 21 files changed, 209 insertions(+), 107 deletions(-) diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst index 1e35f37f448bcdab642ef3d5a26bf0a2c4ae66ab..b8c1dcfef2d98e5d71e309d0a91c71625c565c4a 100644 --- a/Doc/library/ftplib.rst +++ b/Doc/library/ftplib.rst @@ -97,6 +97,13 @@ The module defines the following items: :attr:`ssl.SSLContext.check_hostname` and *Server Name Indication* (see :data:`ssl.HAS_SNI`). + .. deprecated:: 3.6 + + *keyfile* and *certfile* are deprecated in favor of *context*. + Please use :meth:`ssl.SSLContext.load_cert_chain` instead, or let + :func:`ssl.create_default_context` select the system's trusted CA + certificates for you. + Here's a sample session using the :class:`FTP_TLS` class:: >>> ftps = FTP_TLS('ftp.pureftpd.org') diff --git a/Doc/library/http.client.rst b/Doc/library/http.client.rst index d1b445087ef2813af5c4954e803301b58d6141d2..75e7ff36bc9f42dee6031cc942a525509ea138b2 100644 --- a/Doc/library/http.client.rst +++ b/Doc/library/http.client.rst @@ -70,13 +70,6 @@ The module provides the following classes: must be a :class:`ssl.SSLContext` instance describing the various SSL options. - *key_file* and *cert_file* are deprecated, please use - :meth:`ssl.SSLContext.load_cert_chain` instead, or let - :func:`ssl.create_default_context` select the system's trusted CA - certificates for you. The *check_hostname* parameter is also deprecated; the - :attr:`ssl.SSLContext.check_hostname` attribute of *context* should be used - instead. - Please read :ref:`ssl-security` for more information on best practices. .. versionchanged:: 3.2 @@ -96,6 +89,17 @@ The module provides the following classes: :func:`ssl._create_unverified_context` can be passed to the *context* parameter. + .. deprecated:: 3.6 + + *key_file* and *cert_file* are deprecated in favor of *context*. + Please use :meth:`ssl.SSLContext.load_cert_chain` instead, or let + :func:`ssl.create_default_context` select the system's trusted CA + certificates for you. + + The *check_hostname* parameter is also deprecated; the + :attr:`ssl.SSLContext.check_hostname` attribute of *context* should + be used instead. + .. class:: HTTPResponse(sock, debuglevel=0, method=None, url=None) diff --git a/Doc/library/imaplib.rst b/Doc/library/imaplib.rst index b9b3b91518cb0424537eca718c42fdad35f01820..7024a1ba5ac15975581985688e1e34119686eef9 100644 --- a/Doc/library/imaplib.rst +++ b/Doc/library/imaplib.rst @@ -103,6 +103,14 @@ There's also a subclass for secure connections: :attr:`ssl.SSLContext.check_hostname` and *Server Name Indication* (see :data:`ssl.HAS_SNI`). + .. deprecated:: 3.6 + + *keyfile* and *certfile* are deprecated in favor of *ssl_context*. + Please use :meth:`ssl.SSLContext.load_cert_chain` instead, or let + :func:`ssl.create_default_context` select the system's trusted CA + certificates for you. + + The second subclass allows for connections created by a child process: diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst index 83d5c2ddf4173db358cfa14049cc18ef054c5ae8..1cb3aafcf3826de3bd4b82d532d45502d67528f7 100644 --- a/Doc/library/smtplib.rst +++ b/Doc/library/smtplib.rst @@ -95,6 +95,14 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions). :attr:`ssl.SSLContext.check_hostname` and *Server Name Indication* (see :data:`ssl.HAS_SNI`). + .. deprecated:: 3.6 + + *keyfile* and *certfile* are deprecated in favor of *context*. + Please use :meth:`ssl.SSLContext.load_cert_chain` instead, or let + :func:`ssl.create_default_context` select the system's trusted CA + certificates for you. + + .. class:: LMTP(host='', port=LMTP_PORT, local_hostname=None, source_address=None) The LMTP protocol, which is very similar to ESMTP, is heavily based on the diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 3706a6e8966975b9d8f310d3a0113ecadc46929a..76e5f9aaf8d0806bd4398040bf182796f855606f 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -230,6 +230,10 @@ instead. .. versionchanged:: 3.2 New optional argument *ciphers*. + .. deprecated:: 3.6 + :func:`wrap_socket` has to create a new :class:`SSLContext` for each + socket. Applications should rather keep a context around and use + :meth:`SSLContext.wrap_socket`. Context creation ^^^^^^^^^^^^^^^^ @@ -891,7 +895,7 @@ SSL Sockets :ref:`notes on non-blocking sockets `. Usually, :class:`SSLSocket` are not created directly, but using the - :func:`wrap_socket` function or the :meth:`SSLContext.wrap_socket` method. + the :meth:`SSLContext.wrap_socket` method. .. versionchanged:: 3.5 The :meth:`sendfile` method was added. @@ -901,6 +905,10 @@ SSL Sockets are received or sent. The socket timeout is now to maximum total duration of the shutdown. + .. deprecated:: 3.6 + It is deprecated to create a :class:`SSLSocket` instance directly, use + :meth:`SSLContext.wrap_socket` to wrap a socket. + SSL sockets also have the following additional methods and attributes: @@ -921,6 +929,9 @@ SSL sockets also have the following additional methods and attributes: The socket timeout is now to maximum total duration to read up to *len* bytes. + .. deprecated:: 3.6 + Use :meth:`~SSLSocket.recv` instead of :meth:`~SSLSocket.read`. + .. method:: SSLSocket.write(buf) Write *buf* to the SSL socket and return the number of bytes written. The @@ -936,6 +947,9 @@ SSL sockets also have the following additional methods and attributes: The socket timeout is no more reset each time bytes are received or sent. The socket timeout is now to maximum total duration to write *buf*. + .. deprecated:: 3.6 + Use :meth:`~SSLSocket.send` instead of :meth:`~SSLSocket.write`. + .. note:: The :meth:`~SSLSocket.read` and :meth:`~SSLSocket.write` methods are the diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index d288165a99db5bc3a4f2086371462614a6091ed7..491bded58baaebb0e95f63d2ba2661014696cffa 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -111,6 +111,12 @@ The :mod:`urllib.request` module defines the following functions: .. versionchanged:: 3.4.3 *context* was added. + .. deprecated:: 3.6 + + *cafile*, *capath* and *cadefault* are deprecated in favor of *context*. + Please use :meth:`ssl.SSLContext.load_cert_chain` instead, or let + :func:`ssl.create_default_context` select the system's trusted CA + certificates for you. .. function:: install_opener(opener) diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py index 396e6aed5673c4c6323ae7f8e091c0ff9ab0e3a9..ac8a8ef752ce943ccedfdb6d8436e34e5010b806 100644 --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -117,10 +117,10 @@ class SSLWSGIServerMixin: 'test', 'test_asyncio') keyfile = os.path.join(here, 'ssl_key.pem') certfile = os.path.join(here, 'ssl_cert.pem') - ssock = ssl.wrap_socket(request, - keyfile=keyfile, - certfile=certfile, - server_side=True) + context = ssl.SSLContext() + context.load_cert_chain(certfile, keyfile) + + ssock = context.wrap_socket(request, server_side=True) try: self.RequestHandlerClass(ssock, client_address, self) ssock.close() diff --git a/Lib/ftplib.py b/Lib/ftplib.py index ee2a137a5c472ec31293addaa63336be280b9c3e..8f36f537e8a54f550a4678a5afeb57aa070918bf 100644 --- a/Lib/ftplib.py +++ b/Lib/ftplib.py @@ -728,6 +728,10 @@ else: if context is not None and certfile is not None: raise ValueError("context and certfile arguments are mutually " "exclusive") + if keyfile is not None or certfile is not None: + import warnings + warnings.warn("keyfile and certfile are deprecated, use a" + "custom context instead", DeprecationWarning, 2) self.keyfile = keyfile self.certfile = certfile if context is None: diff --git a/Lib/http/client.py b/Lib/http/client.py index a1c4ab948255b734876b2994dfb615da8eaa3b8d..3b2e2f83cc4b9b9eaf44b2439294ca7aa0f7a2b8 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -1364,6 +1364,12 @@ else: check_hostname=None): super(HTTPSConnection, self).__init__(host, port, timeout, source_address) + if (key_file is not None or cert_file is not None or + check_hostname is not None): + import warnings + warnings.warn("key_file, cert_file and check_hostname are " + "deprecated, use a custom context instead.", + DeprecationWarning, 2) self.key_file = key_file self.cert_file = cert_file if context is None: diff --git a/Lib/imaplib.py b/Lib/imaplib.py index 965ed83f2b49a6fac5494f17e00d1f7b4d844788..cad508add8d697332de106d5057f7361320135c8 100644 --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -1267,7 +1267,10 @@ if HAVE_SSL: if ssl_context is not None and certfile is not None: raise ValueError("ssl_context and certfile arguments are mutually " "exclusive") - + if keyfile is not None or certfile is not None: + import warnings + warnings.warn("keyfile and certfile are deprecated, use a" + "custom ssl_context instead", DeprecationWarning, 2) self.keyfile = keyfile self.certfile = certfile if ssl_context is None: diff --git a/Lib/poplib.py b/Lib/poplib.py index f6723904e859e12d871aa71c88a426e911372e95..cae6950eb6d2d6c980bbdf7f6aeb507a35e88b7e 100644 --- a/Lib/poplib.py +++ b/Lib/poplib.py @@ -431,6 +431,10 @@ if HAVE_SSL: if context is not None and certfile is not None: raise ValueError("context and certfile arguments are mutually " "exclusive") + if keyfile is not None or certfile is not None: + import warnings + warnings.warn("keyfile and certfile are deprecated, use a" + "custom context instead", DeprecationWarning, 2) self.keyfile = keyfile self.certfile = certfile if context is None: diff --git a/Lib/smtplib.py b/Lib/smtplib.py index 5b9e66536a899cce211b08520704068319edde0f..f7c2c77ab42075b7ba75fe74cbcf7f51324ff7dd 100755 --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -759,6 +759,10 @@ class SMTP: if context is not None and certfile is not None: raise ValueError("context and certfile arguments are mutually " "exclusive") + if keyfile is not None or certfile is not None: + import warnings + warnings.warn("keyfile and certfile are deprecated, use a" + "custom context instead", DeprecationWarning, 2) if context is None: context = ssl._create_stdlib_context(certfile=certfile, keyfile=keyfile) @@ -1011,6 +1015,10 @@ if _have_ssl: if context is not None and certfile is not None: raise ValueError("context and certfile arguments are mutually " "exclusive") + if keyfile is not None or certfile is not None: + import warnings + warnings.warn("keyfile and certfile are deprecated, use a" + "custom context instead", DeprecationWarning, 2) self.keyfile = keyfile self.certfile = certfile if context is None: diff --git a/Lib/ssl.py b/Lib/ssl.py index 42ca1686d93eacc142c2e6db778d21b2f8310e89..3a995c2b087bd9fe412138e808e5bfbb0811b714 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -1067,7 +1067,9 @@ def wrap_socket(sock, keyfile=None, certfile=None, do_handshake_on_connect=True, suppress_ragged_eofs=True, ciphers=None): - + import warnings + warnings.warn("ssl.wrap_socket is deprecated in favor of " + "ssl.SSLContext.wrap_socket", DeprecationWarning, 2) return SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile, server_side=server_side, cert_reqs=cert_reqs, ssl_version=ssl_version, ca_certs=ca_certs, diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py index 9d8de211df8662dc6e91d095bc5cd235dc5f39c8..12fabc5e8be3d69a28f7b2c13e6ee9fffb6a8db6 100644 --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -311,10 +311,12 @@ if ssl is not None: _ssl_closing = False def secure_connection(self): - socket = ssl.wrap_socket(self.socket, suppress_ragged_eofs=False, - certfile=CERTFILE, server_side=True, - do_handshake_on_connect=False, - ssl_version=ssl.PROTOCOL_SSLv23) + context = ssl.SSLContext() + context.load_cert_chain(CERTFILE) + socket = context.wrap_socket(self.socket, + suppress_ragged_eofs=False, + server_side=True, + do_handshake_on_connect=False) self.del_channel() self.set_socket(socket) self._ssl_accepting = True diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py index 8e4990b3cf7080ee21425251a04ef2d4fefbb09a..f95ebf4757110a4346abbe9bf0f0e462490f170f 100644 --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -77,9 +77,9 @@ if ssl: def get_request(self): newsocket, fromaddr = self.socket.accept() - connstream = ssl.wrap_socket(newsocket, - server_side=True, - certfile=CERTFILE) + context = ssl.SSLContext() + context.load_cert_chain(CERTFILE) + connstream = context.wrap_socket(newsocket, server_side=True) return connstream, fromaddr IMAP4_SSL = imaplib.IMAP4_SSL diff --git a/Lib/test/test_nntplib.py b/Lib/test/test_nntplib.py index 2ef6d02c2bffbe5b25e72851e3d8fb33c4e9acf8..feaba3c3c014cc634c19a14ee81b7b542d5dacf0 100644 --- a/Lib/test/test_nntplib.py +++ b/Lib/test/test_nntplib.py @@ -1542,8 +1542,10 @@ class LocalServerTests(unittest.TestCase): elif cmd == b'STARTTLS\r\n': reader.close() client.sendall(b'382 Begin TLS negotiation now\r\n') - client = ssl.wrap_socket( - client, server_side=True, certfile=certfile) + context = ssl.SSLContext() + context.load_cert_chain(certfile) + client = context.wrap_socket( + client, server_side=True) cleanup.enter_context(client) reader = cleanup.enter_context(client.makefile('rb')) elif cmd == b'QUIT\r\n': diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index 7b9606d35933719ae105c203623b084d757c9bdb..e5b16dc98a41113d47e81c7ede3797cea5eb1f19 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -152,10 +152,12 @@ class DummyPOP3Handler(asynchat.async_chat): def cmd_stls(self, arg): if self.tls_active is False: self.push('+OK Begin TLS negotiation') - tls_sock = ssl.wrap_socket(self.socket, certfile=CERTFILE, - server_side=True, - do_handshake_on_connect=False, - suppress_ragged_eofs=False) + context = ssl.SSLContext() + context.load_cert_chain(CERTFILE) + tls_sock = context.wrap_socket(self.socket, + server_side=True, + do_handshake_on_connect=False, + suppress_ragged_eofs=False) self.del_channel() self.set_socket(tls_sock) self.tls_active = True diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 0bdb86d5f23451659b54ab2129afe8f4ebd5600b..00cc42d25bdd6ea5fc433e88284e30f070b758b3 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -137,6 +137,21 @@ def skip_if_broken_ubuntu_ssl(func): needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test") +def test_wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLS, *, + cert_reqs=ssl.CERT_NONE, ca_certs=None, + ciphers=None, certfile=None, keyfile=None, + **kwargs): + context = ssl.SSLContext(ssl_version) + if cert_reqs is not None: + context.verify_mode = cert_reqs + if ca_certs is not None: + context.load_verify_locations(ca_certs) + if certfile is not None or keyfile is not None: + context.load_cert_chain(certfile, keyfile) + if ciphers is not None: + context.set_ciphers(ciphers) + return context.wrap_socket(sock, **kwargs) + class BasicSocketTests(unittest.TestCase): def test_constants(self): @@ -357,7 +372,7 @@ class BasicSocketTests(unittest.TestCase): # Issue #7943: an SSL object doesn't create reference cycles with # itself. s = socket.socket(socket.AF_INET) - ss = ssl.wrap_socket(s) + ss = test_wrap_socket(s) wr = weakref.ref(ss) with support.check_warnings(("", ResourceWarning)): del ss @@ -367,7 +382,7 @@ class BasicSocketTests(unittest.TestCase): # Methods on an unconnected SSLSocket propagate the original # OSError raise by the underlying socket object. s = socket.socket(socket.AF_INET) - with ssl.wrap_socket(s) as ss: + with test_wrap_socket(s) as ss: self.assertRaises(OSError, ss.recv, 1) self.assertRaises(OSError, ss.recv_into, bytearray(b'x')) self.assertRaises(OSError, ss.recvfrom, 1) @@ -381,37 +396,38 @@ class BasicSocketTests(unittest.TestCase): for timeout in (None, 0.0, 5.0): s = socket.socket(socket.AF_INET) s.settimeout(timeout) - with ssl.wrap_socket(s) as ss: + with test_wrap_socket(s) as ss: self.assertEqual(timeout, ss.gettimeout()) - def test_errors(self): + 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) + with support.check_warnings(('', DeprecationWarning)): + 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""" @@ -420,7 +436,7 @@ class BasicSocketTests(unittest.TestCase): sock = socket.socket() self.addCleanup(sock.close) with self.assertRaises(ssl.SSLError): - ssl.wrap_socket(sock, + test_wrap_socket(sock, certfile=certfile, ssl_version=ssl.PROTOCOL_TLSv1) @@ -607,7 +623,7 @@ class BasicSocketTests(unittest.TestCase): s.listen() c = socket.socket(socket.AF_INET) c.connect(s.getsockname()) - with ssl.wrap_socket(c, do_handshake_on_connect=False) as ss: + with test_wrap_socket(c, do_handshake_on_connect=False) as ss: with self.assertRaises(ValueError): ss.get_channel_binding("unknown-type") s.close() @@ -617,15 +633,15 @@ class BasicSocketTests(unittest.TestCase): def test_tls_unique_channel_binding(self): # unconnected should return None for known type s = socket.socket(socket.AF_INET) - with ssl.wrap_socket(s) as ss: + with test_wrap_socket(s) as ss: self.assertIsNone(ss.get_channel_binding("tls-unique")) # the same for server-side s = socket.socket(socket.AF_INET) - with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss: + with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss: self.assertIsNone(ss.get_channel_binding("tls-unique")) def test_dealloc_warn(self): - ss = ssl.wrap_socket(socket.socket(socket.AF_INET)) + ss = test_wrap_socket(socket.socket(socket.AF_INET)) r = repr(ss) with self.assertWarns(ResourceWarning) as cm: ss = None @@ -744,7 +760,7 @@ class BasicSocketTests(unittest.TestCase): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.addCleanup(s.close) with self.assertRaises(NotImplementedError) as cx: - ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE) + test_wrap_socket(s, cert_reqs=ssl.CERT_NONE) self.assertEqual(str(cx.exception), "only stream sockets are supported") ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) with self.assertRaises(NotImplementedError) as cx: @@ -820,7 +836,7 @@ class BasicSocketTests(unittest.TestCase): server = socket.socket(socket.AF_INET) self.addCleanup(server.close) port = support.bind_port(server) # Reserve port but don't listen - s = ssl.wrap_socket(socket.socket(socket.AF_INET), + s = test_wrap_socket(socket.socket(socket.AF_INET), cert_reqs=ssl.CERT_REQUIRED) self.addCleanup(s.close) rc = s.connect_ex((HOST, port)) @@ -1440,13 +1456,13 @@ class SimpleBackgroundTests(unittest.TestCase): self.addCleanup(server.__exit__, None, None, None) def test_connect(self): - with ssl.wrap_socket(socket.socket(socket.AF_INET), + with test_wrap_socket(socket.socket(socket.AF_INET), cert_reqs=ssl.CERT_NONE) as s: s.connect(self.server_addr) self.assertEqual({}, s.getpeercert()) # this should succeed because we specify the root cert - with ssl.wrap_socket(socket.socket(socket.AF_INET), + with test_wrap_socket(socket.socket(socket.AF_INET), cert_reqs=ssl.CERT_REQUIRED, ca_certs=SIGNING_CA) as s: s.connect(self.server_addr) @@ -1456,7 +1472,7 @@ class SimpleBackgroundTests(unittest.TestCase): # This should fail because we have no verification certs. Connection # failure crashes ThreadedEchoServer, so run this in an independent # test method. - s = ssl.wrap_socket(socket.socket(socket.AF_INET), + s = test_wrap_socket(socket.socket(socket.AF_INET), cert_reqs=ssl.CERT_REQUIRED) self.addCleanup(s.close) self.assertRaisesRegex(ssl.SSLError, "certificate verify failed", @@ -1464,7 +1480,7 @@ class SimpleBackgroundTests(unittest.TestCase): def test_connect_ex(self): # Issue #11326: check connect_ex() implementation - s = ssl.wrap_socket(socket.socket(socket.AF_INET), + s = test_wrap_socket(socket.socket(socket.AF_INET), cert_reqs=ssl.CERT_REQUIRED, ca_certs=SIGNING_CA) self.addCleanup(s.close) @@ -1474,7 +1490,7 @@ class SimpleBackgroundTests(unittest.TestCase): def test_non_blocking_connect_ex(self): # Issue #11326: non-blocking connect_ex() should allow handshake # to proceed after the socket gets ready. - s = ssl.wrap_socket(socket.socket(socket.AF_INET), + s = test_wrap_socket(socket.socket(socket.AF_INET), cert_reqs=ssl.CERT_REQUIRED, ca_certs=SIGNING_CA, do_handshake_on_connect=False) @@ -1574,7 +1590,7 @@ class SimpleBackgroundTests(unittest.TestCase): # Issue #5238: creating a file-like object with makefile() shouldn't # delay closing the underlying "real socket" (here tested with its # file descriptor, hence skipping the test under Windows). - ss = ssl.wrap_socket(socket.socket(socket.AF_INET)) + ss = test_wrap_socket(socket.socket(socket.AF_INET)) ss.connect(self.server_addr) fd = ss.fileno() f = ss.makefile() @@ -1592,7 +1608,7 @@ class SimpleBackgroundTests(unittest.TestCase): s = socket.socket(socket.AF_INET) s.connect(self.server_addr) s.setblocking(False) - s = ssl.wrap_socket(s, + s = test_wrap_socket(s, cert_reqs=ssl.CERT_NONE, do_handshake_on_connect=False) self.addCleanup(s.close) @@ -1618,16 +1634,16 @@ class SimpleBackgroundTests(unittest.TestCase): _test_get_server_certificate_fail(self, *self.server_addr) def test_ciphers(self): - with ssl.wrap_socket(socket.socket(socket.AF_INET), + with test_wrap_socket(socket.socket(socket.AF_INET), cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s: s.connect(self.server_addr) - with ssl.wrap_socket(socket.socket(socket.AF_INET), + with test_wrap_socket(socket.socket(socket.AF_INET), cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s: s.connect(self.server_addr) # Error checking can happen at instantiation or when connecting with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"): with socket.socket(socket.AF_INET) as sock: - s = ssl.wrap_socket(sock, + s = test_wrap_socket(sock, cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx") s.connect(self.server_addr) @@ -1745,7 +1761,7 @@ class NetworkedTests(unittest.TestCase): # Issue #12065: on a timeout, connect_ex() should return the original # errno (mimicking the behaviour of non-SSL sockets). with support.transient_internet(REMOTE_HOST): - s = ssl.wrap_socket(socket.socket(socket.AF_INET), + s = test_wrap_socket(socket.socket(socket.AF_INET), cert_reqs=ssl.CERT_REQUIRED, do_handshake_on_connect=False) self.addCleanup(s.close) @@ -2036,7 +2052,7 @@ if _have_threads: class ConnectionHandler (asyncore.dispatcher_with_send): def __init__(self, conn, certfile): - self.socket = ssl.wrap_socket(conn, server_side=True, + self.socket = test_wrap_socket(conn, server_side=True, certfile=certfile, do_handshake_on_connect=False) asyncore.dispatcher_with_send.__init__(self, self.socket) @@ -2397,7 +2413,7 @@ if _have_threads: connectionchatty=False) with server, \ socket.socket() as sock, \ - ssl.wrap_socket(sock, + test_wrap_socket(sock, certfile=certfile, ssl_version=ssl.PROTOCOL_TLSv1) as s: try: @@ -2444,7 +2460,7 @@ if _have_threads: c.connect((HOST, port)) listener_gone.wait() try: - ssl_sock = ssl.wrap_socket(c) + ssl_sock = test_wrap_socket(c) except OSError: pass else: @@ -2634,7 +2650,7 @@ if _have_threads: sys.stdout.write( " client: read %r from server, starting TLS...\n" % msg) - conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1) + conn = test_wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1) wrapped = True elif indata == b"ENDTLS" and msg.startswith(b"ok"): # ENDTLS ok, switch back to clear text @@ -2695,7 +2711,7 @@ if _have_threads: indata = b"FOO\n" server = AsyncoreEchoServer(CERTFILE) with server: - s = ssl.wrap_socket(socket.socket()) + s = test_wrap_socket(socket.socket()) s.connect(('127.0.0.1', server.port)) if support.verbose: sys.stdout.write( @@ -2728,7 +2744,7 @@ if _have_threads: chatty=True, connectionchatty=False) with server: - s = ssl.wrap_socket(socket.socket(), + s = test_wrap_socket(socket.socket(), server_side=False, certfile=CERTFILE, ca_certs=CERTFILE, @@ -2852,7 +2868,7 @@ if _have_threads: self.addCleanup(server.__exit__, None, None) s = socket.create_connection((HOST, server.port)) self.addCleanup(s.close) - s = ssl.wrap_socket(s, suppress_ragged_eofs=False) + s = test_wrap_socket(s, suppress_ragged_eofs=False) self.addCleanup(s.close) # recv/read(0) should return no data @@ -2874,7 +2890,7 @@ if _have_threads: chatty=True, connectionchatty=False) with server: - s = ssl.wrap_socket(socket.socket(), + s = test_wrap_socket(socket.socket(), server_side=False, certfile=CERTFILE, ca_certs=CERTFILE, @@ -2928,12 +2944,12 @@ if _have_threads: c.connect((host, port)) # Will attempt handshake and time out self.assertRaisesRegex(socket.timeout, "timed out", - ssl.wrap_socket, c) + test_wrap_socket, c) finally: c.close() try: c = socket.socket(socket.AF_INET) - c = ssl.wrap_socket(c) + c = test_wrap_socket(c) c.settimeout(0.2) # Will attempt handshake and time out self.assertRaisesRegex(socket.timeout, "timed out", @@ -3058,7 +3074,7 @@ if _have_threads: chatty=True, connectionchatty=False) with server: - s = ssl.wrap_socket(socket.socket(), + s = test_wrap_socket(socket.socket(), server_side=False, certfile=CERTFILE, ca_certs=CERTFILE, @@ -3083,7 +3099,7 @@ if _have_threads: s.close() # now, again - s = ssl.wrap_socket(socket.socket(), + s = test_wrap_socket(socket.socket(), server_side=False, certfile=CERTFILE, ca_certs=CERTFILE, diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py index 8f06b08afa0ee7bcf0f1cc564512e1817fc8372a..3bd4413ea818f0800b4539bf39c718a4140aa6d5 100644 --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -469,10 +469,11 @@ Connection: close @unittest.skipUnless(ssl, "ssl module required") def test_cafile_and_context(self): context = ssl.create_default_context() - with self.assertRaises(ValueError): - urllib.request.urlopen( - "https://localhost", cafile="/nonexistent/path", context=context - ) + with support.check_warnings(('', DeprecationWarning)): +> with self.assertRaises(ValueError): + urllib.request.urlopen( + "https://localhost", cafile="/nonexistent/path", context=context + ) class urlopen_DataTests(unittest.TestCase): """Test urlopen() opening a data URL.""" diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py index e9564fde621a07c30d6e1808b29f207e3a3d781a..e6a522c6c5e93e0b5dc869adea77cf033c1da826 100644 --- a/Lib/test/test_urllib2_localnet.py +++ b/Lib/test/test_urllib2_localnet.py @@ -548,26 +548,28 @@ class TestUrlopen(unittest.TestCase): def test_https_with_cafile(self): handler = self.start_https_server(certfile=CERT_localhost) - # Good cert - data = self.urlopen("https://localhost:%s/bizarre" % handler.port, - cafile=CERT_localhost) - self.assertEqual(data, b"we care a bit") - # Bad cert - with self.assertRaises(urllib.error.URLError) as cm: - self.urlopen("https://localhost:%s/bizarre" % handler.port, - cafile=CERT_fakehostname) - # Good cert, but mismatching hostname - handler = self.start_https_server(certfile=CERT_fakehostname) - with self.assertRaises(ssl.CertificateError) as cm: - self.urlopen("https://localhost:%s/bizarre" % handler.port, - cafile=CERT_fakehostname) + with support.check_warnings(('', DeprecationWarning)): + # Good cert + data = self.urlopen("https://localhost:%s/bizarre" % handler.port, + cafile=CERT_localhost) + self.assertEqual(data, b"we care a bit") + # Bad cert + with self.assertRaises(urllib.error.URLError) as cm: + self.urlopen("https://localhost:%s/bizarre" % handler.port, + cafile=CERT_fakehostname) + # Good cert, but mismatching hostname + handler = self.start_https_server(certfile=CERT_fakehostname) + with self.assertRaises(ssl.CertificateError) as cm: + self.urlopen("https://localhost:%s/bizarre" % handler.port, + cafile=CERT_fakehostname) def test_https_with_cadefault(self): handler = self.start_https_server(certfile=CERT_localhost) # Self-signed cert should fail verification with system certificate store - with self.assertRaises(urllib.error.URLError) as cm: - self.urlopen("https://localhost:%s/bizarre" % handler.port, - cadefault=True) + with support.check_warnings(('', DeprecationWarning)): + with self.assertRaises(urllib.error.URLError) as cm: + self.urlopen("https://localhost:%s/bizarre" % handler.port, + cadefault=True) def test_https_sni(self): if ssl is None: diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index 30bf6e051ec6e97c5d9dc550c045db06d3cc7c88..82a465c6e5f129cc9ae54ffac1834ff70c279ed0 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -198,6 +198,9 @@ def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, ''' global _opener if cafile or capath or cadefault: + import warnings + warnings.warn("cafile, cpath and cadefault are deprecated, use a " + "custom context instead.", DeprecationWarning, 2) if context is not None: raise ValueError( "You can't pass both context and any of cafile, capath, and " -- 2.7.4