Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-94172: urllib.request avoids deprecated check_hostname #94193

Merged
merged 1 commit into from
Jun 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions Lib/http/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,20 @@ def getcode(self):
'''
return self.status


def _create_https_context(http_version):
# Function also used by urllib.request to be able to set the check_hostname
# attribute on a context object.
context = ssl._create_default_https_context()
# send ALPN extension to indicate HTTP/1.1 protocol
if http_version == 11:
context.set_alpn_protocols(['http/1.1'])
# enable PHA for TLS 1.3 connections if available
if context.post_handshake_auth is not None:
context.post_handshake_auth = True
return context


class HTTPConnection:

_http_vsn = 11
Expand Down Expand Up @@ -1418,28 +1432,16 @@ def __init__(self, host, port=None, key_file=None, cert_file=None,
self.key_file = key_file
self.cert_file = cert_file
if context is None:
context = ssl._create_default_https_context()
# send ALPN extension to indicate HTTP/1.1 protocol
if self._http_vsn == 11:
context.set_alpn_protocols(['http/1.1'])
# enable PHA for TLS 1.3 connections if available
if context.post_handshake_auth is not None:
context.post_handshake_auth = True
will_verify = context.verify_mode != ssl.CERT_NONE
if check_hostname is None:
check_hostname = context.check_hostname
if check_hostname and not will_verify:
raise ValueError("check_hostname needs a SSL context with "
"either CERT_OPTIONAL or CERT_REQUIRED")
context = _create_https_context(self._http_vsn)
if check_hostname is not None:
context.check_hostname = check_hostname
if key_file or cert_file:
context.load_cert_chain(cert_file, key_file)
# cert and key file means the user wants to authenticate.
# enable TLS 1.3 PHA implicitly even for custom contexts.
if context.post_handshake_auth is not None:
context.post_handshake_auth = True
self._context = context
if check_hostname is not None:
self._context.check_hostname = check_hostname

def connect(self):
"Connect to a host on a given (SSL) port."
Expand Down
8 changes: 6 additions & 2 deletions Lib/urllib/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -1383,12 +1383,16 @@ class HTTPSHandler(AbstractHTTPHandler):

def __init__(self, debuglevel=0, context=None, check_hostname=None):
AbstractHTTPHandler.__init__(self, debuglevel)
if context is None:
http_version = http.client.HTTPSConnection._http_vsn
context = http.client._create_https_context(http_version)
if check_hostname is not None:
context.check_hostname = check_hostname
self._context = context
self._check_hostname = check_hostname

def https_open(self, req):
return self.do_open(http.client.HTTPSConnection, req,
context=self._context, check_hostname=self._check_hostname)
context=self._context)

https_request = AbstractHTTPHandler.do_request_

Expand Down