8000 bpo-44362: ssl: improve deprecation warnings and docs (GH-26646) · python/cpython@e26014f · GitHub
[go: up one dir, main page]

Skip to content

Commit e26014f

Browse files
authored
bpo-44362: ssl: improve deprecation warnings and docs (GH-26646)
Signed-off-by: Christian Heimes <christian@python.org>
1 parent c4955e2 commit e26014f

File tree

6 files changed

+98
-47
lines changed

6 files changed

+98
-47
lines changed

Doc/library/ssl.rst

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -681,19 +681,23 @@ Constants
681681

682682
.. deprecated:: 3.10
683683

684+
TLS clients and servers require different default settings for secure
685+
communication. The generic TLS protocol constant is deprecated in
686+
favor of :data:`PROTOCOL_TLS_CLIENT` and :data:`PROTOCOL_TLS_SERVER`.
687+
684688
.. data:: PROTOCOL_TLS_CLIENT
685689

686-
Auto-negotiate the highest protocol version like :data:`PROTOCOL_TLS`,
687-
but only support client-side :class:`SSLSocket` connections. The protocol
688-
enables :data:`CERT_REQUIRED` and :attr:`~SSLContext.check_hostname` by
689-
default.
690+
Auto-negotiate the highest protocol version that both the client and
691+
server support, and configure the context client-side connections. The
692+
protocol enables :data:`CERT_REQUIRED` and
693+
:attr:`~SSLContext.check_hostname` by default.
690694

691695
.. versionadded:: 3.6
692696

693697
.. data:: PROTOCOL_TLS_SERVER
694698

695-
Auto-negotiate the highest protocol version like :data:`PROTOCOL_TLS`,
696-
but only support server-side :class:`SSLSocket` connections.
699+
Auto-negotiate the highest protocol version that both the client and
700+
server support, and configure the context server-side connections.
697701

698702
.. versionadded:: 3.6
699703

Doc/whatsnew/3.10.rst

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,18 +1214,11 @@ The ssl module has preliminary support for OpenSSL 3.0.0 and new option
12141214
:issue:`43789`, and :issue:`43811`.)
12151215
12161216
Deprecated function and use of deprecated constants now result in
1217< 67F4 code>-
a :exc:`DeprecationWarning`. The following features have been deprecated
1218-
since Python 3.6, Python 3.7, or OpenSSL 1.1.0:
1219-
:data:`~ssl.OP_NO_SSLv2`, :data:`~ssl.OP_NO_SSLv3`, :data:`~ssl.OP_NO_TLSv1`,
1220-
:data:`~ssl.OP_NO_TLSv1_1`, :data:`~ssl.OP_NO_TLSv1_2`,
1221-
:data:`~ssl.OP_NO_TLSv1_3`, :data:`~ssl.PROTOCOL_SSLv2`,
1222-
:data:`~ssl.PROTOCOL_SSLv3`, :data:`~ssl.PROTOCOL_SSLv23`,
1223-
:data:`~ssl.PROTOCOL_TLSv1`, :data:`~ssl.PROTOCOL_TLSv1_1`,
1224-
:data:`~ssl.PROTOCOL_TLSv1_2`, :data:`~ssl.PROTOCOL_TLS`,
1225-
:func:`~ssl.wrap_socket`, :func:`~ssl.match_hostname`,
1226-
:func:`~ssl.RAND_pseudo_bytes`, :func:`~ssl.RAND_egd`,
1227-
:meth:`ssl.SSLSocket.selected_npn_protocol`,
1228-
:meth:`ssl.SSLContext.set_npn_protocols`.
1217+
a :exc:`DeprecationWarning`. :attr:`ssl.SSLContext.options` has
1218+
:data:`~ssl.OP_NO_SSLv2` and :data:`~ssl.OP_NO_SSLv3` set by default and
1219+
therefore cannot warn about setting the flag again. The
1220+
:ref:`deprecation section <whatsnew310-deprecated>` has a list of deprecated
1221+
features.
12291222
(Contributed by Christian Heimes in :issue:`43880`.)
12301223
12311224
The ssl module now has more secure default settings. Ciphers without forward
@@ -1441,6 +1434,8 @@ Optimizations
14411434
readers or writers, just like its equivalent classes in :mod:`gzip` and
14421435
:mod:`lzma` have always been. (Contributed by Inada Naoki in :issue:`43785`).
14431436
1437+
.. _whatsnew310-deprecated:
1438+
14441439
Deprecated
14451440
==========
14461441
@@ -1609,6 +1604,30 @@ Deprecated
16091604
* ``cgi.log()`` is deprecated and slated for removal in Python 3.12.
16101605
(Contributed by Inada Naoki in :issue:`41139`.)
16111606
1607+
* The following :mod:`ssl` features have been deprecated since Python 3.6,
1608+
Python 3.7, or OpenSSL 1.1.0 and will be removed in 3.11:
1609+
1610+
* :data:`~ssl.OP_NO_SSLv2`, :data:`~ssl.OP_NO_SSLv3`, :data:`~ssl.OP_NO_TLSv1`,
1611+
:data:`~ssl.OP_NO_TLSv1_1`, :data:`~ssl.OP_NO_TLSv1_2`, and
1612+
:data:`~ssl.OP_NO_TLSv1_3` are replaced by
1613+
:attr:`sslSSLContext.minimum_version` and
1614+
:attr:`sslSSLContext.maximum_version`.
1615+
1616+
* :data:`~ssl.PROTOCOL_SSLv2`, :data:`~ssl.PROTOCOL_SSLv3`,
1617+
:data:`~ssl.PROTOCOL_SSLv23`, :data:`~ssl.PROTOCOL_TLSv1`,
1618+
:data:`~ssl.PROTOCOL_TLSv1_1`, :data:`~ssl.PROTOCOL_TLSv1_2`, and
1619+
:data:`~ssl.PROTOCOL_TLS` are deprecated in favor of
1620+
:data:`~ssl.PROTOCOL_TLS_CLIENT` and :data:`~ssl.PROTOCOL_TLS_SERVER`
1621+
1622+
* :func:`~ssl.wrap_socket` is replaced by :meth:`ssl.SSLContext.wrap_socket`
1623+
1624+
* :func:`~ssl.match_hostname`
1625+
1626+
* :func:`~ssl.RAND_pseudo_bytes`, :func:`~ssl.RAND_egd`
1627+
1628+
* NPN features like :meth:`ssl.SSLSocket.selected_npn_protocol` and
1629+
:meth:`ssl.SSLContext.set_npn_protocols` are replaced by ALPN.
1630+
16121631
.. _whatsnew310-removed:
16131632
16141633
Removed

