Issue #19292: Add SSLContext.load_default_certs() to load default root CA
certificates from default stores or system stores. By default the method loads CA certs for authentication of server certs.
This commit is contained in:
parent
a30d82f597
commit
72d28500b3
|
@ -681,6 +681,20 @@ Constants
|
||||||
|
|
||||||
.. versionadded:: 3.4
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
|
.. data:: Purpose.SERVER_AUTH
|
||||||
|
|
||||||
|
Option for :meth:`SSLContext.load_default_certs` to load CA certificates
|
||||||
|
for TLS web server authentication (client side socket).
|
||||||
|
|
||||||
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
|
.. data:: Purpose.clientAuth
|
||||||
|
|
||||||
|
Option for :meth:`SSLContext.load_default_certs` to load CA certificates
|
||||||
|
for TLS web client authentication (server side socket).
|
||||||
|
|
||||||
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
|
|
||||||
SSL Sockets
|
SSL Sockets
|
||||||
-----------
|
-----------
|
||||||
|
@ -903,6 +917,22 @@ to speed up repeated connections from the same clients.
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
New optional argument *password*.
|
New optional argument *password*.
|
||||||
|
|
||||||
|
.. method:: SSLContext.load_default_certs(purpose=Purpose.SERVER_AUTH)
|
||||||
|
|
||||||
|
Load a set of default "certification authority" (CA) certificates from
|
||||||
|
default locations. On Windows it loads CA certs from the ``CA`` and
|
||||||
|
``ROOT`` system stores. On other systems it calls
|
||||||
|
:meth:`SSLContext.set_default_verify_paths`. In the future the method may
|
||||||
|
load CA certificates from other locations, too.
|
||||||
|
|
||||||
|
The *purpose* flag specifies what kind of CA certificates are loaded. The
|
||||||
|
default settings :data:`Purpose.SERVER_AUTH` loads certificates, that are
|
||||||
|
flagged and trusted for TLS web server authentication (client side
|
||||||
|
sockets). :data:`Purpose.clientAuth` loads CA certificates for client
|
||||||
|
certificate verification on the server side.
|
||||||
|
|
||||||
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
.. method:: SSLContext.load_verify_locations(cafile=None, capath=None, cadata=None)
|
.. method:: SSLContext.load_verify_locations(cafile=None, capath=None, cadata=None)
|
||||||
|
|
||||||
Load a set of "certification authority" (CA) certificates used to validate
|
Load a set of "certification authority" (CA) certificates used to validate
|
||||||
|
@ -931,7 +961,6 @@ to speed up repeated connections from the same clients.
|
||||||
.. versionchanged:: 3.4
|
.. versionchanged:: 3.4
|
||||||
New optional argument *cadata*
|
New optional argument *cadata*
|
||||||
|
|
||||||
|
|
||||||
.. method:: SSLContext.get_ca_certs(binary_form=False)
|
.. method:: SSLContext.get_ca_certs(binary_form=False)
|
||||||
|
|
||||||
Get a list of loaded "certification authority" (CA) certificates. If the
|
Get a list of loaded "certification authority" (CA) certificates. If the
|
||||||
|
|
28
Lib/ssl.py
28
Lib/ssl.py
|
@ -92,6 +92,7 @@ import re
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
from enum import Enum as _Enum
|
||||||
|
|
||||||
import _ssl # if we can't import it, let the error propagate
|
import _ssl # if we can't import it, let the error propagate
|
||||||
|
|
||||||
|
@ -298,11 +299,19 @@ class _ASN1Object(namedtuple("_ASN1Object", "nid shortname longname oid")):
|
||||||
return super().__new__(cls, *_txt2obj(name, name=True))
|
return super().__new__(cls, *_txt2obj(name, name=True))
|
||||||
|
|
||||||
|
|
||||||
|
class Purpose(_ASN1Object, _Enum):
|
||||||
|
"""SSLContext purpose flags with X509v3 Extended Key Usage objects
|
||||||
|
"""
|
||||||
|
SERVER_AUTH = '1.3.6.1.5.5.7.3.1'
|
||||||
|
CLIENT_AUTH = '1.3.6.1.5.5.7.3.2'
|
||||||
|
|
||||||
|
|
||||||
class SSLContext(_SSLContext):
|
class SSLContext(_SSLContext):
|
||||||
"""An SSLContext holds various SSL-related configuration options and
|
"""An SSLContext holds various SSL-related configuration options and
|
||||||
data, such as certificates and possibly a private key."""
|
data, such as certificates and possibly a private key."""
|
||||||
|
|
||||||
__slots__ = ('protocol', '__weakref__')
|
__slots__ = ('protocol', '__weakref__')
|
||||||
|
_windows_cert_stores = ("CA", "ROOT")
|
||||||
|
|
||||||
def __new__(cls, protocol, *args, **kwargs):
|
def __new__(cls, protocol, *args, **kwargs):
|
||||||
self = _SSLContext.__new__(cls, protocol)
|
self = _SSLContext.__new__(cls, protocol)
|
||||||
|
@ -334,6 +343,25 @@ class SSLContext(_SSLContext):
|
||||||
|
|
||||||
self._set_npn_protocols(protos)
|
self._set_npn_protocols(protos)
|
||||||
|
|
||||||
|
def _load_windows_store_certs(self, storename, purpose):
|
||||||
|
certs = bytearray()
|
||||||
|
for cert, encoding, trust in enum_certificates(storename):
|
||||||
|
# CA certs are never PKCS#7 encoded
|
||||||
|
if encoding == "x509_asn":
|
||||||
|
if trust is True or purpose.oid in trust:
|
||||||
|
certs.extend(cert)
|
||||||
|
self.load_verify_locations(cadata=certs)
|
||||||
|
return certs
|
||||||
|
|
||||||
|
def load_default_certs(self, purpose=Purpose.SERVER_AUTH):
|
||||||
|
if not isinstance(purpose, _ASN1Object):
|
||||||
|
raise TypeError(purpose)
|
||||||
|
if sys.platform == "win32":
|
||||||
|
for storename in self._windows_cert_stores:
|
||||||
|
self._load_windows_store_certs(storename, purpose)
|
||||||
|
else:
|
||||||
|
self.set_default_verify_paths()
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -611,6 +611,23 @@ class BasicSocketTests(unittest.TestCase):
|
||||||
with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
|
with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
|
||||||
ssl._ASN1Object.fromname('serverauth')
|
ssl._ASN1Object.fromname('serverauth')
|
||||||
|
|
||||||
|
def test_purpose_enum(self):
|
||||||
|
val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
|
||||||
|
self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
|
||||||
|
self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
|
||||||
|
self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
|
||||||
|
self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
|
||||||
|
self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
|
||||||
|
'1.3.6.1.5.5.7.3.1')
|
||||||
|
|
||||||
|
val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
|
||||||
|
self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
|
||||||
|
self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
|
||||||
|
self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
|
||||||
|
self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
|
||||||
|
self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
|
||||||
|
'1.3.6.1.5.5.7.3.2')
|
||||||
|
|
||||||
|
|
||||||
class ContextTests(unittest.TestCase):
|
class ContextTests(unittest.TestCase):
|
||||||
|
|
||||||
|
@ -967,6 +984,21 @@ class ContextTests(unittest.TestCase):
|
||||||
der = ssl.PEM_cert_to_DER_cert(pem)
|
der = ssl.PEM_cert_to_DER_cert(pem)
|
||||||
self.assertEqual(ctx.get_ca_certs(True), [der])
|
self.assertEqual(ctx.get_ca_certs(True), [der])
|
||||||
|
|
||||||
|
def test_load_default_certs(self):
|
||||||
|
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||||
|
ctx.load_default_certs()
|
||||||
|
|
||||||
|
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||||
|
ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
|
||||||
|
ctx.load_default_certs()
|
||||||
|
|
||||||
|
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||||
|
ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
|
||||||
|
|
||||||
|
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||||
|
self.assertRaises(TypeError, ctx.load_default_certs, None)
|
||||||
|
self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
|
||||||
|
|
||||||
|
|
||||||
class SSLErrorTests(unittest.TestCase):
|
class SSLErrorTests(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,10 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #19292: Add SSLContext.load_default_certs() to load default root CA
|
||||||
|
certificates from default stores or system stores. By default the method
|
||||||
|
loads CA certs for authentication of server certs.
|
||||||
|
|
||||||
- Issue #19673: Add pathlib to the stdlib as a provisional module (PEP 428).
|
- Issue #19673: Add pathlib to the stdlib as a provisional module (PEP 428).
|
||||||
|
|
||||||
- Issue #17916: Added dis.Bytecode.from_traceback() and
|
- Issue #17916: Added dis.Bytecode.from_traceback() and
|
||||||
|
|
Loading…
Reference in New Issue