Commit d0486377 authored by Christian Heimes's avatar Christian Heimes

Issue #28022: Deprecate ssl-related arguments in favor of SSLContext.

The deprecation include manual creation of SSLSocket and certfile/keyfile
(or similar) in ftplib, httplib, imaplib, smtplib, poplib and urllib.

ssl.wrap_socket() is not marked as deprecated yet.
parent 130bbe5f
......@@ -97,6 +97,13 @@ The module defines the following items:
:attr:`ssl.SSLContext.check_hostname` and *Server Name Indication* (see
:data:`ssl.HAS_SNI`).
.. deprecated:: 3.6
*keyfile* and *certfile* are deprecated in favor of *context*.
Please use :meth:`ssl.SSLContext.load_cert_chain` instead, or let
:func:`ssl.create_default_context` select the system's trusted CA
certificates for you.
Here's a sample session using the :class:`FTP_TLS` class::
>>> ftps = FTP_TLS('ftp.pureftpd.org')
......
......@@ -69,13 +69,6 @@ The module provides the following classes:
must be a :class:`ssl.SSLContext` instance describing the various SSL
options.
*key_file* and *cert_file* are deprecated, please use
:meth:`ssl.SSLContext.load_cert_chain` instead, or let
:func:`ssl.create_default_context` select the system's trusted CA
certificates for you. The *check_hostname* parameter is also deprecated; the
:attr:`ssl.SSLContext.check_hostname` attribute of *context* should be used
instead.
Please read :ref:`ssl-security` for more information on best practices.
.. versionchanged:: 3.2
......@@ -95,6 +88,17 @@ The module provides the following classes:
:func:`ssl._create_unverified_context` can be passed to the *context*
parameter.
.. deprecated:: 3.6
*key_file* and *cert_file* are deprecated in favor of *context*.
Please use :meth:`ssl.SSLContext.load_cert_chain` instead, or let
:func:`ssl.create_default_context` select the system's trusted CA
certificates for you.
The *check_hostname* parameter is also deprecated; the
:attr:`ssl.SSLContext.check_hostname` attribute of *context* should
be used instead.
.. class:: HTTPResponse(sock, debuglevel=0, method=None, url=None)
......
......@@ -103,6 +103,14 @@ There's also a subclass for secure connections:
:attr:`ssl.SSLContext.check_hostname` and *Server Name Indication* (see
:data:`ssl.HAS_SNI`).
.. deprecated:: 3.6
*keyfile* and *certfile* are deprecated in favor of *ssl_context*.
Please use :meth:`ssl.SSLContext.load_cert_chain` instead, or let
:func:`ssl.create_default_context` select the system's trusted CA
certificates for you.
The second subclass allows for connections created by a child process:
......
......@@ -62,6 +62,13 @@ The :mod:`poplib` module provides two classes:
:attr:`ssl.SSLContext.check_hostname` and *Server Name Indication* (see
:data:`ssl.HAS_SNI`).
.. deprecated:: 3.6
*keyfile* and *certfile* are deprecated in favor of *context*.
Please use :meth:`ssl.SSLContext.load_cert_chain` instead, or let
:func:`ssl.create_default_context` select the system's trusted CA
certificates for you.
One exception is defined as an attribute of the :mod:`poplib` module:
......
......@@ -95,6 +95,14 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions).
:attr:`ssl.SSLContext.check_hostname` and *Server Name Indication* (see
:data:`ssl.HAS_SNI`).
.. deprecated:: 3.6
*keyfile* and *certfile* are deprecated in favor of *context*.
Please use :meth:`ssl.SSLContext.load_cert_chain` instead, or let
:func:`ssl.create_default_context` select the system's trusted CA
certificates for you.
.. class:: LMTP(host='', port=LMTP_PORT, local_hostname=None, source_address=None)
The LMTP protocol, which is very similar to ESMTP, is heavily based on the
......
......@@ -230,7 +230,6 @@ instead.
.. versionchanged:: 3.2
New optional argument *ciphers*.
Context creation
^^^^^^^^^^^^^^^^
......@@ -925,7 +924,7 @@ SSL Sockets
:ref:`notes on non-blocking sockets <ssl-nonblocking>`.
Usually, :class:`SSLSocket` are not created directly, but using the
:func:`wrap_socket` function or the :meth:`SSLContext.wrap_socket` method.
the :meth:`SSLContext.wrap_socket` method.
.. versionchanged:: 3.5
The :meth:`sendfile` method was added.
......@@ -935,6 +934,10 @@ SSL Sockets
are received or sent. The socket timeout is now to maximum total duration
of the shutdown.
.. deprecated:: 3.6
It is deprecated to create a :class:`SSLSocket` instance directly, use
:meth:`SSLContext.wrap_socket` to wrap a socket.
SSL sockets also have the following additional methods and attributes:
......@@ -955,6 +958,9 @@ SSL sockets also have the following additional methods and attributes:
The socket timeout is now to maximum total duration to read up to *len*
bytes.
.. deprecated:: 3.6
Use :meth:`~SSLSocket.recv` instead of :meth:`~SSLSocket.read`.
.. method:: SSLSocket.write(buf)
Write *buf* to the SSL socket and return the number of bytes written. The
......@@ -970,6 +976,9 @@ SSL sockets also have the following additional methods and attributes:
The socket timeout is no more reset each time bytes are received or sent.
The socket timeout is now to maximum total duration to write *buf*.
.. deprecated:: 3.6
Use :meth:`~SSLSocket.send` instead of :meth:`~SSLSocket.write`.
.. note::
The :meth:`~SSLSocket.read` and :meth:`~SSLSocket.write` methods are the
......
......@@ -111,6 +111,12 @@ The :mod:`urllib.request` module defines the following functions:
.. versionchanged:: 3.4.3
*context* was added.
.. deprecated:: 3.6
*cafile*, *capath* and *cadefault* are deprecated in favor of *context*.
Please use :meth:`ssl.SSLContext.load_cert_chain` instead, or let
:func:`ssl.create_default_context` select the system's trusted CA
certificates for you.
.. function:: install_opener(opener)
......
......@@ -117,10 +117,10 @@ class SSLWSGIServerMixin:
'test', 'test_asyncio')
keyfile = os.path.join(here, 'ssl_key.pem')
certfile = os.path.join(here, 'ssl_cert.pem')
ssock = ssl.wrap_socket(request,
keyfile=keyfile,
certfile=certfile,
server_side=True)
context = ssl.SSLContext()
context.load_cert_chain(certfile, keyfile)
ssock = context.wrap_socket(request, server_side=True)
try:
self.RequestHandlerClass(ssock, client_address, self)
ssock.close()
......
......@@ -728,6 +728,10 @@ else:
if context is not None and certfile is not None:
raise ValueError("context and certfile arguments are mutually "
"exclusive")
if keyfile is not None or certfile is not None:
import warnings
warnings.warn("keyfile and certfile are deprecated, use a"
"custom context instead", DeprecationWarning, 2)
self.keyfile = keyfile
self.certfile = certfile
if context is None:
......
......@@ -1365,6 +1365,12 @@ else:
check_hostname=None):
super(HTTPSConnection, self).__init__(host, port, timeout,
source_address)
if (key_file is not None or cert_file is not None or
check_hostname is not None):
import warnings
warnings.warn("key_file, cert_file and check_hostname are "
"deprecated, use a custom context instead.",
DeprecationWarning, 2)
self.key_file = key_file
self.cert_file = cert_file
if context is None:
......
......@@ -1267,7 +1267,10 @@ if HAVE_SSL:
if ssl_context is not None and certfile is not None:
raise ValueError("ssl_context and certfile arguments are mutually "
"exclusive")
if keyfile is not None or certfile is not None:
import warnings
warnings.warn("keyfile and certfile are deprecated, use a"
"custom ssl_context instead", DeprecationWarning, 2)
self.keyfile = keyfile
self.certfile = certfile
if ssl_context is None:
......
......@@ -431,6 +431,10 @@ if HAVE_SSL:
if context is not None and certfile is not None:
raise ValueError("context and certfile arguments are mutually "
"exclusive")
if keyfile is not None or certfile is not None:
import warnings
warnings.warn("keyfile and certfile are deprecated, use a"
"custom context instead", DeprecationWarning, 2)
self.keyfile = keyfile
self.certfile = certfile
if context is None:
......
......@@ -759,6 +759,10 @@ class SMTP:
if context is not None and certfile is not None:
raise ValueError("context and certfile arguments are mutually "
"exclusive")
if keyfile is not None or certfile is not None:
import warnings
warnings.warn("keyfile and certfile are deprecated, use a"
"custom context instead", DeprecationWarning, 2)
if context is None:
context = ssl._create_stdlib_context(certfile=certfile,
keyfile=keyfile)
......@@ -1011,6 +1015,10 @@ if _have_ssl:
if context is not None and certfile is not None:
raise ValueError("context and certfile arguments are mutually "
"exclusive")
if keyfile is not None or certfile is not None:
import warnings
warnings.warn("keyfile and certfile are deprecated, use a"
"custom context instead", DeprecationWarning, 2)
self.keyfile = keyfile
self.certfile = certfile
if context is None:
......
......@@ -1091,7 +1091,6 @@ def wrap_socket(sock, keyfile=None, certfile=None,
do_handshake_on_connect=True,
suppress_ragged_eofs=True,
ciphers=None):
return SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile,
server_side=server_side, cert_reqs=cert_reqs,
ssl_version=ssl_version, ca_certs=ca_certs,
......
......@@ -311,10 +311,12 @@ if ssl is not None:
_ssl_closing = False
def secure_connection(self):
socket = ssl.wrap_socket(self.socket, suppress_ragged_eofs=False,
certfile=CERTFILE, server_side=True,
do_handshake_on_connect=False,
ssl_version=ssl.PROTOCOL_SSLv23)
context = ssl.SSLContext()
context.load_cert_chain(CERTFILE)
socket = context.wrap_socket(self.socket,
suppress_ragged_eofs=False,
server_side=True,
do_handshake_on_connect=False)
self.del_channel()
self.set_socket(socket)
self._ssl_accepting = True
......
......@@ -77,9 +77,9 @@ if ssl:
def get_request(self):
newsocket, fromaddr = self.socket.accept()
connstream = ssl.wrap_socket(newsocket,
server_side=True,
certfile=CERTFILE)
context = ssl.SSLContext()
context.load_cert_chain(CERTFILE)
connstream = context.wrap_socket(newsocket, server_side=True)
return connstream, fromaddr
IMAP4_SSL = imaplib.IMAP4_SSL
......
......@@ -1542,8 +1542,10 @@ class LocalServerTests(unittest.TestCase):
elif cmd == b'STARTTLS\r\n':
reader.close()
client.sendall(b'382 Begin TLS negotiation now\r\n')
client = ssl.wrap_socket(
client, server_side=True, certfile=certfile)
context = ssl.SSLContext()
context.load_cert_chain(certfile)
client = context.wrap_socket(
client, server_side=True)
cleanup.enter_context(client)
reader = cleanup.enter_context(client.makefile('rb'))
elif cmd == b'QUIT\r\n':
......
......@@ -152,10 +152,12 @@ class DummyPOP3Handler(asynchat.async_chat):
def cmd_stls(self, arg):
if self.tls_active is False:
self.push('+OK Begin TLS negotiation')
tls_sock = ssl.wrap_socket(self.socket, certfile=CERTFILE,
server_side=True,
do_handshake_on_connect=False,
suppress_ragged_eofs=False)
context = ssl.SSLContext()
context.load_cert_chain(CERTFILE)
tls_sock = context.wrap_socket(self.socket,
server_side=True,
do_handshake_on_connect=False,
suppress_ragged_eofs=False)
self.del_channel()
self.set_socket(tls_sock)
self.tls_active = True
......
This diff is collapsed.
......@@ -469,10 +469,11 @@ Connection: close
@unittest.skipUnless(ssl, "ssl module required")
def test_cafile_and_context(self):
context = ssl.create_default_context()
with self.assertRaises(ValueError):
urllib.request.urlopen(
"https://localhost", cafile="/nonexistent/path", context=context
)
with support.check_warnings(('', DeprecationWarning)):
with self.assertRaises(ValueError):
urllib.request.urlopen(
"https://localhost", cafile="/nonexistent/path", context=context
)
class urlopen_DataTests(unittest.TestCase):
"""Test urlopen() opening a data URL."""
......
......@@ -548,26 +548,28 @@ class TestUrlopen(unittest.TestCase):
def test_https_with_cafile(self):
handler = self.start_https_server(certfile=CERT_localhost)
# Good cert
data = self.urlopen("https://localhost:%s/bizarre" % handler.port,
cafile=CERT_localhost)
self.assertEqual(data, b"we care a bit")
# Bad cert
with self.assertRaises(urllib.error.URLError) as cm:
self.urlopen("https://localhost:%s/bizarre" % handler.port,
cafile=CERT_fakehostname)
# Good cert, but mismatching hostname
handler = self.start_https_server(certfile=CERT_fakehostname)
with self.assertRaises(ssl.CertificateError) as cm:
self.urlopen("https://localhost:%s/bizarre" % handler.port,
cafile=CERT_fakehostname)
with support.check_warnings(('', DeprecationWarning)):
# Good cert
data = self.urlopen("https://localhost:%s/bizarre" % handler.port,
cafile=CERT_localhost)
self.assertEqual(data, b"we care a bit")
# Bad cert
with self.assertRaises(urllib.error.URLError) as cm:
self.urlopen("https://localhost:%s/bizarre" % handler.port,
cafile=CERT_fakehostname)
# Good cert, but mismatching hostname
handler = self.start_https_server(certfile=CERT_fakehostname)
with self.assertRaises(ssl.CertificateError) as cm:
self.urlopen("https://localhost:%s/bizarre" % handler.port,
cafile=CERT_fakehostname)
def test_https_with_cadefault(self):
handler = self.start_https_server(certfile=CERT_localhost)
# Self-signed cert should fail verification with system certificate store
with self.assertRaises(urllib.error.URLError) as cm:
self.urlopen("https://localhost:%s/bizarre" % handler.port,
cadefault=True)
with support.check_warnings(('', DeprecationWarning)):
with self.assertRaises(urllib.error.URLError) as cm:
self.urlopen("https://localhost:%s/bizarre" % handler.port,
cadefault=True)
def test_https_sni(self):
if ssl is None:
......
......@@ -198,6 +198,9 @@ def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
'''
global _opener
if cafile or capath or cadefault:
import warnings
warnings.warn("cafile, cpath and cadefault are deprecated, use a "
"custom context instead.", DeprecationWarning, 2)
if context is not None:
raise ValueError(
"You can't pass both context and any of cafile, capath, and "
......
......@@ -138,7 +138,11 @@ Core and Builtins
Library
-------
- Issue 28043: SSLContext has improved default settings: OP_NO_SSLv2,
- Issue #28022: Deprecate ssl-related arguments in favor of SSLContext. The
deprecation include manual creation of SSLSocket and certfile/keyfile
(or similar) in ftplib, httplib, imaplib, smtplib, poplib and urllib.
- Issue #28043: SSLContext has improved default settings: OP_NO_SSLv2,
OP_NO_SSLv3, OP_NO_COMPRESSION, OP_CIPHER_SERVER_PREFERENCE,
OP_SINGLE_DH_USE, OP_SINGLE_ECDH_USE and HIGH ciphers without MD5.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment