summaryrefslogtreecommitdiff
path: root/Lib/asyncio
diff options
context:
space:
mode:
authorAndrew Svetlov <andrew.svetlov@gmail.com>2017-11-18 18:54:05 +0200
committerGitHub <noreply@github.com>2017-11-18 18:54:05 +0200
commit51d546ae4d563fde608e23c9c337fefd7e95c93f (patch)
treed2bd875c8f22d60a2fc5a5c522bf17a424b97757 /Lib/asyncio
parentf02f5e5c3eb815fff9578dc58de60374c6baaa3d (diff)
downloadcpython-git-51d546ae4d563fde608e23c9c337fefd7e95c93f.tar.gz
bpo-32069: Drop legacy SSL transport (#4451)
* Drop legacy SSL transport * Drop unused import * Fix Windows tests * Drop never executed on Python 3.4+ code
Diffstat (limited to 'Lib/asyncio')
-rw-r--r--Lib/asyncio/proactor_events.py5
-rw-r--r--Lib/asyncio/selector_events.py248
-rw-r--r--Lib/asyncio/sslproto.py20
-rw-r--r--Lib/asyncio/test_utils.py5
4 files changed, 4 insertions, 274 deletions
diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py
index 5e7a39727c..e35d05b7bf 100644
--- a/Lib/asyncio/proactor_events.py
+++ b/Lib/asyncio/proactor_events.py
@@ -392,11 +392,6 @@ class BaseProactorEventLoop(base_events.BaseEventLoop):
def _make_ssl_transport(self, rawsock, protocol, sslcontext, waiter=None,
*, server_side=False, server_hostname=None,
extra=None, server=None):
- if not sslproto._is_sslproto_available():
- raise NotImplementedError("Proactor event loop requires Python 3.5"
- " or newer (ssl.MemoryBIO) to support "
- "SSL")
-
ssl_protocol = sslproto.SSLProtocol(self, protocol, sslcontext, waiter,
server_side, server_hostname)
_ProactorSocketTransport(self, rawsock, ssl_protocol,
diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py
index f3b278c9ea..4baad48ce3 100644
--- a/Lib/asyncio/selector_events.py
+++ b/Lib/asyncio/selector_events.py
@@ -74,28 +74,12 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
def _make_ssl_transport(self, rawsock, protocol, sslcontext, waiter=None,
*, server_side=False, server_hostname=None,
extra=None, server=None):
- if not sslproto._is_sslproto_available():
- return self._make_legacy_ssl_transport(
- rawsock, protocol, sslcontext, waiter,
- server_side=server_side, server_hostname=server_hostname,
- extra=extra, server=server)
-
ssl_protocol = sslproto.SSLProtocol(self, protocol, sslcontext, waiter,
server_side, server_hostname)
_SelectorSocketTransport(self, rawsock, ssl_protocol,
extra=extra, server=server)
return ssl_protocol._app_transport
- def _make_legacy_ssl_transport(self, rawsock, protocol, sslcontext,
- waiter, *,
- server_side=False, server_hostname=None,
- extra=None, server=None):
- # Use the legacy API: SSL_write, SSL_read, etc. The legacy API is used
- # on Python 3.4 and older, when ssl.MemoryBIO is not available.
- return _SelectorSslTransport(
- self, rawsock, protocol, sslcontext, waiter,
- server_side, server_hostname, extra, server)
-
def _make_datagram_transport(self, sock, protocol,
address=None, waiter=None, extra=None):
return _SelectorDatagramTransport(self, sock, protocol,
@@ -848,238 +832,6 @@ class _SelectorSocketTransport(_SelectorTransport):
return True
-class _SelectorSslTransport(_SelectorTransport):
-
- _buffer_factory = bytearray
-
- def __init__(self, loop, rawsock, protocol, sslcontext, waiter=None,
- server_side=False, server_hostname=None,
- extra=None, server=None):
- if ssl is None:
- raise RuntimeError('stdlib ssl module not available')
-
- if not sslcontext:
- sslcontext = sslproto._create_transport_context(server_side, server_hostname)
-
- wrap_kwargs = {
- 'server_side': server_side,
- 'do_handshake_on_connect': False,
- }
- if server_hostname and not server_side:
- wrap_kwargs['server_hostname'] = server_hostname
- sslsock = sslcontext.wrap_socket(rawsock, **wrap_kwargs)
-
- super().__init__(loop, sslsock, protocol, extra, server)
- # the protocol connection is only made after the SSL handshake
- self._protocol_connected = False
-
- self._server_hostname = server_hostname
- self._waiter = waiter
- self._sslcontext = sslcontext
- self._paused = False
-
- # SSL-specific extra info. (peercert is set later)
- self._extra.update(sslcontext=sslcontext)
-
- if self._loop.get_debug():
- logger.debug("%r starts SSL handshake", self)
- start_time = self._loop.time()
- else:
- start_time = None
- self._on_handshake(start_time)
-
- def _wakeup_waiter(self, exc=None):
- if self._waiter is None:
- return
- if not self._waiter.cancelled():
- if exc is not None:
- self._waiter.set_exception(exc)
- else:
- self._waiter.set_result(None)
- self._waiter = None
-
- def _on_handshake(self, start_time):
- try:
- self._sock.do_handshake()
- except ssl.SSLWantReadError:
- self._loop._add_reader(self._sock_fd,
- self._on_handshake, start_time)
- return
- except ssl.SSLWantWriteError:
- self._loop._add_writer(self._sock_fd,
- self._on_handshake, start_time)
- return
- except BaseException as exc:
- if self._loop.get_debug():
- logger.warning("%r: SSL handshake failed",
- self, exc_info=True)
- self._loop._remove_reader(self._sock_fd)
- self._loop._remove_writer(self._sock_fd)
- self._sock.close()
- self._wakeup_waiter(exc)
- if isinstance(exc, Exception):
- return
- else:
- raise
-
- self._loop._remove_reader(self._sock_fd)
- self._loop._remove_writer(self._sock_fd)
-
- peercert = self._sock.getpeercert()
- if not hasattr(self._sslcontext, 'check_hostname'):
- # Verify hostname if requested, Python 3.4+ uses check_hostname
- # and checks the hostname in do_handshake()
- if (self._server_hostname and
- self._sslcontext.verify_mode != ssl.CERT_NONE):
- try:
- ssl.match_hostname(peercert, self._server_hostname)
- except Exception as exc:
- if self._loop.get_debug():
- logger.warning("%r: SSL handshake failed "
- "on matching the hostname",
- self, exc_info=True)
- self._sock.close()
- self._wakeup_waiter(exc)
- return
-
- # Add extra info that becomes available after handshake.
- self._extra.update(peercert=peercert,
- cipher=self._sock.cipher(),
- compression=self._sock.compression(),
- ssl_object=self._sock,
- )
-
- self._read_wants_write = False
- self._write_wants_read = False
- self._loop._add_reader(self._sock_fd, self._read_ready)
- self._protocol_connected = True
- self._loop.call_soon(self._protocol.connection_made, self)
- # only wake up the waiter when connection_made() has been called
- self._loop.call_soon(self._wakeup_waiter)
-
- if self._loop.get_debug():
- dt = self._loop.time() - start_time
- logger.debug("%r: SSL handshake took %.1f ms", self, dt * 1e3)
-
- def pause_reading(self):
- # XXX This is a bit icky, given the comment at the top of
- # _read_ready(). Is it possible to evoke a deadlock? I don't
- # know, although it doesn't look like it; write() will still
- # accept more data for the buffer and eventually the app will
- # call resume_reading() again, and things will flow again.
-
- if self._closing:
- raise RuntimeError('Cannot pause_reading() when closing')
- if self._paused:
- raise RuntimeError('Already paused')
- self._paused = True
- self._loop._remove_reader(self._sock_fd)
- if self._loop.get_debug():
- logger.debug("%r pauses reading", self)
-
- def resume_reading(self):
- if not self._paused:
- raise RuntimeError('Not paused')
- self._paused = False
- if self._closing:
- return
- self._loop._add_reader(self._sock_fd, self._read_ready)
- if self._loop.get_debug():
- logger.debug("%r resumes reading", self)
-
- def _read_ready(self):
- if self._conn_lost:
- return
- if self._write_wants_read:
- self._write_wants_read = False
- self._write_ready()
-
- if self._buffer:
- self._loop._add_writer(self._sock_fd, self._write_ready)
-
- try:
- data = self._sock.recv(self.max_size)
- except (BlockingIOError, InterruptedError, ssl.SSLWantReadError):
- pass
- except ssl.SSLWantWriteError:
- self._read_wants_write = True
- self._loop._remove_reader(self._sock_fd)
- self._loop._add_writer(self._sock_fd, self._write_ready)
- except Exception as exc:
- self._fatal_error(exc, 'Fatal read error on SSL transport')
- else:
- if data:
- self._protocol.data_received(data)
- else:
- try:
- if self._loop.get_debug():
- logger.debug("%r received EOF", self)
- keep_open = self._protocol.eof_received()
- if keep_open:
- logger.warning('returning true from eof_received() '
- 'has no effect when using ssl')
- finally:
- self.close()
-
- def _write_ready(self):
- if self._conn_lost:
- return
- if self._read_wants_write:
- self._read_wants_write = False
- self._read_ready()
-
- if not (self._paused or self._closing):
- self._loop._add_reader(self._sock_fd, self._read_ready)
-
- if self._buffer:
- try:
- n = self._sock.send(self._buffer)
- except (BlockingIOError, InterruptedError, ssl.SSLWantWriteError):
- n = 0
- except ssl.SSLWantReadError:
- n = 0
- self._loop._remove_writer(self._sock_fd)
- self._write_wants_read = True
- except Exception as exc:
- self._loop._remove_writer(self._sock_fd)
- self._buffer.clear()
- self._fatal_error(exc, 'Fatal write error on SSL transport')
- return
-
- if n:
- del self._buffer[:n]
-
- self._maybe_resume_protocol() # May append to buffer.
-
- if not self._buffer:
- self._loop._remove_writer(self._sock_fd)
- if self._closing:
- self._call_connection_lost(None)
-
- def write(self, data):
- if not isinstance(data, (bytes, bytearray, memoryview)):
- raise TypeError('data argument must be a bytes-like object, '
- 'not %r' % type(data).__name__)
- if not data:
- return
-
- if self._conn_lost:
- if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES:
- logger.warning('socket.send() raised exception.')
- self._conn_lost += 1
- return
-
- if not self._buffer:
- self._loop._add_writer(self._sock_fd, self._write_ready)
-
- # Add it to the buffer.
- self._buffer.extend(data)
- self._maybe_pause_protocol()
-
- def can_write_eof(self):
- return False
-
-
class _SelectorDatagramTransport(_SelectorTransport):
_buffer_factory = collections.deque
diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py
index 53e6d2b667..c231eb58ee 100644
--- a/Lib/asyncio/sslproto.py
+++ b/Lib/asyncio/sslproto.py
@@ -18,25 +18,13 @@ def _create_transport_context(server_side, server_hostname):
# Client side may pass ssl=True to use a default
# context; in that case the sslcontext passed is None.
# 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
+ # Python 3.4+: use up-to-date strong settings.
+ sslcontext = ssl.create_default_context()
+ if not server_hostname:
+ sslcontext.check_hostname = False
return sslcontext
-def _is_sslproto_available():
- return hasattr(ssl, "MemoryBIO")
-
-
# States of an _SSLPipe.
_UNWRAPPED = "UNWRAPPED"
_DO_HANDSHAKE = "DO_HANDSHAKE"
diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py
index c9b19825f2..c3ddfe3756 100644
--- a/Lib/asyncio/test_utils.py
+++ b/Lib/asyncio/test_utils.py
@@ -508,8 +508,3 @@ def mock_nonblocking_socket(proto=socket.IPPROTO_TCP, type=socket.SOCK_STREAM,
sock.family = family
sock.gettimeout.return_value = 0.0
return sock
-
-
-def force_legacy_ssl_support():
- return mock.patch('asyncio.sslproto._is_sslproto_available',
- return_value=False)