diff options
author | Guido van Rossum <guido@dropbox.com> | 2013-11-01 21:16:54 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@dropbox.com> | 2013-11-01 21:16:54 (GMT) |
commit | 21c85a7124004bfbddf2c3db4085ec48842e90f6 (patch) | |
tree | da81a3150df7c9abdf63ff7e410c2a32157bf738 /Lib/asyncio | |
parent | 2b430b8720f0d206491250220672d4f1d0189b5a (diff) | |
download | cpython-21c85a7124004bfbddf2c3db4085ec48842e90f6.zip cpython-21c85a7124004bfbddf2c3db4085ec48842e90f6.tar.gz cpython-21c85a7124004bfbddf2c3db4085ec48842e90f6.tar.bz2 |
asyncio: Add server_hostname as create_connection() argument, with secure default.
Diffstat (limited to 'Lib/asyncio')
-rw-r--r-- | Lib/asyncio/base_events.py | 23 | ||||
-rw-r--r-- | Lib/asyncio/events.py | 2 | ||||
-rw-r--r-- | Lib/asyncio/selector_events.py | 4 |
3 files changed, 24 insertions, 5 deletions
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 37d50aa..f18a556 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -275,8 +275,27 @@ class BaseEventLoop(events.AbstractEventLoop): @tasks.coroutine def create_connection(self, protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, - local_addr=None): + local_addr=None, server_hostname=None): """XXX""" + if server_hostname is not None and not ssl: + raise ValueError('server_hostname is only meaningful with ssl') + + if server_hostname is None and ssl: + # Use host as default for server_hostname. It is an error + # if host is empty or not set, e.g. when an + # already-connected socket was passed or when only a port + # is given. To avoid this error, you can pass + # server_hostname='' -- this will bypass the hostname + # check. (This also means that if host is a numeric + # IP/IPv6 address, we will attempt to verify that exact + # address; this will probably fail, but it is possible to + # create a certificate for a specific IP address, so we + # don't judge it here.) + if not host: + raise ValueError('You must set server_hostname ' + 'when using ssl without a host') + server_hostname = host + if host is not None or port is not None: if sock is not None: raise ValueError( @@ -357,7 +376,7 @@ class BaseEventLoop(events.AbstractEventLoop): sslcontext = None if isinstance(ssl, bool) else ssl transport = self._make_ssl_transport( sock, protocol, sslcontext, waiter, - server_side=False, server_hostname=host) + server_side=False, server_hostname=server_hostname) else: transport = self._make_socket_transport(sock, protocol, waiter) diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 62f8e94..a47253a 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -172,7 +172,7 @@ class AbstractEventLoop: def create_connection(self, protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, - local_addr=None): + local_addr=None, server_hostname=None): raise NotImplementedError def create_server(self, protocol_factory, host=None, port=None, *, diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index e61a88d..44430b2 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -573,7 +573,7 @@ class _SelectorSslTransport(_SelectorTransport): 'server_side': server_side, 'do_handshake_on_connect': False, } - if server_hostname is not None and not server_side and ssl.HAS_SNI: + if server_hostname and not server_side and ssl.HAS_SNI: wrap_kwargs['server_hostname'] = server_hostname sslsock = sslcontext.wrap_socket(rawsock, **wrap_kwargs) @@ -619,7 +619,7 @@ class _SelectorSslTransport(_SelectorTransport): # Verify hostname if requested. peercert = self._sock.getpeercert() - if (self._server_hostname is not None and + if (self._server_hostname and self._sslcontext.verify_mode != ssl.CERT_NONE): try: ssl.match_hostname(peercert, self._server_hostname) |