Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 51d546a

Browse files
authored
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
1 parent f02f5e5 commit 51d546a

7 files changed

Lines changed: 5 additions & 705 deletions

File tree

Lib/asyncio/proactor_events.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -392,11 +392,6 @@ def _make_socket_transport(self, sock, protocol, waiter=None,
392392
def _make_ssl_transport(self, rawsock, protocol, sslcontext, waiter=None,
393393
*, server_side=False, server_hostname=None,
394394
extra=None, server=None):
395-
if not sslproto._is_sslproto_available():
396-
raise NotImplementedError("Proactor event loop requires Python 3.5"
397-
" or newer (ssl.MemoryBIO) to support "
398-
"SSL")
399-
400395
ssl_protocol = sslproto.SSLProtocol(self, protocol, sslcontext, waiter,
401396
server_side, server_hostname)
402397
_ProactorSocketTransport(self, rawsock, ssl_protocol,

Lib/asyncio/selector_events.py

Lines changed: 0 additions & 248 deletions
Original file line numberDiff line numberDiff line change
@@ -74,28 +74,12 @@ def _make_socket_transport(self, sock, protocol, waiter=None, *,
7474
def _make_ssl_transport(self, rawsock, protocol, sslcontext, waiter=None,
7575
*, server_side=False, server_hostname=None,
7676
extra=None, server=None):
77-
if not sslproto._is_sslproto_available():
78-
return self._make_legacy_ssl_transport(
79-
rawsock, protocol, sslcontext, waiter,
80-
server_side=server_side, server_hostname=server_hostname,
81-
extra=extra, server=server)
82-
8377
ssl_protocol = sslproto.SSLProtocol(self, protocol, sslcontext, waiter,
8478
server_side, server_hostname)
8579
_SelectorSocketTransport(self, rawsock, ssl_protocol,
8680
extra=extra, server=server)
8781
return ssl_protocol._app_transport
8882

89-
def _make_legacy_ssl_transport(self, rawsock, protocol, sslcontext,
90-
waiter, *,
91-
server_side=False, server_hostname=None,
92-
extra=None, server=None):
93-
# Use the legacy API: SSL_write, SSL_read, etc. The legacy API is used
94-
# on Python 3.4 and older, when ssl.MemoryBIO is not available.
95-
return _SelectorSslTransport(
96-
self, rawsock, protocol, sslcontext, waiter,
97-
server_side, server_hostname, extra, server)
98-
9983
def _make_datagram_transport(self, sock, protocol,
10084
address=None, waiter=None, extra=None):
10185
return _SelectorDatagramTransport(self, sock, protocol,
@@ -848,238 +832,6 @@ def can_write_eof(self):
848832
return True
849833

850834

851-
class _SelectorSslTransport(_SelectorTransport):
852-
853-
_buffer_factory = bytearray
854-
855-
def __init__(self, loop, rawsock, protocol, sslcontext, waiter=None,
856-
server_side=False, server_hostname=None,
857-
extra=None, server=None):
858-
if ssl is None:
859-
raise RuntimeError('stdlib ssl module not available')
860-
861-
if not sslcontext:
862-
sslcontext = sslproto._create_transport_context(server_side, server_hostname)
863-
864-
wrap_kwargs = {
865-
'server_side': server_side,
866-
'do_handshake_on_connect': False,
867-
}
868-
if server_hostname and not server_side:
869-
wrap_kwargs['server_hostname'] = server_hostname
870-
sslsock = sslcontext.wrap_socket(rawsock, **wrap_kwargs)
871-
872-
super().__init__(loop, sslsock, protocol, extra, server)
873-
# the protocol connection is only made after the SSL handshake
874-
self._protocol_connected = False
875-
876-
self._server_hostname = server_hostname
877-
self._waiter = waiter
878-
self._sslcontext = sslcontext
879-
self._paused = False
880-
881-
# SSL-specific extra info. (peercert is set later)
882-
self._extra.update(sslcontext=sslcontext)
883-
884-
if self._loop.get_debug():
885-
logger.debug("%r starts SSL handshake", self)
886-
start_time = self._loop.time()
887-
else:
888-
start_time = None
889-
self._on_handshake(start_time)
890-
891-
def _wakeup_waiter(self, exc=None):
892-
if self._waiter is None:
893-
return
894-
if not self._waiter.cancelled():
895-
if exc is not None:
896-
self._waiter.set_exception(exc)
897-
else:
898-
self._waiter.set_result(None)
899-
self._waiter = None
900-
901-
def _on_handshake(self, start_time):
902-
try:
903-
self._sock.do_handshake()
904-
except ssl.SSLWantReadError:
905-
self._loop._add_reader(self._sock_fd,
906-
self._on_handshake, start_time)
907-
return
908-
except ssl.SSLWantWriteError:
909-
self._loop._add_writer(self._sock_fd,
910-
self._on_handshake, start_time)
911-
return
912-
except BaseException as exc:
913-
if self._loop.get_debug():
914-
logger.warning("%r: SSL handshake failed",
915-
self, exc_info=True)
916-
self._loop._remove_reader(self._sock_fd)
917-
self._loop._remove_writer(self._sock_fd)
918-
self._sock.close()
919-
self._wakeup_waiter(exc)
920-
if isinstance(exc, Exception):
921-
return
922-
else:
923-
raise
924-
925-
self._loop._remove_reader(self._sock_fd)
926-
self._loop._remove_writer(self._sock_fd)
927-
928-
peercert = self._sock.getpeercert()
929-
if not hasattr(self._sslcontext, 'check_hostname'):
930-
# Verify hostname if requested, Python 3.4+ uses check_hostname
931-
# and checks the hostname in do_handshake()
932-
if (self._server_hostname and
933-
self._sslcontext.verify_mode != ssl.CERT_NONE):
934-
try:
935-
ssl.match_hostname(peercert, self._server_hostname)
936-
except Exception as exc:
937-
if self._loop.get_debug():
938-
logger.warning("%r: SSL handshake failed "
939-
"on matching the hostname",
940-
self, exc_info=True)
941-
self._sock.close()
942-
self._wakeup_waiter(exc)
943-
return
944-
945-
# Add extra info that becomes available after handshake.
946-
self._extra.update(peercert=peercert,
947-
cipher=self._sock.cipher(),
948-
compression=self._sock.compression(),
949-
ssl_object=self._sock,
950-
)
951-
952-
self._read_wants_write = False
953-
self._write_wants_read = False
954-
self._loop._add_reader(self._sock_fd, self._read_ready)
955-
self._protocol_connected = True
956-
self._loop.call_soon(self._protocol.connection_made, self)
957-
# only wake up the waiter when connection_made() has been called
958-
self._loop.call_soon(self._wakeup_waiter)
959-
960-
if self._loop.get_debug():
961-
dt = self._loop.time() - start_time
962-
logger.debug("%r: SSL handshake took %.1f ms", self, dt * 1e3)
963-
964-
def pause_reading(self):
965-
# XXX This is a bit icky, given the comment at the top of
966-
# _read_ready(). Is it possible to evoke a deadlock? I don't
967-
# know, although it doesn't look like it; write() will still
968-
# accept more data for the buffer and eventually the app will
969-
# call resume_reading() again, and things will flow again.
970-
971-
if self._closing:
972-
raise RuntimeError('Cannot pause_reading() when closing')
973-
if self._paused:
974-
raise RuntimeError('Already paused')
975-
self._paused = True
976-
self._loop._remove_reader(self._sock_fd)
977-
if self._loop.get_debug():
978-
logger.debug("%r pauses reading", self)
979-
980-
def resume_reading(self):
981-
if not self._paused:
982-
raise RuntimeError('Not paused')
983-
self._paused = False
984-
if self._closing:
985-
return
986-
self._loop._add_reader(self._sock_fd, self._read_ready)
987-
if self._loop.get_debug():
988-
logger.debug("%r resumes reading", self)
989-
990-
def _read_ready(self):
991-
if self._conn_lost:
992-
return
993-
if self._write_wants_read:
994-
self._write_wants_read = False
995-
self._write_ready()
996-
997-
if self._buffer:
998-
self._loop._add_writer(self._sock_fd, self._write_ready)
999-
1000-
try:
1001-
data = self._sock.recv(self.max_size)
1002-
except (BlockingIOError, InterruptedError, ssl.SSLWantReadError):
1003-
pass
1004-
except ssl.SSLWantWriteError:
1005-
self._read_wants_write = True
1006-
self._loop._remove_reader(self._sock_fd)
1007-
self._loop._add_writer(self._sock_fd, self._write_ready)
1008-
except Exception as exc:
1009-
self._fatal_error(exc, 'Fatal read error on SSL transport')
1010-
else:
1011-
if data:
1012-
self._protocol.data_received(data)
1013-
else:
1014-
try:
1015-
if self._loop.get_debug():
1016-
logger.debug("%r received EOF", self)
1017-
keep_open = self._protocol.eof_received()
1018-
if keep_open:
1019-
logger.warning('returning true from eof_received() '
1020-
'has no effect when using ssl')
1021-
finally:
1022-
self.close()
1023-
1024-
def _write_ready(self):
1025-
if self._conn_lost:
1026-
return
1027-
if self._read_wants_write:
1028-
self._read_wants_write = False
1029-
self._read_ready()
1030-
1031-
if not (self._paused or self._closing):
1032-
self._loop._add_reader(self._sock_fd, self._read_ready)
1033-
1034-
if self._buffer:
1035-
try:
1036-
n = self._sock.send(self._buffer)
1037-
except (BlockingIOError, InterruptedError, ssl.SSLWantWriteError):
1038-
n = 0
1039-
except ssl.SSLWantReadError:
1040-
n = 0
1041-
self._loop._remove_writer(self._sock_fd)
1042-
self._write_wants_read = True
1043-
except Exception as exc:
1044-
self._loop._remove_writer(self._sock_fd)
1045-
self._buffer.clear()
1046-
self._fatal_error(exc, 'Fatal write error on SSL transport')
1047-
return
1048-
1049-
if n:
1050-
del self._buffer[:n]
1051-
1052-
self._maybe_resume_protocol() # May append to buffer.
1053-
1054-
if not self._buffer:
1055-
self._loop._remove_writer(self._sock_fd)
1056-
if self._closing:
1057-
self._call_connection_lost(None)
1058-
1059-
def write(self, data):
1060-
if not isinstance(data, (bytes, bytearray, memoryview)):
1061-
raise TypeError('data argument must be a bytes-like object, '
1062-
'not %r' % type(data).__name__)
1063-
if not data:
1064-
return
1065-
1066-
if self._conn_lost:
1067-
if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES:
1068-
logger.warning('socket.send() raised exception.')
1069-
self._conn_lost += 1
1070-
return
1071-
1072-
if not self._buffer:
1073-
self._loop._add_writer(self._sock_fd, self._write_ready)
1074-
1075-
# Add it to the buffer.
1076-
self._buffer.extend(data)
1077-
self._maybe_pause_protocol()
1078-
1079-
def can_write_eof(self):
1080-
return False
1081-
1082-
1083835
class _SelectorDatagramTransport(_SelectorTransport):
1084836

1085837
_buffer_factory = collections.deque

Lib/asyncio/sslproto.py

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,13 @@ def _create_transport_context(server_side, server_hostname):
1818
# Client side may pass ssl=True to use a default
1919
# context; in that case the sslcontext passed is None.
2020
# The default is secure for client connections.
21-
if hasattr(ssl, 'create_default_context'):
22-
# Python 3.4+: use up-to-date strong settings.
23-
sslcontext = ssl.create_default_context()
24-
if not server_hostname:
25-
sslcontext.check_hostname = False
26-
else:
27-
# Fallback for Python 3.3.
28-
sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
29-
sslcontext.options |= ssl.OP_NO_SSLv2
30-
sslcontext.options |= ssl.OP_NO_SSLv3
31-
sslcontext.set_default_verify_paths()
32-
sslcontext.verify_mode = ssl.CERT_REQUIRED
21+
# Python 3.4+: use up-to-date strong settings.
22+
sslcontext = ssl.create_default_context()
23+
if not server_hostname:
24+
sslcontext.check_hostname = False
3325
return sslcontext
3426

3527

36-
def _is_sslproto_available():
37-
return hasattr(ssl, "MemoryBIO")
38-
39-
4028
# States of an _SSLPipe.
4129
_UNWRAPPED = "UNWRAPPED"
4230
_DO_HANDSHAKE = "DO_HANDSHAKE"

Lib/asyncio/test_utils.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,3 @@ def mock_nonblocking_socket(proto=socket.IPPROTO_TCP, type=socket.SOCK_STREAM,
508508
sock.family = family
509509
sock.gettimeout.return_value = 0.0
510510
return sock
511-
512-
513-
def force_legacy_ssl_support():
514-
return mock.patch('asyncio.sslproto._is_sslproto_available',
515-
return_value=False)

0 commit comments

Comments
 (0)