Lib/ssl.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@
9494
import os
9595
from collections import namedtuple
9696
from enum import Enum as _Enum, IntEnum as _IntEnum, IntFlag as _IntFlag
97-
from enum import _simple_enum, _test_simple_enum
97+
from enum import _simple_enum
9898

9999
import _ssl # if we can't import it, let the error propagate
100100

@@ -387,7 +387,7 @@ def match_hostname(cert, hostname):
387387
returns nothing.
388388
"""
389389
warnings.warn(
390-
"ssl module: match_hostname() is deprecated",
390+
"ssl.match_hostname() is deprecated",
391391
category=DeprecationWarning,
392392
stacklevel=2
393393
)
@@ -492,8 +492,7 @@ class SSLContext(_SSLContext):
492492
def __new__(cls, protocol=None, *args, **kwargs):
493493
if protocol is None:
494494
warnings.warn(
495-
"ssl module: "
496-
"SSLContext() without protocol argument is deprecated.",
495+
"ssl.SSLContext() without protocol argument is deprecated.",
497496
category=DeprecationWarning,
498497
stacklevel=2
499498
)
@@ -536,7 +535,11 @@ def wrap_bio(self, incoming, outgoing, server_side=False,
536535
)
537536

538537
def set_npn_protocols(self, npn_protocols):
539-
warnings.warn("NPN is deprecated, use ALPN instead", stacklevel=2)
538+
warnings.warn(
539+
"ssl NPN is deprecated, use ALPN instead",
540+
DeprecationWarning,
541+
stacklevel=2
542+
)
540543
protos = bytearray()
541544
for protocol in npn_protocols:
542545
b = bytes(protocol, 'ascii')
@@ -940,7 +943,9 @@ def selected_npn_protocol(self):
940943
if a next protocol was not negotiated or if NPN is not supported by one
941944
of the peers."""
942945
warnings.warn(
943-
"ssl module: NPN is deprecated, use ALPN instead", stacklevel=2
946+
"ssl NPN is deprecated, use ALPN instead",
947+
DeprecationWarning,
948+
stacklevel=2
944949
)
945950

946951
def selected_alpn_protocol(self):
@@ -1157,7 +1162,9 @@ def getpeercert(self, binary_form=False):
11571162
def selected_npn_protocol(self):
11581163
self._checkClosed()
11591164
warnings.warn(
1160-
"ssl module: NPN is deprecated, use ALPN instead", stacklevel=2
1165+
"ssl NPN is deprecated, use ALPN instead",
1166+
DeprecationWarning,
1167+
stacklevel=2
11611168
)
11621169
return None
11631170

