diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -16,7 +16,8 @@ The :mod:`urllib.request` module defines the following functions: -.. function:: urlopen(url, data=None[, timeout], *, cafile=None, capath=None, cadefault=True) +.. function:: urlopen(url, data=None[, timeout], *, cafile=None, capath=None, \ + cadefault=True, check_hostname=None) Open the URL *url*, which can be either a string or a :class:`Request` object. @@ -58,11 +59,18 @@ *cafile* and *capath* parameters are omitted. This will only work on some non-Windows platforms. + When HTTPS request is performed with server certificate verification using + *cafile*, *capath* or using *cadefault* parameter, the *host* in the request + *url* is matched against the host name allowed by the server's certificate. + *check_hostname* parameter allows you to override this default hostname + match, by setting it to False. + .. warning:: If neither *cafile* nor *capath* is specified, and *cadefault* is False, an HTTPS request will not do any verification of the server's certificate. + For http and https urls, this function returns a :class:`http.client.HTTPResponse` object which has the following :ref:`httpresponse-objects` methods. @@ -109,6 +117,10 @@ .. versionchanged:: 3.3 *cadefault* was added. + .. versionadded:: 3.4 + *check_hostname* was added. + + .. function:: install_opener(opener) Install an :class:`OpenerDirector` instance as the default global opener. diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py --- a/Lib/test/test_urllib2_localnet.py +++ b/Lib/test/test_urllib2_localnet.py @@ -482,6 +482,11 @@ with self.assertRaises(ssl.CertificateError) as cm: self.urlopen("https://localhost:%s/bizarre" % handler.port, cafile=CERT_fakehostname) + # Good cert, mismatching hostname, ignore hostname checking. + data = self.urlopen("https://localhost:%s/bizarre" % handler.port, + cafile=CERT_fakehostname, check_hostname=False) + self.assertEqual(data, b"we care a bit") + def test_https_with_cadefault(self): handler = self.start_https_server(certfile=CERT_localhost) diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -136,7 +136,7 @@ _opener = None def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, - *, cafile=None, capath=None, cadefault=False): + *, cafile=None, capath=None, cadefault=False, check_hostname=None): global _opener if cafile or capath or cadefault: if not _have_ssl: @@ -149,9 +149,8 @@ context.load_verify_locations(cafile, capath) else: context.set_default_verify_paths() - check_hostname = True - else: - check_hostname = False + if check_hostname is None: + check_hostname = True https_handler = HTTPSHandler(context=context, check_hostname=check_hostname) opener = build_opener(https_handler) elif _opener is None: