HTTPSConnection: prefer the context's check_hostname attribute over the constructor parameter (#22959)

This commit is contained in:
Benjamin Peterson 2014-12-07 13:18:25 -05:00
parent b92fd01189
commit a090f01bb6
4 changed files with 22 additions and 10 deletions

View File

@ -69,17 +69,12 @@ The module provides the following classes:
*key_file* and *cert_file* are deprecated, please use *key_file* and *cert_file* are deprecated, please use
:meth:`ssl.SSLContext.load_cert_chain` instead, or let :meth:`ssl.SSLContext.load_cert_chain` instead, or let
:func:`ssl.create_default_context` select the system's trusted CA :func:`ssl.create_default_context` select the system's trusted CA
certificates for you. certificates for you. The *check_hostname* parameter is also deprecated; the
:attr:`SSLContext.check_hostname` attribute of *context* should be used
instead.
Please read :ref:`ssl-security` for more information on best practices. Please read :ref:`ssl-security` for more information on best practices.
.. note::
If *context* is specified and has a :attr:`~ssl.SSLContext.verify_mode`
of either :data:`~ssl.CERT_OPTIONAL` or :data:`~ssl.CERT_REQUIRED`, then
by default *host* is matched against the host name(s) allowed by the
server's certificate. If you want to change that behaviour, you can
explicitly set *check_hostname* to False.
.. versionchanged:: 3.2 .. versionchanged:: 3.2
*source_address*, *context* and *check_hostname* were added. *source_address*, *context* and *check_hostname* were added.

View File

@ -1210,8 +1210,8 @@ else:
context = ssl._create_default_https_context() context = ssl._create_default_https_context()
will_verify = context.verify_mode != ssl.CERT_NONE will_verify = context.verify_mode != ssl.CERT_NONE
if check_hostname is None: if check_hostname is None:
check_hostname = will_verify check_hostname = context.check_hostname
elif check_hostname and not will_verify: if check_hostname and not will_verify:
raise ValueError("check_hostname needs a SSL context with " raise ValueError("check_hostname needs a SSL context with "
"either CERT_OPTIONAL or CERT_REQUIRED") "either CERT_OPTIONAL or CERT_REQUIRED")
if key_file or cert_file: if key_file or cert_file:

View File

@ -882,6 +882,7 @@ class HTTPSTest(TestCase):
server = self.make_server(CERT_fakehostname) server = self.make_server(CERT_fakehostname)
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
context.verify_mode = ssl.CERT_REQUIRED context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
context.load_verify_locations(CERT_fakehostname) context.load_verify_locations(CERT_fakehostname)
h = client.HTTPSConnection('localhost', server.port, context=context) h = client.HTTPSConnection('localhost', server.port, context=context)
with self.assertRaises(ssl.CertificateError): with self.assertRaises(ssl.CertificateError):
@ -892,11 +893,24 @@ class HTTPSTest(TestCase):
with self.assertRaises(ssl.CertificateError): with self.assertRaises(ssl.CertificateError):
h.request('GET', '/') h.request('GET', '/')
# With check_hostname=False, the mismatching is ignored # With check_hostname=False, the mismatching is ignored
context.check_hostname = False
h = client.HTTPSConnection('localhost', server.port, context=context, h = client.HTTPSConnection('localhost', server.port, context=context,
check_hostname=False) check_hostname=False)
h.request('GET', '/nonexistent') h.request('GET', '/nonexistent')
resp = h.getresponse() resp = h.getresponse()
self.assertEqual(resp.status, 404) self.assertEqual(resp.status, 404)
# The context's check_hostname setting is used if one isn't passed to
# HTTPSConnection.
context.check_hostname = False
h = client.HTTPSConnection('localhost', server.port, context=context)
h.request('GET', '/nonexistent')
self.assertEqual(h.getresponse().status, 404)
# Passing check_hostname to HTTPSConnection should override the
# context's setting.
h = client.HTTPSConnection('localhost', server.port, context=context,
check_hostname=True)
with self.assertRaises(ssl.CertificateError):
h.request('GET', '/')
@unittest.skipIf(not hasattr(client, 'HTTPSConnection'), @unittest.skipIf(not hasattr(client, 'HTTPSConnection'),
'http.client.HTTPSConnection not available') 'http.client.HTTPSConnection not available')

View File

@ -39,6 +39,9 @@ Core and Builtins
Library Library
------- -------
- Issue #22959: In the constructor of http.client.HTTPSConnection, prefer the
context's check_hostname attribute over the *check_hostname* parameter.
- Issue #16043: Add a default limit for the amount of data xmlrpclib.gzip_decode - Issue #16043: Add a default limit for the amount of data xmlrpclib.gzip_decode
will return. This resolves CVE-2013-1753. will return. This resolves CVE-2013-1753.