Issue #8550: Add first class `SSLContext` objects to the ssl module.
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
index 95f5f70..45ffcb0 100644
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -36,6 +36,11 @@
 connection, and a method, :meth:`cipher`, to retrieve the cipher being used for
 the secure connection.
 
+For more sophisticated applications, the :class:`ssl.SSLContext` class
+helps manage settings and certificates, which can then be inherited
+by SSL sockets created through the :meth:`SSLContext.wrap_socket` method.
+
+
 Functions, Constants, and Exceptions
 ------------------------------------
 
@@ -64,19 +69,6 @@
    connection.  See the discussion of :ref:`ssl-certificates` for more
    information on how the certificate is stored in the ``certfile``.
 
-   Often the private key is stored in the same file as the certificate; in this
-   case, only the ``certfile`` parameter need be passed.  If the private key is
-   stored in a separate file, both parameters must be used.  If the private key
-   is stored in the ``certfile``, it should come before the first certificate in
-   the certificate chain::
-
-      -----BEGIN RSA PRIVATE KEY-----
-      ... (private key in base64 encoding) ...
-      -----END RSA PRIVATE KEY-----
-      -----BEGIN CERTIFICATE-----
-      ... (certificate in base64 PEM encoding) ...
-      -----END CERTIFICATE-----
-
    The parameter ``server_side`` is a boolean which identifies whether
    server-side or client-side behavior is desired from this socket.
 
@@ -208,24 +200,36 @@
 
 .. data:: CERT_NONE
 
-   Value to pass to the ``cert_reqs`` parameter to :func:`sslobject` when no
-   certificates will be required or validated from the other side of the socket
-   connection.
+   Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs``
+   parameter to :func:`wrap_socket`.  In this mode (the default), no
+   certificates will be required from the other side of the socket connection.
+   If a certificate is received from the other end, no attempt to validate it
+   is made.
+
+   See the discussion of :ref:`ssl-security` below.
 
 .. data:: CERT_OPTIONAL
 
-   Value to pass to the ``cert_reqs`` parameter to :func:`sslobject` when no
-   certificates will be required from the other side of the socket connection,
-   but if they are provided, will be validated.  Note that use of this setting
-   requires a valid certificate validation file also be passed as a value of the
-   ``ca_certs`` parameter.
+   Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs``
+   parameter to :func:`wrap_socket`.  In this mode no certificates will be
+   required from the other side of the socket connection; but if they
+   are provided, validation will be attempted and an :class:`SSLError`
+   will be raised on failure.
+
+   Use of this setting requires a valid set of CA certificates to
+   be passed, either to :meth:`SSLContext.load_verify_locations` or as a
+   value of the ``ca_certs`` parameter to :func:`wrap_socket`.
 
 .. data:: CERT_REQUIRED
 
-   Value to pass to the ``cert_reqs`` parameter to :func:`sslobject` when
-   certificates will be required from the other side of the socket connection.
-   Note that use of this setting requires a valid certificate validation file
-   also be passed as a value of the ``ca_certs`` parameter.
+   Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs``
+   parameter to :func:`wrap_socket`.  In this mode, certificates are
+   required from the other side of the socket connection; an :class:`SSLError`
+   will be raised if no certificate is provided, or if its validation fails.
+
+   Use of this setting requires a valid set of CA certificates to
+   be passed, either to :meth:`SSLContext.load_verify_locations` or as a
+   value of the ``ca_certs`` parameter to :func:`wrap_socket`.
 
 .. data:: PROTOCOL_SSLv2
 
@@ -284,8 +288,8 @@
    .. versionadded:: 3.2
 
 
-SSLSocket Objects
------------------
+SSL Sockets
+-----------
 
 .. method:: SSLSocket.read(nbytes=1024, buffer=None)
 
@@ -371,6 +375,83 @@
    returned socket should always be used for further communication with the
    other side of the connection, rather than the original socket.
 
