mirror of https://github.com/python/cpython.git
Issue #19689: Add ssl.create_default_context() factory function. It creates
a new SSLContext object with secure default settings.
This commit is contained in:
parent
6b2ff98df4
commit
4c05b472dd
|
@ -346,6 +346,24 @@ Certificate handling
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
This function is now IPv6-compatible.
|
This function is now IPv6-compatible.
|
||||||
|
|
||||||
|
.. function:: create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None, capath=None, cadata=None)
|
||||||
|
|
||||||
|
Create a :class:`SSLContext` with default settings.
|
||||||
|
|
||||||
|
The current settings are: :data:`PROTOCOL_TLSv1` with high encryption
|
||||||
|
cipher suites without RC4 and without unauthenticated cipher suites. The
|
||||||
|
*purpose* :data:`Purpose.SERVER_AUTH` sets verify_mode to
|
||||||
|
:data:`CERT_REQUIRED` and either loads CA certs (when at least one of
|
||||||
|
*cafile*, *capath* or *cadata* is given) or uses
|
||||||
|
:meth:`SSLContext.load_default_certs` to load default CA certs.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
The protocol, options, cipher and other settings may change to more
|
||||||
|
restrictive values anytime without prior deprecation. The values
|
||||||
|
represent a fair balance between maximum compatibility and security.
|
||||||
|
|
||||||
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
.. function:: DER_cert_to_PEM_cert(DER_cert_bytes)
|
.. function:: DER_cert_to_PEM_cert(DER_cert_bytes)
|
||||||
|
|
||||||
Given a certificate as a DER-encoded blob of bytes, returns a PEM-encoded
|
Given a certificate as a DER-encoded blob of bytes, returns a PEM-encoded
|
||||||
|
|
35
Lib/ssl.py
35
Lib/ssl.py
|
@ -165,6 +165,13 @@ def _import_symbols(prefix):
|
||||||
# (OpenSSL's default setting is 'DEFAULT:!aNULL:!eNULL')
|
# (OpenSSL's default setting is 'DEFAULT:!aNULL:!eNULL')
|
||||||
_DEFAULT_CIPHERS = 'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2'
|
_DEFAULT_CIPHERS = 'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2'
|
||||||
|
|
||||||
|
# restricted and more secure ciphers
|
||||||
|
# HIGH: high encryption cipher suites with key length >= 128 bits (no MD5)
|
||||||
|
# !aNULL: only authenticated cipher suites (no anonymous DH)
|
||||||
|
# !RC4: no RC4 streaming cipher, RC4 is broken
|
||||||
|
# !DSS: RSA is preferred over DSA
|
||||||
|
_RESTRICTED_CIPHERS = 'HIGH:!aNULL:!RC4:!DSS'
|
||||||
|
|
||||||
|
|
||||||
class CertificateError(ValueError):
|
class CertificateError(ValueError):
|
||||||
pass
|
pass
|
||||||
|
@ -363,6 +370,34 @@ def load_default_certs(self, purpose=Purpose.SERVER_AUTH):
|
||||||
self.set_default_verify_paths()
|
self.set_default_verify_paths()
|
||||||
|
|
||||||
|
|
||||||
|
def create_default_context(purpose=Purpose.SERVER_AUTH, *, cafile=None,
|
||||||
|
capath=None, cadata=None):
|
||||||
|
"""Create a SSLContext object with default settings.
|
||||||
|
|
||||||
|
NOTE: The protocol and settings may change anytime without prior
|
||||||
|
deprecation. The values represent a fair balance between maximum
|
||||||
|
compatibility and security.
|
||||||
|
"""
|
||||||
|
if not isinstance(purpose, _ASN1Object):
|
||||||
|
raise TypeError(purpose)
|
||||||
|
context = SSLContext(PROTOCOL_TLSv1)
|
||||||
|
# SSLv2 considered harmful.
|
||||||
|
context.options |= OP_NO_SSLv2
|
||||||
|
# disallow ciphers with known vulnerabilities
|
||||||
|
context.set_ciphers(_RESTRICTED_CIPHERS)
|
||||||
|
# verify certs in client mode
|
||||||
|
if purpose == Purpose.SERVER_AUTH:
|
||||||
|
context.verify_mode = CERT_REQUIRED
|
||||||
|
if cafile or capath or cadata:
|
||||||
|
context.load_verify_locations(cafile, capath, cadata)
|
||||||
|
elif context.verify_mode != CERT_NONE:
|
||||||
|
# no explicit cafile, capath or cadata but the verify mode is
|
||||||
|
# CERT_OPTIONAL or CERT_REQUIRED. Let's try to load default system
|
||||||
|
# root CA certificates for the given purpose. This may fail silently.
|
||||||
|
context.load_default_certs(purpose)
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class SSLSocket(socket):
|
class SSLSocket(socket):
|
||||||
"""This class implements a subtype of socket.socket that wraps
|
"""This class implements a subtype of socket.socket that wraps
|
||||||
the underlying OS socket in an SSL context when necessary, and
|
the underlying OS socket in an SSL context when necessary, and
|
||||||
|
|
|
@ -999,6 +999,26 @@ def test_load_default_certs(self):
|
||||||
self.assertRaises(TypeError, ctx.load_default_certs, None)
|
self.assertRaises(TypeError, ctx.load_default_certs, None)
|
||||||
self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
|
self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
|
||||||
|
|
||||||
|
def test_create_default_context(self):
|
||||||
|
ctx = ssl.create_default_context()
|
||||||
|
self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
|
||||||
|
self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
|
||||||
|
self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
|
||||||
|
|
||||||
|
with open(SIGNING_CA) as f:
|
||||||
|
cadata = f.read()
|
||||||
|
ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
|
||||||
|
cadata=cadata)
|
||||||
|
self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
|
||||||
|
self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
|
||||||
|
self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
|
||||||
|
|
||||||
|
ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||||
|
self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
|
||||||
|
self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
|
||||||
|
self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SSLErrorTests(unittest.TestCase):
|
class SSLErrorTests(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #19689: Add ssl.create_default_context() factory function. It creates
|
||||||
|
a new SSLContext object with secure default settings.
|
||||||
|
|
||||||
- Issue #19292: Add SSLContext.load_default_certs() to load default root CA
|
- Issue #19292: Add SSLContext.load_default_certs() to load default root CA
|
||||||
certificates from default stores or system stores. By default the method
|
certificates from default stores or system stores. By default the method
|
||||||
loads CA certs for authentication of server certs.
|
loads CA certs for authentication of server certs.
|
||||||
|
|
Loading…
Reference in New Issue