@@ -1419,7 +1426,7 @@ def wrap_socket(sock, keyfile=None, certfile=None,
14191426
suppress_ragged_eofs=True,
14201427
ciphers=None):
14211428
warnings.warn(
1422-
"ssl module: wrap_socket is deprecated, use SSLContext.wrap_socket()",
1429+
"ssl.wrap_socket() is deprecated, use SSLContext.wrap_socket()",
14231430
category=DeprecationWarning,
14241431
stacklevel=2
14251432
)

Lib/test/test_ssl.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,7 +1750,7 @@ class MySSLObject(ssl.SSLObject):
17501750

17511751
with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
17521752
self.assertIsInstance(sock, MySSLSocket)
1753-
obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
1753+
obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(), server_side=True)
17541754
self.assertIsInstance(obj, MySSLObject)
17551755

17561756
def test_num_tickest(self):
@@ -2884,24 +2884,29 @@ def test_echo(self):
28842884
server_context=client_context,
28852885
chatty=True, connectionchatty=True,
28862886
sni_name=hostname)
2887-
self.assertIn('called a function you should not call',
2888-
str(e.exception))
2887+
self.assertIn(
2888+
'Cannot create a client socket with a PROTOCOL_TLS_SERVER context',
2889+
str(e.exception)
2890+
)
28892891

28902892
with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
28912893
with self.assertRaises(ssl.SSLError) as e:
28922894
server_params_test(client_context=server_context,
28932895
server_context=server_context,
28942896
chatty=True, connectionchatty=True)
2895-
self.assertIn('called a function you should not call',
2896-
str(e.exception))
2897+
self.assertIn(
2898+
'Cannot create a client socket with a PROTOCOL_TLS_SERVER context',
2899+
str(e.exception)
2900+
)
28972901

28982902
with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
28992903
with self.assertRaises(ssl.SSLError) as e:
29002904
server_params_test(client_context=server_context,
29012905
server_context=client_context,
29022906
chatty=True, connectionchatty=True)
2903-
self.assertIn('called a function you should not call',
2904-
str(e.exception))
2907+
self.assertIn(
2908+
'Cannot create a client socket with a PROTOCOL_TLS_SERVER context',
2909+
str(e.exception))
29052910

29062911
def test_getpeercert(self):
29072912
if support.verbose:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Improve :mod:`ssl` module's deprecation messages, error reporting, and
2+
documentation for deprecations.

Modules/_ssl.c

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -697,10 +697,9 @@ _setSSLError (_sslmodulestate *state, const char *errstr, int errcode, const cha
697697
}
698698