+
+SSL Contexts
+------------
+
+.. class:: SSLContext(protocol)
+
+   An object holding various data longer-lived than single SSL connections,
+   such as SSL configuration options, certificate(s) and private key(s).
+   You must pass *protocol* which must be one of the ``PROTOCOL_*`` constants
+   defined in this module.  :data:`PROTOCOL_SSLv23` is recommended for
+   maximum interoperability.
+
+:class:`SSLContext` objects have the following methods and attributes:
+
+.. method:: SSLContext.load_cert_chain(certfile, keyfile=None)
+
+   Load a private key and the corresponding certificate.  The *certfile*
+   string must be the path to a single file in PEM format containing the
+   certificate as well as any number of CA certificates needed to establish
+   the certificate's authenticity.  The *keyfile* string, if present, must
+   point to a file containing the private key in.  Otherwise the private
+   key will be taken from *certfile* as well.  See the discussion of
+   :ref:`ssl-certificates` for more information on how the certificate
+   is stored in the *certfile*.
+
+   An :class:`SSLError` is raised if the private key doesn't
+   match with the certificate.
+
+.. method:: SSLContext.load_verify_locations(cafile=None, capath=None)
+
+   Load a set of "certification authority" (CA) certificates used to validate
+   other peers' certificates when :data:`verify_mode` is other than
+   :data:`CERT_NONE`.  At least one of *cafile* or *capath* must be specified.
+
+   The *cafile* string, if present, is the path to a file of concatenated
+   CA certificates in PEM format. See the discussion of
+   :ref:`ssl-certificates` for more information about how to arrange the
+   certificates in this file.
+
+   The *capath* string, if present, is
+   the path to a directory containing several CA certificates in PEM format,
+   following an `OpenSSL specific layout
+   <http://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html>`_.
+
+.. method:: SSLContext.set_ciphers(ciphers)
+
+   Set the available ciphers for sockets created with this context.
+   It should be a string in the `OpenSSL cipher list format
+   <http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT>`_.
+   If no cipher can be selected (because compile-time options or other
+   configuration forbids use of all the specified ciphers), an
+   :class:`SSLError` will be raised.
+
+   .. note::
+      when connected, the :meth:`SSLSocket.cipher` method of SSL sockets will
+      give the currently selected cipher.
+
+.. method:: SSLContext.wrap_socket(sock, server_side=False, do_handshake_on_connect=True, suppress_ragged_eofs=True)
+
+   Wrap an existing Python socket *sock* and return an :class:`SSLSocket`
+   object.  The SSL socket is tied to the context, its settings and
+   certificates.  The parameters *server_side*, *do_handshake_on_connect*
+   and *suppress_ragged_eofs* have the same meaning as in the top-level
+   :func:`wrap_socket` function.
+
+.. attribute:: SSLContext.protocol
+
+   The protocol version chosen when constructing the context.  This attribute
+   is read-only.
+
+.. attribute:: SSLContext.verify_mode
+
+   Whether to try to verify other peers' certificates and how to behave
+   if verification fails.  This attribute must be one of
+   :data:`CERT_NONE`, :data:`CERT_OPTIONAL` or :data:`CERT_REQUIRED`.
+
+
 .. index:: single: certificates
 
 .. index:: single: X509 certificate
@@ -416,6 +497,9 @@
       ... (certificate in base64 PEM encoding) ...
       -----END CERTIFICATE-----
 
+Certificate chains
+^^^^^^^^^^^^^^^^^^
+
 The Python files which contain certificates can contain a sequence of
 certificates, sometimes called a *certificate chain*.  This chain should start
 with the specific certificate for the principal who "is" the client or server,
