diff options
author | Benjamin Peterson <benjamin@python.org> | 2014-11-23 17:42:45 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2014-11-23 17:42:45 (GMT) |
commit | fcfb18ee2b754368ff005a3fec8a9fe7930ccf7d (patch) | |
tree | d0ec3069e6f10073b55fca4ebf710a8da6123b1f /Lib/httplib.py | |
parent | 5f6b89bda3cc9797186c567b6be5c6d8feedb3ec (diff) | |
download | cpython-fcfb18ee2b754368ff005a3fec8a9fe7930ccf7d.zip cpython-fcfb18ee2b754368ff005a3fec8a9fe7930ccf7d.tar.gz cpython-fcfb18ee2b754368ff005a3fec8a9fe7930ccf7d.tar.bz2 |
allow passing cert/ssl information to urllib2.urlopen and httplib.HTTPSConnection
This is basically a backport of issues #9003 and #22366.
Diffstat (limited to 'Lib/httplib.py')
-rw-r--r-- | Lib/httplib.py | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/Lib/httplib.py b/Lib/httplib.py index b2f6e5c..db5fa37 100644 --- a/Lib/httplib.py +++ b/Lib/httplib.py @@ -1187,21 +1187,44 @@ else: def __init__(self, host, port=None, key_file=None, cert_file=None, strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, - source_address=None): + source_address=None, context=None, check_hostname=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_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." - sock = self._create_connection((self.host, self.port), - self.timeout, self.source_address) + HTTPConnection.connect(self) + if self._tunnel_host: - self.sock = sock - self._tunnel() - self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file) + server_hostname = self._tunnel_host + else: + server_hostname = self.host + sni_hostname = server_hostname if ssl.HAS_SNI else None + + self.sock = self._context.wrap_socket(self.sock, + server_hostname=sni_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") |