summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2014-10-20 22:14:39 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2014-10-20 22:14:39 (GMT)
commit4b4ddb21904320bd009688a473186041c52135a4 (patch)
tree17424d212496bbfd327bdae9fd2fc206e557910c
parent67503c5f1c39413465fc5fdc192eb0ff1b7334fe (diff)
downloadcpython-4b4ddb21904320bd009688a473186041c52135a4.zip
cpython-4b4ddb21904320bd009688a473186041c52135a4.tar.gz
cpython-4b4ddb21904320bd009688a473186041c52135a4.tar.bz2
Issue #22660: update various mentions in the ssl module documentation.
-rw-r--r--Doc/library/ssl.rst210
1 files changed, 95 insertions, 115 deletions
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
index 095a831..503b04b 100644
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -201,13 +201,9 @@ instead.
.. note::
Which connections succeed will vary depending on the version of
- OpenSSL. For instance, in some older versions of OpenSSL (such
- as 0.9.7l on OS X 10.4), an SSLv2 client could not connect to an
- SSLv23 server. Another example: beginning with OpenSSL 1.0.0,
- an SSLv23 client will not actually attempt SSLv2 connections
- unless you explicitly enable SSLv2 ciphers; for example, you
- might specify ``"ALL"`` or ``"SSLv2"`` as the *ciphers* parameter
- to enable them.
+ OpenSSL. For example, beginning with OpenSSL 1.0.0, an SSLv23 client
+ will not actually attempt SSLv2 connections unless you explicitly
+ enable SSLv2 ciphers (which is not recommended, as SSLv2 is broken).
The *ciphers* parameter sets the available ciphers for this SSL object.
It should be a string in the `OpenSSL cipher list format
@@ -534,6 +530,11 @@ Constants
.. versionadded:: 3.4
+.. data:: PROTOCOL_SSLv23
+
+ Selects the highest protocol version that both the client and server support.
+ Despite the name, this option can select "TLS" protocols as well as "SSL".
+
.. data:: PROTOCOL_SSLv2
Selects SSL version 2 as the channel encryption protocol.
@@ -545,17 +546,13 @@ Constants
SSL version 2 is insecure. Its use is highly discouraged.
-.. data:: PROTOCOL_SSLv23
+.. data:: PROTOCOL_SSLv3
- Selects SSL version 2 or 3 as the channel encryption protocol. This is a
- setting to use with servers for maximum compatibility with the other end of
- an SSL connection, but it may cause the specific ciphers chosen for the
- encryption to be of fairly low quality.
+ Selects SSL version 3 as the channel encryption protocol.
-.. data:: PROTOCOL_SSLv3
+ .. warning::
- Selects SSL version 3 as the channel encryption protocol. For clients, this
- is the maximally compatible SSL variant.
+ SSL version 3 is insecure. Its use is highly discouraged.
.. data:: PROTOCOL_TLSv1
@@ -570,9 +567,9 @@ Constants
.. data:: PROTOCOL_TLSv1_2
- Selects TLS version 1.2 as the channel encryption protocol. This is the most
- modern version, and probably the best choice for maximum protection, if both
- sides can speak it. Available only with openssl version 1.0.1+.
+ Selects TLS version 1.2 as the channel encryption protocol. This is the
+ most modern version, and probably the best choice for maximum protection,
+ if both sides can speak it. Available only with openssl version 1.0.1+.
.. versionadded:: 3.4
@@ -667,9 +664,8 @@ Constants
.. data:: HAS_SNI
Whether the OpenSSL library has built-in support for the *Server Name
- Indication* extension to the SSLv3 and TLSv1 protocols (as defined in
- :rfc:`4366`). When true, you can use the *server_hostname* argument to
- :meth:`SSLContext.wrap_socket`.
+ Indication* extension (as defined in :rfc:`4366`). When true, you can
+ use the *server_hostname* argument to :meth:`SSLContext.wrap_socket`.
.. versionadded:: 3.2
@@ -1474,118 +1470,100 @@ should use the following idiom::
Client-side operation
^^^^^^^^^^^^^^^^^^^^^
-This example connects to an SSL server and prints the server's certificate::
-
- import socket, ssl, pprint
-
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- # require a certificate from the server
- ssl_sock = ssl.wrap_socket(s,
- ca_certs="/etc/ca_certs_file",
- cert_reqs=ssl.CERT_REQUIRED)
- ssl_sock.connect(('www.verisign.com', 443))
-
- pprint.pprint(ssl_sock.getpeercert())
- # note that closing the SSLSocket will also close the underlying socket
- ssl_sock.close()
-
-As of January 6, 2012, the certificate printed by this program looks like
-this::
-
- {'issuer': ((('countryName', 'US'),),
- (('organizationName', 'VeriSign, Inc.'),),
- (('organizationalUnitName', 'VeriSign Trust Network'),),
- (('organizationalUnitName',
- 'Terms of use at https://www.verisign.com/rpa (c)06'),),
- (('commonName',
- 'VeriSign Class 3 Extended Validation SSL SGC CA'),)),
- 'notAfter': 'May 25 23:59:59 2012 GMT',
- 'notBefore': 'May 26 00:00:00 2010 GMT',
- 'serialNumber': '53D2BEF924A7245E83CA01E46CAA2477',
- 'subject': ((('1.3.6.1.4.1.311.60.2.1.3', 'US'),),
- (('1.3.6.1.4.1.311.60.2.1.2', 'Delaware'),),
- (('businessCategory', 'V1.0, Clause 5.(b)'),),
- (('serialNumber', '2497886'),),
- (('countryName', 'US'),),
- (('postalCode', '94043'),),
- (('stateOrProvinceName', 'California'),),
- (('localityName', 'Mountain View'),),
- (('streetAddress', '487 East Middlefield Road'),),
- (('organizationName', 'VeriSign, Inc.'),),
- (('organizationalUnitName', ' Production Security Services'),),
- (('commonName', 'www.verisign.com'),)),
- 'subjectAltName': (('DNS', 'www.verisign.com'),
- ('DNS', 'verisign.com'),
- ('DNS', 'www.verisign.net'),
- ('DNS', 'verisign.net'),
- ('DNS', 'www.verisign.mobi'),
- ('DNS', 'verisign.mobi'),
- ('DNS', 'www.verisign.eu'),
- ('DNS', 'verisign.eu')),
- 'version': 3}
+This example creates a SSL context with the recommended security settings
+for client sockets, including automatic certificate verification::
+
+ >>> context = ssl.create_default_context()
-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)::
+If you prefer to tune security settings yourself, you might create
+a context from scratch (but beware that you might not get the settings
+right)::
>>> context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
>>> context.verify_mode = ssl.CERT_REQUIRED
+ >>> context.check_hostname = True
>>> 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)
+(this snippet assumes 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_REQUIRED`
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))
+ >>> conn = context.wrap_socket(socket.socket(socket.AF_INET),
+ ... server_hostname="www.python.org")
+ >>> conn.connect(("www.python.org", 443))
-You should then fetch the certificate and check its fields for conformity::
+You may then fetch the certificate::
>>> cert = conn.getpeercert()
- >>> ssl.match_hostname(cert, "linuxfr.org")
Visual inspection shows that the certificate does identify the desired service
-(that is, the HTTPS host ``linuxfr.org``)::
+(that is, the HTTPS host ``www.python.org``)::
>>> pprint.pprint(cert)
- {'issuer': ((('organizationName', 'CAcert Inc.'),),
- (('organizationalUnitName', 'http://www.CAcert.org'),),
- (('commonName', 'CAcert Class 3 Root'),)),
- 'notAfter': 'Jun 7 21:02:24 2013 GMT',
- 'notBefore': 'Jun 8 21:02:24 2011 GMT',
- 'serialNumber': 'D3E9',
- 'subject': ((('commonName', 'linuxfr.org'),),),
- 'subjectAltName': (('DNS', 'linuxfr.org'),
- ('othername', '<unsupported>'),
- ('DNS', 'linuxfr.org'),
- ('othername', '<unsupported>'),
- ('DNS', 'dev.linuxfr.org'),
- ('othername', '<unsupported>'),
- ('DNS', 'prod.linuxfr.org'),
- ('othername', '<unsupported>'),
- ('DNS', 'alpha.linuxfr.org'),
- ('othername', '<unsupported>'),
- ('DNS', '*.linuxfr.org'),
- ('othername', '<unsupported>')),
+ {'OCSP': ('http://ocsp.digicert.com',),
+ 'caIssuers': ('http://cacerts.digicert.com/DigiCertSHA2ExtendedValidationServerCA.crt',),
+ 'crlDistributionPoints': ('http://crl3.digicert.com/sha2-ev-server-g1.crl',
+ 'http://crl4.digicert.com/sha2-ev-server-g1.crl'),
+ 'issuer': ((('countryName', 'US'),),
+ (('organizationName', 'DigiCert Inc'),),
+ (('organizationalUnitName', 'www.digicert.com'),),
+ (('commonName', 'DigiCert SHA2 Extended Validation Server CA'),)),
+ 'notAfter': 'Sep 9 12:00:00 2016 GMT',
+ 'notBefore': 'Sep 5 00:00:00 2014 GMT',
+ 'serialNumber': '01BB6F00122B177F36CAB49CEA8B6B26',
+ 'subject': ((('businessCategory', 'Private Organization'),),
+ (('1.3.6.1.4.1.311.60.2.1.3', 'US'),),
+ (('1.3.6.1.4.1.311.60.2.1.2', 'Delaware'),),
+ (('serialNumber', '3359300'),),
+ (('streetAddress', '16 Allen Rd'),),
+ (('postalCode', '03894-4801'),),
+ (('countryName', 'US'),),
+ (('stateOrProvinceName', 'NH'),),
+ (('localityName', 'Wolfeboro,'),),
+ (('organizationName', 'Python Software Foundation'),),
+ (('commonName', 'www.python.org'),)),
+ 'subjectAltName': (('DNS', 'www.python.org'),
+ ('DNS', 'python.org'),
+ ('DNS', 'pypi.python.org'),
+ ('DNS', 'docs.python.org'),
+ ('DNS', 'testpypi.python.org'),
+ ('DNS', 'bugs.python.org'),
+ ('DNS', 'wiki.python.org'),
+ ('DNS', 'hg.python.org'),
+ ('DNS', 'mail.python.org'),
+ ('DNS', 'packaging.python.org'),
+ ('DNS', 'pythonhosted.org'),
+ ('DNS', 'www.pythonhosted.org'),
+ ('DNS', 'test.pythonhosted.org'),
+ ('DNS', 'us.pycon.org'),
+ ('DNS', 'id.python.org')),
'version': 3}
-Now that you are assured of its authenticity, you can proceed to talk with
-the server::
+Now the SSL channel is established and the certificate verified, you can
+proceed to talk with the server::
>>> conn.sendall(b"HEAD / HTTP/1.0\r\nHost: linuxfr.org\r\n\r\n")
>>> pprint.pprint(conn.recv(1024).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'HTTP/1.1 200 OK',
+ b'Date: Sat, 18 Oct 2014 18:27:20 GMT',
+ b'Server: nginx',
+ b'Content-Type: text/html; charset=utf-8',
+ b'X-Frame-Options: SAMEORIGIN',
+ b'Content-Length: 45679',
+ b'Accept-Ranges: bytes',
+ b'Via: 1.1 varnish',
+ b'Age: 2188',
+ b'X-Served-By: cache-lcy1134-LCY',
+ b'X-Cache: HIT',
+ b'X-Cache-Hits: 11',
+ b'Vary: Cookie',
+ b'Strict-Transport-Security: max-age=63072000; includeSubDomains',
b'Connection: close',
- b'Content-Type: text/html; charset=iso-8859-1',
b'',
b'']
@@ -1603,7 +1581,7 @@ waiting for clients to connect::
import socket, ssl
- context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
+ context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile="mycertfile", keyfile="mykeyfile")
bindsocket = socket.socket()
@@ -1764,16 +1742,18 @@ to specify :const:`CERT_REQUIRED` and similarly check the client certificate.
Protocol versions
'''''''''''''''''
-SSL version 2 is considered insecure and is therefore dangerous to use. If
-you want maximum compatibility between clients and servers, it is recommended
-to use :const:`PROTOCOL_SSLv23` as the protocol version and then disable
-SSLv2 explicitly using the :data:`SSLContext.options` attribute::
+SSL versions 2 and 3 are considered insecure and are therefore dangerous to
+use. If you want maximum compatibility between clients and servers, it is
+recommended to use :const:`PROTOCOL_SSLv23` as the protocol version and then
+disable SSLv2 and SSLv3 explicitly using the :data:`SSLContext.options`
+attribute::
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.options |= ssl.OP_NO_SSLv2
+ context.options |= ssl.OP_NO_SSLv3
-The SSL context created above will allow SSLv3 and TLSv1 (and later, if
-supported by your system) connections, but not SSLv2.
+The SSL context created above will only allow TLSv1 and later (if
+supported by your system) connections.
Cipher selection
''''''''''''''''