@@ -439,6 +523,9 @@
       ... (the root certificate for the CA's issuer)...
       -----END CERTIFICATE-----
 
+CA certificates
+^^^^^^^^^^^^^^^
+
 If you are going to require validation of the other side of the connection's
 certificate, you need to provide a "CA certs" file, filled with the certificate
 chains for each issuer you are willing to trust.  Again, this file just contains
@@ -458,6 +545,25 @@
 certificate to a root certificate.  See :rfc:`4158` for more discussion of the
 way in which certification chains can be built.
 
+Combined key and certificate
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Often the private key is stored in the same file as the certificate; in this
+case, only the ``certfile`` parameter to :meth:`SSLContext.load_cert_chain`
+and :func:`wrap_socket` needs to be passed.  If the private key is stored
+with the certificate, it should come before the first certificate in
+the certificate chain::
+
+   -----BEGIN RSA PRIVATE KEY-----
+   ... (private key in base64 encoding) ...
+   -----END RSA PRIVATE KEY-----
+   -----BEGIN CERTIFICATE-----
+   ... (certificate in base64 PEM encoding) ...
+   -----END CERTIFICATE-----
+
+Self-signed certificates
+^^^^^^^^^^^^^^^^^^^^^^^^
+
 If you are going to create a server that provides SSL-encrypted connection
 services, you will need to acquire a certificate for that service.  There are
 many ways of acquiring appropriate certificates, such as buying one from a
@@ -530,8 +636,7 @@
    print(pprint.pformat(ssl_sock.getpeercert()))
 
    # Set a simple HTTP request -- use http.client in actual code.
-   ssl_sock.write("""GET / HTTP/1.0\r
-   Host: www.verisign.com\r\n\r\n""")
+   ssl_sock.write(b"GET / HTTP/1.0\r\nHost: www.verisign.com\r\n\r\n")
 
    # Read a chunk of data.  Will not necessarily
    # read all the data returned by the server.
@@ -561,39 +666,91 @@
 
 which is a fairly poorly-formed ``subject`` field.
 
+This other example first creates an SSL context, instructs it to verify
+certificates sent by peers, and feeds it a set of recognized certificate
+authorities (CA)::
+
+   >>> context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
+   >>> context.verify_mode = ssl.CERT_OPTIONAL
+   >>> context.load_verify_locations("/etc/ssl/certs/ca-bundle.crt")
+
+(it is assumed your operating system places a bundle of all CA certificates
+in ``/etc/ssl/certs/ca-bundle.crt``; if not, you'll get an error and have
+to adjust the location)
+
+When you use the context to connect to a server, :const:`CERT_OPTIONAL`
+validates the server certificate: it ensures that the server certificate
+was signed with one of the CA certificates, and checks the signature for
+correctness::
+
+   >>> conn = context.wrap_socket(socket.socket(socket.AF_INET))
+   >>> conn.connect(("linuxfr.org", 443))
+
+You should then fetch the certificate and check its fields for conformity.
+Here, the ``commonName`` field in the ``subject`` matches the desired HTTPS
+host ``linuxfr.org``::
+
+   >>> pprint.pprint(conn.getpeercert())
+   {'notAfter': 'Jun 26 21:41:46 2011 GMT',
+    'subject': ((('commonName', 'linuxfr.org'),),),
+    'subjectAltName': (('DNS', 'linuxfr.org'), ('othername', '<unsupported>'))}
+
+Now that you are assured of its authenticity, you can proceed to talk with
+the server::
+
+   >>> conn.write(b"HEAD / HTTP/1.0\r\nHost: linuxfr.org\r\n\r\n")
+   38
+   >>> pprint.pprint(conn.read().split(b"\r\n"))
+   [b'HTTP/1.1 302 Found',
+    b'Date: Sun, 16 May 2010 13:43:28 GMT',
+    b'Server: Apache/2.2',
+    b'Location: https://linuxfr.org/pub/',
+    b'Vary: Accept-Encoding',
+    b'Connection: close',
+    b'Content-Type: text/html; charset=iso-8859-1',
+    b'',
+    b'']
+
+
+See the discussion of :ref:`ssl-security` below.
+
+
 Server-side operation
 ^^^^^^^^^^^^^^^^^^^^^
 
-For server operation, typically you'd need to have a server certificate, and
-private key, each in a file.  You'd open a socket, bind it to a port, call
-:meth:`listen` on it, then start waiting for clients to connect::
+For server operation, typically you'll need to have a server certificate, and
+private key, each in a file.  You'll first create a context holding the key
+and the certificate, so that clients can check your authenticity.  Then
+you'll open a socket, bind it to a port, call :meth:`listen` on it, and start
+waiting for clients to connect::
 
    import socket, ssl
 
+   context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
+   context.load_cert_chain(certfile="mycertfile", keyfile="mykeyfile")
+
    bindsocket = socket.socket()
    bindsocket.bind(('myaddr.mydomain.com', 10023))
    bindsocket.listen(5)
 
-When one did, you'd call :meth:`accept` on the socket to get the new socket from
-the other end, and use :func:`wrap_socket` to create a server-side SSL context
-for it::
+When a client connects, you'll call :meth:`accept` on the socket to get the
+new socket from the other end, and use the context's :meth:`SSLContext.wrap_socket`
+method to create a server-side SSL socket for the connection::
 
    while True:
       newsocket, fromaddr = bindsocket.accept()
-      connstream = ssl.wrap_socket(newsocket,
-                                   server_side=True,
-                                   certfile="mycertfile",
-                                   keyfile="mykeyfile",
-                                   ssl_version=ssl.PROTOCOL_TLSv1)
-      deal_with_client(connstream)
+      connstream = context.wrap_socket(newsocket, server_side=True)
+      try:
+         deal_with_client(connstream)
+      finally:
+         connstream.close()
 
-Then you'd read data from the ``connstream`` and do something with it till you
+Then you'll read data from the ``connstream`` and do something with it till you
 are finished with the client (or the client is finished with you)::
 
    def deal_with_client(connstream):
-
       data = connstream.read()
-      # null data means the client is finished with us
+      # empty data means the client is finished with us
       while data:
          if not do_something(connstream, data):
             # we'll assume do_something returns False
@@ -601,9 +758,41 @@
             break
          data = connstream.read()
       # finished with client
-      connstream.close()
 
-And go back to listening for new client connections.
+And go back to listening for new client connections (of course, a real server
+would probably handle each client connection in a separate thread, or put
+the sockets in non-blocking mode and use an event loop).
+
+
+.. _ssl-security:
+
+Security considerations
+-----------------------
+
+Verifying certificates
+^^^^^^^^^^^^^^^^^^^^^^
+
+:const:`CERT_NONE` is the default.  Since it does not authenticate the other
+peer, it can be insecure, especially in client mode where most of time you
+would like to ensure the authenticity of the server you're talking to.
+Therefore, when in client mode, it is highly recommended to use
+:const:`CERT_REQUIRED`.  However, it is in itself not sufficient; you also
+have to check that the server certificate (obtained with
+:meth:`SSLSocket.getpeercert`) matches the desired service.  The exact way
+of doing so depends on the higher-level protocol used; for example, with
+HTTPS, you'll check that the host name in the URL matches either the
+``commonName`` field in the ``subjectName``, or one of the ``DNS`` fields
+in the ``subjectAltName``.
+
+In server mode, if you want to authenticate your clients using the SSL layer
+(rather than using a higher-level authentication mechanism), you'll also have
+to specify :const:`CERT_REQUIRED` and similarly check the client certificate.
+
+   .. note::
+
+      In client mode, :const:`CERT_OPTIONAL` and :const:`CERT_REQUIRED` are
+      equivalent unless anonymous ciphers are enabled (they are disabled
+      by default).
 
 
 .. seealso::