diff -r fcf45ec7863e Lib/http/client.py --- a/Lib/http/client.py Mon Sep 15 23:50:44 2014 +1200 +++ b/Lib/http/client.py Tue Sep 16 00:28:49 2014 +1200 @@ -1203,7 +1203,7 @@ self.key_file = key_file self.cert_file = cert_file if context is None: - context = ssl._create_stdlib_context() + context = ssl._create_default_https_context() will_verify = context.verify_mode != ssl.CERT_NONE if check_hostname is None: check_hostname = will_verify diff -r fcf45ec7863e Lib/ssl.py --- a/Lib/ssl.py Mon Sep 15 23:50:44 2014 +1200 +++ b/Lib/ssl.py Tue Sep 16 00:28:49 2014 +1200 @@ -442,8 +442,7 @@ context.load_default_certs(purpose) return context - -def _create_stdlib_context(protocol=PROTOCOL_SSLv23, *, cert_reqs=None, +def _create_unverified_context(protocol=PROTOCOL_SSLv23, *, cert_reqs=None, check_hostname=False, purpose=Purpose.SERVER_AUTH, certfile=None, keyfile=None, cafile=None, capath=None, cadata=None): @@ -481,6 +480,17 @@ return context +# PEP 476 target for monkeypatching hack that reverts to old behaviour +_create_default_https_context = create_default_context +# To revert back to the old behaviour, monkeypatch the ssl module: +# ssl._create_default_https_context = ssl._create_unverified_context + + +# Minimise impact of PEP 476 patch on other modules in 3.4 and 2.7 +# by providing a backwards compatibility alias for the old private name +_create_stdlib_context = _create_unverified_context + + class SSLSocket(socket): """This class implements a subtype of socket.socket that wraps the underlying OS socket in an SSL context when necessary, and diff -r fcf45ec7863e Lib/test/test_httplib.py --- a/Lib/test/test_httplib.py Mon Sep 15 23:50:44 2014 +1200 +++ b/Lib/test/test_httplib.py Tue Sep 16 00:28:49 2014 +1200 @@ -778,14 +778,35 @@ self.assertIn('Apache', server_string) def test_networked(self): - # Default settings: no cert verification is done + # Default settings: requires a valid cert from a trusted CA + import ssl support.requires('network') with support.transient_internet('svn.python.org'): h = client.HTTPSConnection('svn.python.org', 443) + with self.assertRaises(ssl.SSLError): + h.request('GET', '/') + + def test_networked_noverification(self): + # Switch off cert verification + import ssl + support.requires('network') + with support.transient_internet('svn.python.org'): + context = ssl._create_unverified_context() + h = client.HTTPSConnection('svn.python.org', 443, context=context) h.request('GET', '/') resp = h.getresponse() self._check_svn_python_org(resp) + def test_networked_trusted_by_default_cert(self): + # Default settings: requires a valid cert from a trusted CA + support.requires('network') + with support.transient_internet('www.python.org'): + h = client.HTTPSConnection('www.python.org', 443) + h.request('GET', '/') + resp = h.getresponse() + content_type = resp.getheader('content-type') + self.assertIn('text/html', content_type) + def test_networked_good_cert(self): # We feed a CA cert that validates the server's cert import ssl @@ -811,6 +832,15 @@ with self.assertRaises(ssl.SSLError): h.request('GET', '/') + def test_local_unknown_cert(self): + # The custom cert isn't known to the default trust bundle + import ssl + server = self.make_server(CERT_localhost) + h = client.HTTPSConnection('localhost', server.port) + with self.assertRaises(ssl.SSLError): + h.request('GET', '/') + del server + def test_local_good_hostname(self): # The (valid) cert validates the HTTP hostname import ssl