summaryrefslogtreecommitdiffstats
path: root/Lib/ssl.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/ssl.py')
-rw-r--r--Lib/ssl.py50
1 files changed, 44 insertions, 6 deletions
diff --git a/Lib/ssl.py b/Lib/ssl.py
index 880a3d4..72e6a6e 100644
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -398,6 +398,43 @@ def create_default_context(purpose=Purpose.SERVER_AUTH, *, cafile=None,
return context
+def _create_stdlib_context(protocol=PROTOCOL_SSLv23, *, cert_reqs=None,
+ purpose=Purpose.SERVER_AUTH,
+ certfile=None, keyfile=None,
+ cafile=None, capath=None, cadata=None):
+ """Create a SSLContext object for Python stdlib modules
+
+ All Python stdlib modules shall use this function to create SSLContext
+ objects in order to keep common settings in one place. The configuration
+ is less restrict than create_default_context()'s to increase backward
+ compatibility.
+ """
+ if not isinstance(purpose, _ASN1Object):
+ raise TypeError(purpose)
+
+ context = SSLContext(protocol)
+ # SSLv2 considered harmful.
+ context.options |= OP_NO_SSLv2
+
+ if cert_reqs is not None:
+ context.verify_mode = cert_reqs
+
+ if keyfile and not certfile:
+ raise ValueError("certfile must be specified")
+ if certfile or keyfile:
+ context.load_cert_chain(certfile, keyfile)
+
+ # load CA root certs
+ 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):
"""This class implements a subtype of socket.socket that wraps
the underlying OS socket in an SSL context when necessary, and
@@ -829,15 +866,16 @@ def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None):
If 'ssl_version' is specified, use it in the connection attempt."""
host, port = addr
- if (ca_certs is not None):
+ if ca_certs is not None:
cert_reqs = CERT_REQUIRED
else:
cert_reqs = CERT_NONE
- s = create_connection(addr)
- s = wrap_socket(s, ssl_version=ssl_version,
- cert_reqs=cert_reqs, ca_certs=ca_certs)
- dercert = s.getpeercert(True)
- s.close()
+ context = _create_stdlib_context(ssl_version,
+ cert_reqs=cert_reqs,
+ cafile=ca_certs)
+ with create_connection(addr) as sock:
+ with context.wrap_socket(sock) as sslsock:
+ dercert = sslsock.getpeercert(True)
return DER_cert_to_PEM_cert(dercert)
def get_protocol_name(protocol_code):