[Python-checkins] cpython (merge 3.4 -> default): Issue #22641: In asyncio, the default SSL context for client connections is now

antoine.pitrou python-checkins at python.org
Wed Oct 15 17:34:13 CEST 2014


https://hg.python.org/cpython/rev/d75b63cb3e78
changeset: 93067:d75b63cb3e78
parent: 93065:34436ae65523
parent: 93066:c2ccbcd11d47
user: Antoine Pitrou <solipsis at pitrou.net>
date: Wed Oct 15 16:59:58 2014 +0200
summary:
 Issue #22641: In asyncio, the default SSL context for client connections is now created using ssl.create_default_context(), for stronger security.
files:
 Lib/asyncio/selector_events.py | 13 ++--
 Lib/asyncio/test_utils.py | 13 ++++-
 Lib/test/test_asyncio/test_events.py | 48 ++++++++++++---
 Misc/NEWS | 3 +
 4 files changed, 60 insertions(+), 17 deletions(-)
diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py
--- a/Lib/asyncio/selector_events.py
+++ b/Lib/asyncio/selector_events.py
@@ -689,16 +689,17 @@
 if not sslcontext:
 # Client side may pass ssl=True to use a default
 # context; in that case the sslcontext passed is None.
- # The default is the same as used by urllib with
- # cadefault=True.
- if hasattr(ssl, '_create_stdlib_context'):
- sslcontext = ssl._create_stdlib_context(
- cert_reqs=ssl.CERT_REQUIRED,
- check_hostname=bool(server_hostname))
+ # The default is secure for client connections.
+ if hasattr(ssl, 'create_default_context'):
+ # Python 3.4+: use up-to-date strong settings.
+ sslcontext = ssl.create_default_context()
+ if not server_hostname:
+ sslcontext.check_hostname = False
 else:
 # Fallback for Python 3.3.
 sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 sslcontext.options |= ssl.OP_NO_SSLv2
+ sslcontext.options |= ssl.OP_NO_SSLv3
 sslcontext.set_default_verify_paths()
 sslcontext.verify_mode = ssl.CERT_REQUIRED
 
diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py
--- a/Lib/asyncio/test_utils.py
+++ b/Lib/asyncio/test_utils.py
@@ -91,6 +91,13 @@
 
 class SilentWSGIServer(WSGIServer):
 
+ request_timeout = 2
+
+ def get_request(self):
+ request, client_addr = super().get_request()
+ request.settimeout(self.request_timeout)
+ return request, client_addr
+
 def handle_error(self, request, client_address):
 pass
 
@@ -138,7 +145,8 @@
 httpd = server_class(address, SilentWSGIRequestHandler)
 httpd.set_app(app)
 httpd.address = httpd.server_address
- server_thread = threading.Thread(target=httpd.serve_forever)
+ server_thread = threading.Thread(
+ target=lambda: httpd.serve_forever(poll_interval=0.05))
 server_thread.start()
 try:
 yield httpd
@@ -160,12 +168,15 @@
 
 class UnixWSGIServer(UnixHTTPServer, WSGIServer):
 
+ request_timeout = 2
+
 def server_bind(self):
 UnixHTTPServer.server_bind(self)
 self.setup_environ()
 
 def get_request(self):
 request, client_addr = super().get_request()
+ request.settimeout(self.request_timeout)
 # Code in the stdlib expects that get_request
 # will return a socket and a tuple (host, port).
 # However, this isn't true for UNIX sockets,
diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py
--- a/Lib/test/test_asyncio/test_events.py
+++ b/Lib/test/test_asyncio/test_events.py
@@ -606,15 +606,43 @@
 self.assertGreater(pr.nbytes, 0)
 tr.close()
 
+ def _dummy_ssl_create_context(self, purpose=ssl.Purpose.SERVER_AUTH, *,
+ cafile=None, capath=None, cadata=None):
+ """
+ A ssl.create_default_context() replacement that doesn't enable
+ cert validation.
+ """
+ self.assertEqual(purpose, ssl.Purpose.SERVER_AUTH)
+ return test_utils.dummy_ssl_context()
+
+ def _test_create_ssl_connection(self, httpd, create_connection,
+ check_sockname=True):
+ conn_fut = create_connection(ssl=test_utils.dummy_ssl_context())
+ self._basetest_create_ssl_connection(conn_fut, check_sockname)
+
+ # With ssl=True, ssl.create_default_context() should be called
+ with mock.patch('ssl.create_default_context',
+ side_effect=self._dummy_ssl_create_context) as m:
+ conn_fut = create_connection(ssl=True)
+ self._basetest_create_ssl_connection(conn_fut, check_sockname)
+ self.assertEqual(m.call_count, 1)
+
+ # With the real ssl.create_default_context(), certificate
+ # validation will fail
+ with self.assertRaises(ssl.SSLError) as cm:
+ conn_fut = create_connection(ssl=True)
+ self._basetest_create_ssl_connection(conn_fut, check_sockname)
+
+ self.assertEqual(cm.exception.reason, 'CERTIFICATE_VERIFY_FAILED')
+
 @unittest.skipIf(ssl is None, 'No ssl module')
 def test_create_ssl_connection(self):
 with test_utils.run_test_server(use_ssl=True) as httpd:
- conn_fut = self.loop.create_connection(
+ create_connection = functools.partial(
+ self.loop.create_connection,
 lambda: MyProto(loop=self.loop),
- *httpd.address,
- ssl=test_utils.dummy_ssl_context())
-
- self._basetest_create_ssl_connection(conn_fut)
+ *httpd.address)
+ self._test_create_ssl_connection(httpd, create_connection)
 
 @unittest.skipIf(ssl is None, 'No ssl module')
 @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
@@ -624,13 +652,13 @@
 check_sockname = not osx_tiger()
 
 with test_utils.run_test_unix_server(use_ssl=True) as httpd:
- conn_fut = self.loop.create_unix_connection(
- lambda: MyProto(loop=self.loop),
- httpd.address,
- ssl=test_utils.dummy_ssl_context(),
+ create_connection = functools.partial(
+ self.loop.create_unix_connection,
+ lambda: MyProto(loop=self.loop), httpd.address,
 server_hostname='127.0.0.1')
 
- self._basetest_create_ssl_connection(conn_fut, check_sockname)
+ self._test_create_ssl_connection(httpd, create_connection,
+ check_sockname)
 
 def test_create_connection_local_addr(self):
 with test_utils.run_test_server() as httpd:
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -175,6 +175,9 @@
 Library
 -------
 
+- Issue #22641: In asyncio, the default SSL context for client connections
+ is now created using ssl.create_default_context(), for stronger security.
+
 - Issue #21338: Add silent mode for compileall. quiet parameters of
 compile_{dir, file, path} functions now have a multilevel value. Also,
 -q option of the CLI now have a multilevel value. Patch by Thomas Kluyver.
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /