changeset: 93772:41021c771510 branch: 2.7 parent: 93766:f18b37befb6c user: Benjamin Peterson date: Sun Dec 07 13:41:26 2014 -0500 files: Doc/library/httplib.rst Lib/httplib.py Lib/test/data/README Lib/test/test_httplib.py Lib/urllib2.py Misc/NEWS description: remove HTTPSConnection's check_hostname parameter (#22959) diff -r f18b37befb6c -r 41021c771510 Doc/library/httplib.rst --- a/Doc/library/httplib.rst Sat Dec 06 11:36:32 2014 -0500 +++ b/Doc/library/httplib.rst Sun Dec 07 13:41:26 2014 -0500 @@ -70,7 +70,7 @@ *source_address* was added. -.. class:: HTTPSConnection(host[, port[, key_file[, cert_file[, strict[, timeout[, source_address, context, check_hostname]]]]]]) +.. class:: HTTPSConnection(host[, port[, key_file[, cert_file[, strict[, timeout[, source_address[, context]]]]]]]) A subclass of :class:`HTTPConnection` that uses SSL for communication with secure servers. Default port is ``443``. If *context* is specified, it must @@ -83,13 +83,6 @@ 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. - .. versionadded:: 2.0 .. versionchanged:: 2.6 @@ -99,7 +92,7 @@ *source_address* was added. .. versionchanged:: 2.7.9 - *context* and *check_hostname* was added. + *context* was added. This class now performs all the necessary certificate and hostname checks by default. To revert to the previous, unverified, behavior diff -r f18b37befb6c -r 41021c771510 Lib/httplib.py --- a/Lib/httplib.py Sat Dec 06 11:36:32 2014 -0500 +++ b/Lib/httplib.py Sun Dec 07 13:41:26 2014 -0500 @@ -1187,23 +1187,16 @@ def __init__(self, host, port=None, key_file=None, cert_file=None, strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, - source_address=None, context=None, check_hostname=None): + source_address=None, context=None): HTTPConnection.__init__(self, host, port, strict, timeout, source_address) self.key_file = key_file self.cert_file = cert_file if context is None: context = ssl._create_default_https_context() - will_verify = context.verify_mode != ssl.CERT_NONE - if check_hostname is None: - check_hostname = will_verify - elif check_hostname and not will_verify: - raise ValueError("check_hostname needs a SSL context with " - "either CERT_OPTIONAL or CERT_REQUIRED") if key_file or cert_file: context.load_cert_chain(cert_file, key_file) self._context = context - self._check_hostname = check_hostname def connect(self): "Connect to a host on a given (SSL) port." @@ -1217,13 +1210,6 @@ self.sock = self._context.wrap_socket(self.sock, server_hostname=server_hostname) - if not self._context.check_hostname and self._check_hostname: - try: - ssl.match_hostname(self.sock.getpeercert(), server_hostname) - except Exception: - self.sock.shutdown(socket.SHUT_RDWR) - self.sock.close() - raise __all__.append("HTTPSConnection") diff -r f18b37befb6c -r 41021c771510 Lib/test/data/README --- a/Lib/test/data/README Sat Dec 06 11:36:32 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -This empty directory serves as destination for temporary files -created by some tests. diff -r f18b37befb6c -r 41021c771510 Lib/test/test_httplib.py --- a/Lib/test/test_httplib.py Sat Dec 06 11:36:32 2014 -0500 +++ b/Lib/test/test_httplib.py Sun Dec 07 13:41:26 2014 -0500 @@ -616,18 +616,15 @@ server = self.make_server(CERT_fakehostname) context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) context.verify_mode = ssl.CERT_REQUIRED + context.check_hostname = True context.load_verify_locations(CERT_fakehostname) h = httplib.HTTPSConnection('localhost', server.port, context=context) with self.assertRaises(ssl.CertificateError): h.request('GET', '/') - # Same with explicit check_hostname=True - h = httplib.HTTPSConnection('localhost', server.port, context=context, - check_hostname=True) - with self.assertRaises(ssl.CertificateError): - h.request('GET', '/') - # With check_hostname=False, the mismatching is ignored - h = httplib.HTTPSConnection('localhost', server.port, context=context, - check_hostname=False) + h.close() + # With context.check_hostname=False, the mismatching is ignored + context.check_hostname = False + h = httplib.HTTPSConnection('localhost', server.port, context=context) h.request('GET', '/nonexistent') resp = h.getresponse() self.assertEqual(resp.status, 404) diff -r f18b37befb6c -r 41021c771510 Lib/urllib2.py --- a/Lib/urllib2.py Sat Dec 06 11:36:32 2014 -0500 +++ b/Lib/urllib2.py Sun Dec 07 13:41:26 2014 -0500 @@ -139,10 +139,10 @@ ) if not _have_ssl: raise ValueError('SSL support not available') - context = ssl._create_stdlib_context(cert_reqs=ssl.CERT_REQUIRED, + context = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH, cafile=cafile, capath=capath) - https_handler = HTTPSHandler(context=context, check_hostname=True) + https_handler = HTTPSHandler(context=context) opener = build_opener(https_handler) elif context: https_handler = HTTPSHandler(context=context) @@ -1231,14 +1231,13 @@ if hasattr(httplib, 'HTTPS'): class HTTPSHandler(AbstractHTTPHandler): - def __init__(self, debuglevel=0, context=None, check_hostname=None): + def __init__(self, debuglevel=0, context=None): AbstractHTTPHandler.__init__(self, debuglevel) self._context = context - self._check_hostname = check_hostname def https_open(self, req): return self.do_open(httplib.HTTPSConnection, req, - context=self._context, check_hostname=self._check_hostname) + context=self._context) https_request = AbstractHTTPHandler.do_request_ diff -r f18b37befb6c -r 41021c771510 Misc/NEWS --- a/Misc/NEWS Sat Dec 06 11:36:32 2014 -0500 +++ b/Misc/NEWS Sun Dec 07 13:41:26 2014 -0500 @@ -10,6 +10,9 @@ Library ------- +- Issue #22959: Remove the *check_hostname* parameter of + httplib.HTTPSConnection. The *context* parameter should be used instead. + - Issue #16043: Add a default limit for the amount of data xmlrpclib_gzip_decode will return. This resolves CVE-2013-1753.