Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(5854)

Unified Diff: Lib/ssl.py

Issue 19689: ssl.create_default_context()
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Lib/smtplib.py ('k') | Lib/test/test_ssl.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
--- a/Lib/ssl.py Fri Nov 22 16:20:53 2013 +0100
+++ b/Lib/ssl.py Fri Nov 22 18:04:20 2013 +0100
@@ -92,6 +92,7 @@
import sys
import os
from collections import namedtuple
+import enum as _enum
import _ssl # if we can't import it, let the error propagate
@@ -298,6 +299,23 @@
return super().__new__(cls, *_txt2obj(name, name=True))
+class PurposeEKU(_ASN1Object, _enum.Enum):
+ """X509v3 Extended Key Usage objects
+ """
+ serverAuth = '1.3.6.1.5.5.7.3.1'
+ clientAuth = '1.3.6.1.5.5.7.3.2'
+ #codeSigning = '1.3.6.1.5.5.7.3.3'
+ #emailProtection = '1.3.6.1.5.5.7.3.4'
+ #ipsecEndSystem = '1.3.6.1.5.5.7.3.5'
+ #ipsecTunnel = '1.3.6.1.5.5.7.3.6'
+ #ipsecUser = '1.3.6.1.5.5.7.3.7'
+ #timeStamping = '1.3.6.1.5.5.7.3.8'
+ #OCSPSigning = '1.3.6.1.5.5.7.3.9'
+ #DVCS = '1.3.6.1.5.5.7.3.10'
+ #nsSGC = '2.16.840.1.113730.4.1'
+ #msSGC = '1.3.6.1.4.1.311.10.3.3'
+
+
class SSLContext(_SSLContext):
"""An SSLContext holds various SSL-related configuration options and
data, such as certificates and possibly a private key."""
@@ -334,6 +352,58 @@
self._set_npn_protocols(protos)
+ def load_default_certs(self, purpose):
+ if not isinstance(purpose, _ASN1Object):
+ raise TypeError(purpose)
+ self.set_default_verify_paths()
+
+
+def create_default_context(protocol=PROTOCOL_SSLv23, *, cert_reqs=None,
+ purpose=PurposeEKU.serverAuth,
+ certfile=None, keyfile=None,
+ 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)
+ # SSLv2 considered harmful.
+ context.options |= OP_NO_SSLv2
+
+ if cert_reqs is None:
+ if purpose == PurposeEKU.serverAuth:
+ # authenticate a TLS web server (for client sockets). The default
+ # setting may change in the future.
+ cert_reqs = CERT_NONE
+ elif purpose == PurposeEKU.clientAuth:
+ # authenticate a TLS web client (for server sockets). The default
+ # setting is guaranteed to be stable and will never change.
+ cert_reqs = CERT_NONE
+ else:
+ # other (code signing, S/MIME, IPSEC, ...), default may change.
+ cert_reqs = CERT_NONE
+ context.verify_mode = cert_reqs
+
+ # load cert file and key file
+ 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 cert_reqs != CERT_NONE and purpose is not 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
@@ -759,22 +829,22 @@
d = pem_cert_string.strip()[len(PEM_HEADER):-len(PEM_FOOTER)]
return base64.decodebytes(d.encode('ASCII', 'strict'))
-def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None):
+def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None,
+ cert_reqs=None):
"""Retrieve the certificate from the server at the specified address,
and return it as a PEM-encoded string.
If 'ca_certs' is specified, validate the server cert against it.
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_default_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):
« no previous file with comments | « Lib/smtplib.py ('k') | Lib/test/test_ssl.py » ('j') | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+