[Python-checkins] bpo-44362: ssl: improve deprecation warnings and docs (GH-26646)
miss-islington
webhook-mailer at python.org
Fri Jun 11 03:36:27 EDT 2021
https://github.com/python/cpython/commit/d7930fb720b5e9db2076b116dffcd52b6ca71438
commit: d7930fb720b5e9db2076b116dffcd52b6ca71438
branch: 3.10
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: miss-islington <31488909+miss-islington at users.noreply.github.com>
date: 2021-06-11T00:36:17-07:00
summary:
bpo-44362: ssl: improve deprecation warnings and docs (GH-26646)
Signed-off-by: Christian Heimes <christian at python.org>
(cherry picked from commit e26014f1c47d26d6097ff7a0f25384bfbde714a9)
Co-authored-by: Christian Heimes <christian at python.org>
files:
A Misc/NEWS.d/next/Library/2021-06-10-20-07-32.bpo-44362.oVOMfd.rst
M Doc/library/ssl.rst
M Doc/whatsnew/3.10.rst
M Lib/ssl.py
M Lib/test/test_ssl.py
M Modules/_ssl.c
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
index afa3d87f5767a..4902d34888ebc 100644
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -681,19 +681,23 @@ Constants
.. deprecated:: 3.10
+ TLS clients and servers require different default settings for secure
+ communication. The generic TLS protocol constant is deprecated in
+ favor of :data:`PROTOCOL_TLS_CLIENT` and :data:`PROTOCOL_TLS_SERVER`.
+
.. data:: PROTOCOL_TLS_CLIENT
- Auto-negotiate the highest protocol version like :data:`PROTOCOL_TLS`,
- but only support client-side :class:`SSLSocket` connections. The protocol
- enables :data:`CERT_REQUIRED` and :attr:`~SSLContext.check_hostname` by
- default.
+ Auto-negotiate the highest protocol version that both the client and
+ server support, and configure the context client-side connections. The
+ protocol enables :data:`CERT_REQUIRED` and
+ :attr:`~SSLContext.check_hostname` by default.
.. versionadded:: 3.6
.. data:: PROTOCOL_TLS_SERVER
- Auto-negotiate the highest protocol version like :data:`PROTOCOL_TLS`,
- but only support server-side :class:`SSLSocket` connections.
+ Auto-negotiate the highest protocol version that both the client and
+ server support, and configure the context server-side connections.
.. versionadded:: 3.6
diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst
index 5e29f932ba1ff..530ffce59b15b 100644
--- a/Doc/whatsnew/3.10.rst
+++ b/Doc/whatsnew/3.10.rst
@@ -1214,18 +1214,11 @@ The ssl module has preliminary support for OpenSSL 3.0.0 and new option
:issue:`43789`, and :issue:`43811`.)
Deprecated function and use of deprecated constants now result in
-a :exc:`DeprecationWarning`. The following features have been deprecated
-since Python 3.6, Python 3.7, or OpenSSL 1.1.0:
-:data:`~ssl.OP_NO_SSLv2`, :data:`~ssl.OP_NO_SSLv3`, :data:`~ssl.OP_NO_TLSv1`,
-:data:`~ssl.OP_NO_TLSv1_1`, :data:`~ssl.OP_NO_TLSv1_2`,
-:data:`~ssl.OP_NO_TLSv1_3`, :data:`~ssl.PROTOCOL_SSLv2`,
-:data:`~ssl.PROTOCOL_SSLv3`, :data:`~ssl.PROTOCOL_SSLv23`,
-:data:`~ssl.PROTOCOL_TLSv1`, :data:`~ssl.PROTOCOL_TLSv1_1`,
-:data:`~ssl.PROTOCOL_TLSv1_2`, :data:`~ssl.PROTOCOL_TLS`,
-:func:`~ssl.wrap_socket`, :func:`~ssl.match_hostname`,
-:func:`~ssl.RAND_pseudo_bytes`, :func:`~ssl.RAND_egd`,
-:meth:`ssl.SSLSocket.selected_npn_protocol`,
-:meth:`ssl.SSLContext.set_npn_protocols`.
+a :exc:`DeprecationWarning`. :attr:`ssl.SSLContext.options` has
+:data:`~ssl.OP_NO_SSLv2` and :data:`~ssl.OP_NO_SSLv3` set by default and
+therefore cannot warn about setting the flag again. The
+:ref:`deprecation section <whatsnew310-deprecated>` has a list of deprecated
+features.
(Contributed by Christian Heimes in :issue:`43880`.)
The ssl module now has more secure default settings. Ciphers without forward
@@ -1448,6 +1441,8 @@ Optimizations
readers or writers, just like its equivalent classes in :mod:`gzip` and
:mod:`lzma` have always been. (Contributed by Inada Naoki in :issue:`43785`).
+.. _whatsnew310-deprecated:
+
Deprecated
==========
@@ -1616,6 +1611,30 @@ Deprecated
* ``cgi.log()`` is deprecated and slated for removal in Python 3.12.
(Contributed by Inada Naoki in :issue:`41139`.)
+* The following :mod:`ssl` features have been deprecated since Python 3.6,
+ Python 3.7, or OpenSSL 1.1.0 and will be removed in 3.11:
+
+ * :data:`~ssl.OP_NO_SSLv2`, :data:`~ssl.OP_NO_SSLv3`, :data:`~ssl.OP_NO_TLSv1`,
+ :data:`~ssl.OP_NO_TLSv1_1`, :data:`~ssl.OP_NO_TLSv1_2`, and
+ :data:`~ssl.OP_NO_TLSv1_3` are replaced by
+ :attr:`sslSSLContext.minimum_version` and
+ :attr:`sslSSLContext.maximum_version`.
+
+ * :data:`~ssl.PROTOCOL_SSLv2`, :data:`~ssl.PROTOCOL_SSLv3`,
+ :data:`~ssl.PROTOCOL_SSLv23`, :data:`~ssl.PROTOCOL_TLSv1`,
+ :data:`~ssl.PROTOCOL_TLSv1_1`, :data:`~ssl.PROTOCOL_TLSv1_2`, and
+ :data:`~ssl.PROTOCOL_TLS` are deprecated in favor of
+ :data:`~ssl.PROTOCOL_TLS_CLIENT` and :data:`~ssl.PROTOCOL_TLS_SERVER`
+
+ * :func:`~ssl.wrap_socket` is replaced by :meth:`ssl.SSLContext.wrap_socket`
+
+ * :func:`~ssl.match_hostname`
+
+ * :func:`~ssl.RAND_pseudo_bytes`, :func:`~ssl.RAND_egd`
+
+ * NPN features like :meth:`ssl.SSLSocket.selected_npn_protocol` and
+ :meth:`ssl.SSLContext.set_npn_protocols` are replaced by ALPN.
+
.. _whatsnew310-removed:
Removed
diff --git a/Lib/ssl.py b/Lib/ssl.py
index 2b131de04306a..a16ebd74a1b16 100644
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -94,7 +94,7 @@
import os
from collections import namedtuple
from enum import Enum as _Enum, IntEnum as _IntEnum, IntFlag as _IntFlag
-from enum import _simple_enum, _test_simple_enum
+from enum import _simple_enum
import _ssl # if we can't import it, let the error propagate
@@ -387,7 +387,7 @@ def match_hostname(cert, hostname):
returns nothing.
"""
warnings.warn(
- "ssl module: match_hostname() is deprecated",
+ "ssl.match_hostname() is deprecated",
category=DeprecationWarning,
stacklevel=2
)
@@ -492,8 +492,7 @@ class SSLContext(_SSLContext):
def __new__(cls, protocol=None, *args, **kwargs):
if protocol is None:
warnings.warn(
- "ssl module: "
- "SSLContext() without protocol argument is deprecated.",
+ "ssl.SSLContext() without protocol argument is deprecated.",
category=DeprecationWarning,
stacklevel=2
)
@@ -536,7 +535,11 @@ def wrap_bio(self, incoming, outgoing, server_side=False,
)
def set_npn_protocols(self, npn_protocols):
- warnings.warn("NPN is deprecated, use ALPN instead", stacklevel=2)
+ warnings.warn(
+ "ssl NPN is deprecated, use ALPN instead",
+ DeprecationWarning,
+ stacklevel=2
+ )
protos = bytearray()
for protocol in npn_protocols:
b = bytes(protocol, 'ascii')
@@ -940,7 +943,9 @@ def selected_npn_protocol(self):
if a next protocol was not negotiated or if NPN is not supported by one
of the peers."""
warnings.warn(
- "ssl module: NPN is deprecated, use ALPN instead", stacklevel=2
+ "ssl NPN is deprecated, use ALPN instead",
+ DeprecationWarning,
+ stacklevel=2
)
def selected_alpn_protocol(self):
@@ -1157,7 +1162,9 @@ def getpeercert(self, binary_form=False):
def selected_npn_protocol(self):
self._checkClosed()
warnings.warn(
- "ssl module: NPN is deprecated, use ALPN instead", stacklevel=2
+ "ssl NPN is deprecated, use ALPN instead",
+ DeprecationWarning,
+ stacklevel=2
)
return None
@@ -1419,7 +1426,7 @@ def wrap_socket(sock, keyfile=None, certfile=None,
suppress_ragged_eofs=True,
ciphers=None):
warnings.warn(
- "ssl module: wrap_socket is deprecated, use SSLContext.wrap_socket()",
+ "ssl.wrap_socket() is deprecated, use SSLContext.wrap_socket()",
category=DeprecationWarning,
stacklevel=2
)
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index 9bd8e2264c152..5dc27df04dc1d 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -1754,7 +1754,7 @@ class MySSLObject(ssl.SSLObject):
with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
self.assertIsInstance(sock, MySSLSocket)
- obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
+ obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(), server_side=True)
self.assertIsInstance(obj, MySSLObject)
def test_num_tickest(self):
@@ -2888,24 +2888,29 @@ def test_echo(self):
server_context=client_context,
chatty=True, connectionchatty=True,
sni_name=hostname)
- self.assertIn('called a function you should not call',
- str(e.exception))
+ self.assertIn(
+ 'Cannot create a client socket with a PROTOCOL_TLS_SERVER context',
+ str(e.exception)
+ )
with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
with self.assertRaises(ssl.SSLError) as e:
server_params_test(client_context=server_context,
server_context=server_context,
chatty=True, connectionchatty=True)
- self.assertIn('called a function you should not call',
- str(e.exception))
+ self.assertIn(
+ 'Cannot create a client socket with a PROTOCOL_TLS_SERVER context',
+ str(e.exception)
+ )
with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
with self.assertRaises(ssl.SSLError) as e:
server_params_test(client_context=server_context,
server_context=client_context,
chatty=True, connectionchatty=True)
- self.assertIn('called a function you should not call',
- str(e.exception))
+ self.assertIn(
+ 'Cannot create a client socket with a PROTOCOL_TLS_SERVER context',
+ str(e.exception))
def test_getpeercert(self):
if support.verbose:
diff --git a/Misc/NEWS.d/next/Library/2021-06-10-20-07-32.bpo-44362.oVOMfd.rst b/Misc/NEWS.d/next/Library/2021-06-10-20-07-32.bpo-44362.oVOMfd.rst
new file mode 100644
index 0000000000000..0e6aef3c90e6f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2021-06-10-20-07-32.bpo-44362.oVOMfd.rst
@@ -0,0 +1,2 @@
+Improve :mod:`ssl` module's deprecation messages, error reporting, and
+documentation for deprecations.
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index 73544bb12d1d8..8daf04dd08bbb 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -697,10 +697,9 @@ _setSSLError (_sslmodulestate *state, const char *errstr, int errcode, const cha
}
static int
-_ssl_deprecated(const char* name, int stacklevel) {
- return PyErr_WarnFormat(
- PyExc_DeprecationWarning, stacklevel,
- "ssl module: %s is deprecated", name
+_ssl_deprecated(const char* msg, int stacklevel) {
+ return PyErr_WarnEx(
+ PyExc_DeprecationWarning, msg, stacklevel
);
}
@@ -788,6 +787,21 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
SSL_CTX *ctx = sslctx->ctx;
_PySSLError err = { 0 };
+ if ((socket_type == PY_SSL_SERVER) &&
+ (sslctx->protocol == PY_SSL_VERSION_TLS_CLIENT)) {
+ _setSSLError(get_state_ctx(sslctx),
+ "Cannot create a server socket with a "
+ "PROTOCOL_TLS_CLIENT context", 0, __FILE__, __LINE__);
+ return NULL;
+ }
+ if ((socket_type == PY_SSL_CLIENT) &&
+ (sslctx->protocol == PY_SSL_VERSION_TLS_SERVER)) {
+ _setSSLError(get_state_ctx(sslctx),
+ "Cannot create a client socket with a "
+ "PROTOCOL_TLS_SERVER context", 0, __FILE__, __LINE__);
+ return NULL;
+ }
+
self = PyObject_GC_New(PySSLSocket,
get_state_ctx(sslctx)->PySSLSocket_Type);
if (self == NULL)
@@ -2980,7 +2994,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
switch(proto_version) {
#if defined(SSL3_VERSION) && !defined(OPENSSL_NO_SSL3)
case PY_SSL_VERSION_SSL3:
- PY_SSL_DEPRECATED("PROTOCOL_SSLv3", 2, NULL);
+ PY_SSL_DEPRECATED("ssl.PROTOCOL_SSLv3 is deprecated", 2, NULL);
method = SSLv3_method();
break;
#endif
@@ -2988,7 +3002,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
!defined(OPENSSL_NO_TLS1) && \
!defined(OPENSSL_NO_TLS1_METHOD))
case PY_SSL_VERSION_TLS1:
- PY_SSL_DEPRECATED("PROTOCOL_TLSv1", 2, NULL);
+ PY_SSL_DEPRECATED("ssl.PROTOCOL_TLSv1 is deprecated", 2, NULL);
method = TLSv1_method();
break;
#endif
@@ -2996,7 +3010,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
!defined(OPENSSL_NO_TLS1_1) && \
!defined(OPENSSL_NO_TLS1_1_METHOD))
case PY_SSL_VERSION_TLS1_1:
- PY_SSL_DEPRECATED("PROTOCOL_TLSv1_1", 2, NULL);
+ PY_SSL_DEPRECATED("ssl.PROTOCOL_TLSv1_1 is deprecated", 2, NULL);
method = TLSv1_1_method();
break;
#endif
@@ -3004,12 +3018,12 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
!defined(OPENSSL_NO_TLS1_2) && \
!defined(OPENSSL_NO_TLS1_2_METHOD))
case PY_SSL_VERSION_TLS1_2:
- PY_SSL_DEPRECATED("PROTOCOL_TLSv1_2", 2, NULL);
+ PY_SSL_DEPRECATED("ssl.PROTOCOL_TLSv1_2 is deprecated", 2, NULL);
method = TLSv1_2_method();
break;
#endif
case PY_SSL_VERSION_TLS:
- PY_SSL_DEPRECATED("PROTOCOL_TLS", 2, NULL);
+ PY_SSL_DEPRECATED("ssl.PROTOCOL_TLS is deprecated", 2, NULL);
method = TLS_method();
break;
case PY_SSL_VERSION_TLS_CLIENT:
@@ -3433,13 +3447,13 @@ set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what)
/* check for deprecations and supported values */
switch(v) {
case PY_PROTO_SSLv3:
- PY_SSL_DEPRECATED("TLSVersion.SSLv3", 2, -1);
+ PY_SSL_DEPRECATED("ssl.TLSVersion.SSLv3 is deprecated", 2, -1);
break;
case PY_PROTO_TLSv1:
- PY_SSL_DEPRECATED("TLSVersion.TLSv1", 2, -1);
+ PY_SSL_DEPRECATED("ssl.TLSVersion.TLSv1 is deprecated", 2, -1);
break;
case PY_PROTO_TLSv1_1:
- PY_SSL_DEPRECATED("TLSVersion.TLSv1_1", 2, -1);
+ PY_SSL_DEPRECATED("ssl.TLSVersion.TLSv1_1 is deprecated", 2, -1);
break;
case PY_PROTO_MINIMUM_SUPPORTED:
case PY_PROTO_MAXIMUM_SUPPORTED:
@@ -3583,7 +3597,7 @@ set_options(PySSLContext *self, PyObject *arg, void *c)
set = ~opts & new_opts;
if ((set & opt_no) != 0) {
- if (_ssl_deprecated("Setting OP_NO_SSL* or SSL_NO_TLS* options is "
+ if (_ssl_deprecated("ssl.OP_NO_SSL*/ssl.SSL_NO_TLS* options are "
"deprecated", 2) < 0) {
return -1;
}
@@ -5146,7 +5160,7 @@ static PyObject *
_ssl_RAND_pseudo_bytes_impl(PyObject *module, int n)
/*[clinic end generated code: output=b1509e937000e52d input=58312bd53f9bbdd0]*/
{
- PY_SSL_DEPRECATED("RAND_pseudo_bytes", 1, NULL);
+ PY_SSL_DEPRECATED("ssl.RAND_pseudo_bytes() is deprecated", 1, NULL);
return PySSL_RAND(module, n, 1);
}
More information about the Python-checkins
mailing list