Skip to content

Commit ca99e00

Browse files
committed
Raise a DeprecationWarning instead of ValueError
1 parent 1712d5b commit ca99e00

6 files changed

Lines changed: 39 additions & 35 deletions

File tree

‎Doc/library/asyncio-eventloop.rst‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,9 @@ Opening network connections
545545
*all_errors* was added.
546546

547547
.. versionchanged:: next
548-
Raises a ``ValueError`` if ``ssl.check_hostname`` is ``True``
549-
and ``server_hostname`` is not supplied.
548+
Raises a ``DeprecationWarning`` if ``ssl.check_hostname`` is ``True``
549+
and ``server_hostname`` is not supplied. In Python 3.13 and
550+
later a ``ValueError`` is raised instead.
550551

551552
.. seealso::
552553

‎Doc/library/asyncio-stream.rst‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,9 @@ StreamWriter
383383
Added the *ssl_shutdown_timeout* parameter.
384384

385385
.. versionchanged:: next
386-
Raises a ``ValueError`` if ``sslcontext.check_hostname`` is ``True``
387-
and ``server_hostname`` is not supplied.
386+
Raises a ``DeprecationWarning`` if ``ssl.check_hostname`` is ``True``
387+
and ``server_hostname`` is not supplied. In Python 3.13 and
388+
later a ``ValueError`` is raised instead.
388389

389390

390391
.. method:: is_closing()

‎Doc/library/ssl.rst‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,10 +1810,10 @@ to speed up repeated connections from the same clients.
18101810

18111811
The *server_side*, *server_hostname* and *session* parameters have the
18121812
same meaning as in :meth:`SSLContext.wrap_socket`, and are validated in
1813-
the same way: in particular a :exc:`ValueError` is raised when
1813+
the same way: in particular a :exc:`DeprecationWarning` is raised when
18141814
:attr:`~SSLContext.check_hostname` is enabled but no *server_hostname* is
18151815
given, since there would be no name to match the peer's certificate
1816-
against.
1816+
against. In Python 3.13 and later a ``ValueError`` is raised instead.
18171817

18181818
.. versionchanged:: 3.6
18191819
*session* argument was added.

‎Lib/ssl.py‎

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -373,20 +373,6 @@ def _ipaddress_match(cert_ipaddress, host_ip):
373373
return ip == host_ip
374374

375375

376-
def _check_sslobject_params(server_side, context=None, server_hostname=None, session=None):
377-
"""Raises a ValueError if SSLObject._create() parameters aren't valid.
378-
"""
379-
if server_side:
380-
if server_hostname:
381-
raise ValueError("server_hostname can only be specified "
382-
"in client mode")
383-
if session is not None:
384-
raise ValueError("session can only be specified in "
385-
"client mode")
386-
if context.check_hostname and not server_hostname:
387-
raise ValueError("check_hostname requires server_hostname")
388-
389-
390376
DefaultVerifyPaths = namedtuple("DefaultVerifyPaths",
391377
"cafile capath openssl_cafile_env openssl_cafile openssl_capath_env "
392378
"openssl_capath")
@@ -817,8 +803,18 @@ def __init__(self, *args, **kwargs):
817803
@classmethod
818804
def _create(cls, incoming, outgoing, server_side=False,
819805
server_hostname=None, session=None, context=None):
820-
_check_sslobject_params(server_side=server_side, context=context,
821-
server_hostname=server_hostname, session=session)
806+
if server_side:
807+
if server_hostname:
808+
raise ValueError("server_hostname can only be specified "
809+
"in client mode")
810+
if session is not None:
811+
raise ValueError("session can only be specified in "
812+
"client mode")
813+
if context.check_hostname and not server_hostname:
814+
warnings.warn("check_hostname requires server_hostname",
815+
category=DeprecationWarning,
816+
stacklevel=3)
817+
822818
self = cls.__new__(cls)
823819
sslobj = context._wrap_bio(
824820
incoming, outgoing, server_side=server_side,
@@ -974,8 +970,15 @@ def _create(cls, sock, server_side=False, do_handshake_on_connect=True,
974970
context=None, session=None):
975971
if sock.getsockopt(SOL_SOCKET, SO_TYPE) != SOCK_STREAM:
976972
raise NotImplementedError("only stream sockets are supported")
977-
_check_sslobject_params(server_side=server_side, context=context,
978-
server_hostname=server_hostname, session=session)
973+
if server_side:
974+
if server_hostname:
975+
raise ValueError("server_hostname can only be specified "
976+
"in client mode")
977+
if session is not None:
978+
raise ValueError("session can only be specified in "
979+
"client mode")
980+
if context.check_hostname and not server_hostname:
981+
raise ValueError("check_hostname requires server_hostname")
979982

980983
sock_timeout = sock.gettimeout()
981984
kwargs = dict(

‎Lib/test/test_asyncio/test_sslproto.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ def test_check_hostname_requires_server_hostname(self, server_hostname):
9696
waiter = mock.Mock()
9797

9898
# Supplying an empty server_hostname fails with check_hostname enabled.
99-
with self.assertRaisesRegex(
100-
ValueError,
99+
with self.assertWarnsRegex(
100+
UserWarning,
101101
'check_hostname requires server_hostname'):
102102
sslproto.SSLProtocol(self.loop, app_proto, sslcontext,
103103
waiter,

‎Lib/test/test_ssl.py‎

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,10 +1722,10 @@ def test_subclass(self):
17221722
def test_bad_server_hostname(self):
17231723
ctx = ssl.create_default_context()
17241724
# Omitting the name entirely is bad too: this context checks it.
1725-
with self.assertRaises(ValueError):
1725+
with self.assertWarns(DeprecationWarning):
17261726
ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
17271727
server_hostname=None)
1728-
with self.assertRaises(ValueError):
1728+
with self.assertRaises(DeprecationWarning):
17291729
ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
17301730
server_hostname="")
17311731
with self.assertRaises(ValueError):
@@ -1812,23 +1812,22 @@ def test_private_init(self):
18121812
def test_check_hostname_requires_server_hostname(self):
18131813
# wrap_bio() used to accept a context asking for hostname checking
18141814
# without a name to check against, and then verify the certificate
1815-
# chain but never the peer's identity, with check_hostname still
1816-
# reporting True and nothing reporting the check had been skipped.
1817-
# It must refuse that call, as wrap_socket() already did.
1815+
# chain but never the peer's identity without a warning. Now
1816+
# a warning is emitted in this scenario.
18181817
client_context, _, hostname = testing_context()
18191818
self.assertTrue(client_context.check_hostname)
18201819

18211820
for server_hostname in (None, ""):
18221821
with self.subTest(server_hostname=server_hostname):
1823-
with self.assertRaisesRegex(
1824-
ValueError,
1822+
with self.assertWarnsRegex(
1823+
DeprecationWarning,
18251824
"check_hostname requires server_hostname"):
18261825
client_context.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
18271826
server_hostname=server_hostname)
18281827
# The sibling constructor refuses the very same call.
18291828
with socket.socket() as sock:
1830-
with self.assertRaisesRegex(
1831-
ValueError,
1829+
with self.assertWarnsRegex(
1830+
DeprecationWarning,
18321831
"check_hostname requires server_hostname"):
18331832
client_context.wrap_socket(
18341833
sock, server_hostname=server_hostname)

0 commit comments

Comments
 (0)