mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
bpo-45129 Remove deprecated reuse_address (GH-28207)
Due to significant security concerns, the reuse_address parameter of asyncio.loop.create_datagram_endpoint, deprecated in Python 3.9, is now removed. This is because of the behavior of the socket option SO_REUSEADDR in UDP. Co-authored-by: Łukasz Langa <lukasz@langa.pl>
This commit is contained in:
parent
a561005761
commit
59ea704df7
5 changed files with 33 additions and 70 deletions
|
@ -493,24 +493,9 @@ Opening network connections
|
||||||
.. coroutinemethod:: loop.create_datagram_endpoint(protocol_factory, \
|
.. coroutinemethod:: loop.create_datagram_endpoint(protocol_factory, \
|
||||||
local_addr=None, remote_addr=None, *, \
|
local_addr=None, remote_addr=None, *, \
|
||||||
family=0, proto=0, flags=0, \
|
family=0, proto=0, flags=0, \
|
||||||
reuse_address=None, reuse_port=None, \
|
reuse_port=None, \
|
||||||
allow_broadcast=None, sock=None)
|
allow_broadcast=None, sock=None)
|
||||||
|
|
||||||
.. note::
|
|
||||||
The parameter *reuse_address* is no longer supported, as using
|
|
||||||
:py:data:`~sockets.SO_REUSEADDR` poses a significant security concern for
|
|
||||||
UDP. Explicitly passing ``reuse_address=True`` will raise an exception.
|
|
||||||
|
|
||||||
When multiple processes with differing UIDs assign sockets to an
|
|
||||||
identical UDP socket address with ``SO_REUSEADDR``, incoming packets can
|
|
||||||
become randomly distributed among the sockets.
|
|
||||||
|
|
||||||
For supported platforms, *reuse_port* can be used as a replacement for
|
|
||||||
similar functionality. With *reuse_port*,
|
|
||||||
:py:data:`~sockets.SO_REUSEPORT` is used instead, which specifically
|
|
||||||
prevents processes with differing UIDs from assigning sockets to the same
|
|
||||||
socket address.
|
|
||||||
|
|
||||||
Create a datagram connection.
|
Create a datagram connection.
|
||||||
|
|
||||||
The socket family can be either :py:data:`~socket.AF_INET`,
|
The socket family can be either :py:data:`~socket.AF_INET`,
|
||||||
|
@ -557,16 +542,31 @@ Opening network connections
|
||||||
:ref:`UDP echo server protocol <asyncio-udp-echo-server-protocol>` examples.
|
:ref:`UDP echo server protocol <asyncio-udp-echo-server-protocol>` examples.
|
||||||
|
|
||||||
.. versionchanged:: 3.4.4
|
.. versionchanged:: 3.4.4
|
||||||
The *family*, *proto*, *flags*, *reuse_address*, *reuse_port,
|
The *family*, *proto*, *flags*, *reuse_address*, *reuse_port*,
|
||||||
*allow_broadcast*, and *sock* parameters were added.
|
*allow_broadcast*, and *sock* parameters were added.
|
||||||
|
|
||||||
.. versionchanged:: 3.8.1
|
.. versionchanged:: 3.8.1
|
||||||
The *reuse_address* parameter is no longer supported due to security
|
The *reuse_address* parameter is no longer supported, as using
|
||||||
concerns.
|
:py:data:`~sockets.SO_REUSEADDR` poses a significant security concern for
|
||||||
|
UDP. Explicitly passing ``reuse_address=True`` will raise an exception.
|
||||||
|
|
||||||
|
When multiple processes with differing UIDs assign sockets to an
|
||||||
|
identical UDP socket address with ``SO_REUSEADDR``, incoming packets can
|
||||||
|
become randomly distributed among the sockets.
|
||||||
|
|
||||||
|
For supported platforms, *reuse_port* can be used as a replacement for
|
||||||
|
similar functionality. With *reuse_port*,
|
||||||
|
:py:data:`~sockets.SO_REUSEPORT` is used instead, which specifically
|
||||||
|
prevents processes with differing UIDs from assigning sockets to the same
|
||||||
|
socket address.
|
||||||
|
|
||||||
.. versionchanged:: 3.8
|
.. versionchanged:: 3.8
|
||||||
Added support for Windows.
|
Added support for Windows.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.11
|
||||||
|
The *reuse_address* parameter, disabled since Python 3.9.0, 3.8.1,
|
||||||
|
3.7.6 and 3.6.10, has been entirely removed.
|
||||||
|
|
||||||
.. coroutinemethod:: loop.create_unix_connection(protocol_factory, \
|
.. coroutinemethod:: loop.create_unix_connection(protocol_factory, \
|
||||||
path=None, *, ssl=None, sock=None, \
|
path=None, *, ssl=None, sock=None, \
|
||||||
server_hostname=None, ssl_handshake_timeout=None)
|
server_hostname=None, ssl_handshake_timeout=None)
|
||||||
|
|
|
@ -254,6 +254,12 @@ Removed
|
||||||
Use ``bdist_wheel`` (wheel packages) instead.
|
Use ``bdist_wheel`` (wheel packages) instead.
|
||||||
(Contributed by Hugo van Kemenade in :issue:`45124`.)
|
(Contributed by Hugo van Kemenade in :issue:`45124`.)
|
||||||
|
|
||||||
|
* Due to significant security concerns, the *reuse_address* parameter of
|
||||||
|
:meth:`asyncio.loop.create_datagram_endpoint`, disabled in Python 3.9, is
|
||||||
|
now entirely removed. This is because of the behavior of the socket option
|
||||||
|
``SO_REUSEADDR`` in UDP.
|
||||||
|
(Contributed by Hugo van Kemenade in :issue:`45129`.)
|
||||||
|
|
||||||
* Remove :meth:`__getitem__` methods of
|
* Remove :meth:`__getitem__` methods of
|
||||||
:class:`xml.dom.pulldom.DOMEventStream`, :class:`wsgiref.util.FileWrapper`
|
:class:`xml.dom.pulldom.DOMEventStream`, :class:`wsgiref.util.FileWrapper`
|
||||||
and :class:`fileinput.FileInput`, deprecated since Python 3.9.
|
and :class:`fileinput.FileInput`, deprecated since Python 3.9.
|
||||||
|
|
|
@ -66,10 +66,6 @@ _HAS_IPv6 = hasattr(socket, 'AF_INET6')
|
||||||
# Maximum timeout passed to select to avoid OS limitations
|
# Maximum timeout passed to select to avoid OS limitations
|
||||||
MAXIMUM_SELECT_TIMEOUT = 24 * 3600
|
MAXIMUM_SELECT_TIMEOUT = 24 * 3600
|
||||||
|
|
||||||
# Used for deprecation and removal of `loop.create_datagram_endpoint()`'s
|
|
||||||
# *reuse_address* parameter
|
|
||||||
_unset = object()
|
|
||||||
|
|
||||||
|
|
||||||
def _format_handle(handle):
|
def _format_handle(handle):
|
||||||
cb = handle._callback
|
cb = handle._callback
|
||||||
|
@ -1235,7 +1231,7 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
async def create_datagram_endpoint(self, protocol_factory,
|
async def create_datagram_endpoint(self, protocol_factory,
|
||||||
local_addr=None, remote_addr=None, *,
|
local_addr=None, remote_addr=None, *,
|
||||||
family=0, proto=0, flags=0,
|
family=0, proto=0, flags=0,
|
||||||
reuse_address=_unset, reuse_port=None,
|
reuse_port=None,
|
||||||
allow_broadcast=None, sock=None):
|
allow_broadcast=None, sock=None):
|
||||||
"""Create datagram connection."""
|
"""Create datagram connection."""
|
||||||
if sock is not None:
|
if sock is not None:
|
||||||
|
@ -1248,7 +1244,7 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
# show the problematic kwargs in exception msg
|
# show the problematic kwargs in exception msg
|
||||||
opts = dict(local_addr=local_addr, remote_addr=remote_addr,
|
opts = dict(local_addr=local_addr, remote_addr=remote_addr,
|
||||||
family=family, proto=proto, flags=flags,
|
family=family, proto=proto, flags=flags,
|
||||||
reuse_address=reuse_address, reuse_port=reuse_port,
|
reuse_port=reuse_port,
|
||||||
allow_broadcast=allow_broadcast)
|
allow_broadcast=allow_broadcast)
|
||||||
problems = ', '.join(f'{k}={v}' for k, v in opts.items() if v)
|
problems = ', '.join(f'{k}={v}' for k, v in opts.items() if v)
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@ -1311,19 +1307,6 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
|
|
||||||
exceptions = []
|
exceptions = []
|
||||||
|
|
||||||
# bpo-37228
|
|
||||||
if reuse_address is not _unset:
|
|
||||||
if reuse_address:
|
|
||||||
raise ValueError("Passing `reuse_address=True` is no "
|
|
||||||
"longer supported, as the usage of "
|
|
||||||
"SO_REUSEPORT in UDP poses a significant "
|
|
||||||
"security concern.")
|
|
||||||
else:
|
|
||||||
warnings.warn("The *reuse_address* parameter has been "
|
|
||||||
"deprecated as of 3.5.10 and is scheduled "
|
|
||||||
"for removal in 3.11.", DeprecationWarning,
|
|
||||||
stacklevel=2)
|
|
||||||
|
|
||||||
for ((family, proto),
|
for ((family, proto),
|
||||||
(local_address, remote_address)) in addr_pairs_info:
|
(local_address, remote_address)) in addr_pairs_info:
|
||||||
sock = None
|
sock = None
|
||||||
|
@ -1407,7 +1390,6 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
sock=None,
|
sock=None,
|
||||||
backlog=100,
|
backlog=100,
|
||||||
ssl=None,
|
ssl=None,
|
||||||
reuse_address=None,
|
|
||||||
reuse_port=None,
|
reuse_port=None,
|
||||||
ssl_handshake_timeout=None,
|
ssl_handshake_timeout=None,
|
||||||
start_serving=True):
|
start_serving=True):
|
||||||
|
@ -1438,8 +1420,6 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
'host/port and sock can not be specified at the same time')
|
'host/port and sock can not be specified at the same time')
|
||||||
|
|
||||||
if reuse_address is None:
|
|
||||||
reuse_address = os.name == 'posix' and sys.platform != 'cygwin'
|
|
||||||
sockets = []
|
sockets = []
|
||||||
if host == '':
|
if host == '':
|
||||||
hosts = [None]
|
hosts = [None]
|
||||||
|
@ -1469,9 +1449,6 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
af, socktype, proto, exc_info=True)
|
af, socktype, proto, exc_info=True)
|
||||||
continue
|
continue
|
||||||
sockets.append(sock)
|
sockets.append(sock)
|
||||||
if reuse_address:
|
|
||||||
sock.setsockopt(
|
|
||||||
socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
|
|
||||||
if reuse_port:
|
if reuse_port:
|
||||||
_set_reuseport(sock)
|
_set_reuseport(sock)
|
||||||
# Disable IPv4/IPv6 dual stack support (enabled by
|
# Disable IPv4/IPv6 dual stack support (enabled by
|
||||||
|
|
|
@ -1794,32 +1794,6 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
|
||||||
self.loop.run_until_complete(protocol.done)
|
self.loop.run_until_complete(protocol.done)
|
||||||
self.assertEqual('CLOSED', protocol.state)
|
self.assertEqual('CLOSED', protocol.state)
|
||||||
|
|
||||||
def test_create_datagram_endpoint_reuse_address_error(self):
|
|
||||||
# bpo-37228: Ensure that explicit passing of `reuse_address=True`
|
|
||||||
# raises an error, as it is not safe to use SO_REUSEADDR when using UDP
|
|
||||||
|
|
||||||
coro = self.loop.create_datagram_endpoint(
|
|
||||||
lambda: MyDatagramProto(create_future=True, loop=self.loop),
|
|
||||||
local_addr=('127.0.0.1', 0),
|
|
||||||
reuse_address=True)
|
|
||||||
|
|
||||||
with self.assertRaises(ValueError):
|
|
||||||
self.loop.run_until_complete(coro)
|
|
||||||
|
|
||||||
def test_create_datagram_endpoint_reuse_address_warning(self):
|
|
||||||
# bpo-37228: Deprecate *reuse_address* parameter
|
|
||||||
|
|
||||||
coro = self.loop.create_datagram_endpoint(
|
|
||||||
lambda: MyDatagramProto(create_future=True, loop=self.loop),
|
|
||||||
local_addr=('127.0.0.1', 0),
|
|
||||||
reuse_address=False)
|
|
||||||
|
|
||||||
with self.assertWarns(DeprecationWarning):
|
|
||||||
transport, protocol = self.loop.run_until_complete(coro)
|
|
||||||
transport.close()
|
|
||||||
self.loop.run_until_complete(protocol.done)
|
|
||||||
self.assertEqual('CLOSED', protocol.state)
|
|
||||||
|
|
||||||
@patch_socket
|
@patch_socket
|
||||||
def test_create_datagram_endpoint_nosoreuseport(self, m_socket):
|
def test_create_datagram_endpoint_nosoreuseport(self, m_socket):
|
||||||
del m_socket.SO_REUSEPORT
|
del m_socket.SO_REUSEPORT
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
Due to significant security concerns, the *reuse_address* parameter of
|
||||||
|
:meth:`asyncio.loop.create_datagram_endpoint`, disabled in Python 3.9, is
|
||||||
|
now entirely removed. This is because of the behavior of the socket option
|
||||||
|
``SO_REUSEADDR`` in UDP.
|
||||||
|
|
||||||
|
Patch by Hugo van Kemenade.
|
Loading…
Add table
Add a link
Reference in a new issue