699699
static int
700-
_ssl_deprecated(const char* name, int stacklevel) {
701-
return PyErr_WarnFormat(
702-
PyExc_DeprecationWarning, stacklevel,
703-
"ssl module: %s is deprecated", name
700+
_ssl_deprecated(const char* msg, int stacklevel) {
701+
return PyErr_WarnEx(
702+
PyExc_DeprecationWarning, msg, stacklevel
704703
);
705704
}
706705

@@ -788,6 +787,21 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
788787
SSL_CTX *ctx = sslctx->ctx;
789788
_PySSLError err = { 0 };
790789

790+
if ((socket_type == PY_SSL_SERVER) &&
791+
(sslctx->protocol == PY_SSL_VERSION_TLS_CLIENT)) {
792+
_setSSLError(get_state_ctx(sslctx),
793+
"Cannot create a server socket with a "
794+
"PROTOCOL_TLS_CLIENT context", 0, __FILE__, __LINE__);
795+
return NULL;
796+
}
797+
if ((socket_type == PY_SSL_CLIENT) &&
798+
(sslctx->protocol == PY_SSL_VERSION_TLS_SERVER)) {
799+
_setSSLError(get_state_ctx(sslctx),
800+
"Cannot create a client socket with a "
801+
"PROTOCOL_TLS_SERVER context", 0, __FILE__, __LINE__);
802+
return NULL;
803+
}
804+
791805
self = PyObject_GC_New(PySSLSocket,
792806
get_state_ctx(sslctx)->PySSLSocket_Type);
793807
if (self == NULL)
@@ -2980,36 +2994,36 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
29802994
switch(proto_version) {
29812995
#if defined(SSL3_VERSION) && !defined(OPENSSL_NO_SSL3)
29822996
case PY_SSL_VERSION_SSL3:
2983-
PY_SSL_DEPRECATED("PROTOCOL_SSLv3", 2, NULL);
2997+
PY_SSL_DEPRECATED("ssl.PROTOCOL_SSLv3 is deprecated", 2, NULL);
29842998
method = SSLv3_method();
29852999
break;
29863000
#endif
29873001
#if (defined(TLS1_VERSION) && \
29883002
!defined(OPENSSL_NO_TLS1) && \
29893003
!defined(OPENSSL_NO_TLS1_METHOD))
29903004
case PY_SSL_VERSION_TLS1:
2991-
PY_SSL_DEPRECATED("PROTOCOL_TLSv1", 2, NULL);
3005+
PY_SSL_DEPRECATED("ssl.PROTOCOL_TLSv1 is deprecated", 2, NULL);
29923006
method = TLSv1_method();
29933007
break;
29943008
#endif
29953009
#if (defined(TLS1_1_VERSION) && \
29963010
!defined(OPENSSL_NO_TLS1_1) && \
29973011
!defined(OPENSSL_NO_TLS1_1_METHOD))
29983012
case PY_SSL_VERSION_TLS1_1:
2999-
PY_SSL_DEPRECATED("PROTOCOL_TLSv1_1", 2, NULL);
3013+
PY_SSL_DEPRECATED("ssl.PROTOCOL_TLSv1_1 is deprecated", 2, NULL);
30003014
method = TLSv1_1_method();
30013015
break;
30023016
#endif
30033017
#if (defined(TLS1_2_VERSION) && \
30043018
!defined(OPENSSL_NO_TLS1_2) && \
30053019
!defined(OPENSSL_NO_TLS1_2_METHOD))
30063020
case PY_SSL_VERSION_TLS1_2:
3007-
PY_SSL_DEPRECATED("PROTOCOL_TLSv1_2", 2, NULL);
3021+
PY_SSL_DEPRECATED("ssl.PROTOCOL_TLSv1_2 is deprecated", 2, NULL);
30083022
method = TLSv1_2_method();
30093023
break;
30103024
#endif
30113025
case PY_SSL_VERSION_TLS:
3012-
PY_SSL_DEPRECATED("PROTOCOL_TLS", 2, NULL);
3026+
PY_SSL_DEPRECATED("ssl.PROTOCOL_TLS is deprecated", 2, NULL);
30133027
method = TLS_method();
30143028
break;
30153029
case PY_SSL_VERSION_TLS_CLIENT:
@@ -3433,13 +3447,13 @@ set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what)
34333447
/* check for deprecations and supported values */
34343448
switch(v) {
34353449
case PY_PROTO_SSLv3:
3436-
PY_SSL_DEPRECATED("TLSVersion.SSLv3", 2, -1);
3450+
PY_SSL_DEPRECATED("ssl.TLSVersion.SSLv3 is deprecated", 2, -1);
34373451
break;
34383452
case PY_PROTO_TLSv1:
3439-
PY_SSL_DEPRECATED("TLSVersion.TLSv1", 2, -1);
3453+
PY_SSL_DEPRECATED("ssl.TLSVersion.TLSv1 is deprecated", 2, -1);
34403454
break;
34413455
case PY_PROTO_TLSv1_1:
3442-
PY_SSL_DEPRECATED("TLSVersion.TLSv1_1", 2, -1);
3456+
PY_SSL_DEPRECATED("ssl.TLSVersion.TLSv1_1 is deprecated", 2, -1);
34433457
break;
34443458
case PY_PROTO_MINIMUM_SUPPORTED:
34453459
case PY_PROTO_MAXIMUM_SUPPORTED:
@@ -3583,7 +3597,7 @@ set_options(PySSLContext *self, PyObject *arg, void *c)
35833597
set = ~opts & new_opts;
35843598

35853599
if ((set & opt_no) != 0) {
3586-
if (_ssl_deprecated("Setting OP_NO_SSL* or SSL_NO_TLS* options is "
3600+
if (_ssl_deprecated("ssl.OP_NO_SSL*/ssl.SSL_NO_TLS* options are "
35873601
"deprecated", 2) < 0) {
35883602
return -1;
35893603
}
@@ -5146,7 +5160,7 @@ static PyObject *
51465160
_ssl_RAND_pseudo_bytes_impl(PyObject *module, int n)
51475161
/*[clinic end generated code: output=b1509e937000e52d input=58312bd53f9bbdd0]*/
51485162
{
5149-
PY_SSL_DEPRECATED("RAND_pseudo_bytes", 1, NULL);
5163+
PY_SSL_DEPRECATED("ssl.RAND_pseudo_bytes() is deprecated", 1, NULL);
51505164
return PySSL_RAND(module, n, 1);
51515165
}
51525166

0 commit comments

Comments
 (0)
0