summaryrefslogtreecommitdiffstats
path: root/Lib/asyncio
diff options
context:
space:
mode:
authorGuido van Rossum <guido@dropbox.com>2013-11-01 21:16:54 (GMT)
committerGuido van Rossum <guido@dropbox.com>2013-11-01 21:16:54 (GMT)
commit21c85a7124004bfbddf2c3db4085ec48842e90f6 (patch)
treeda81a3150df7c9abdf63ff7e410c2a32157bf738 /Lib/asyncio
parent2b430b8720f0d206491250220672d4f1d0189b5a (diff)
downloadcpython-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.py23
-rw-r--r--Lib/asyncio/events.py2
-rw-r--r--Lib/asyncio/selector_events.py4
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)