|
|
b9ffd2 |
diff --git a/Doc/library/http.client.rst b/Doc/library/http.client.rst
|
|
|
b9ffd2 |
index 2f59ece..d756916 100644
|
|
|
b9ffd2 |
--- a/Doc/library/http.client.rst
|
|
|
b9ffd2 |
+++ b/Doc/library/http.client.rst
|
|
|
b9ffd2 |
@@ -88,6 +88,11 @@ The module provides the following classes:
|
|
|
b9ffd2 |
:func:`ssl._create_unverified_context` can be passed to the *context*
|
|
|
b9ffd2 |
parameter.
|
|
|
b9ffd2 |
|
|
|
b9ffd2 |
+ .. versionchanged:: 3.7.4
|
|
|
b9ffd2 |
+ This class now enables TLS 1.3
|
|
|
b9ffd2 |
+ :attr:`ssl.SSLContext.post_handshake_auth` for the default *context* or
|
|
|
b9ffd2 |
+ when *cert_file* is passed with a custom *context*.
|
|
|
b9ffd2 |
+
|
|
|
b9ffd2 |
.. deprecated:: 3.6
|
|
|
b9ffd2 |
|
|
|
b9ffd2 |
*key_file* and *cert_file* are deprecated in favor of *context*.
|
|
|
b9ffd2 |
diff --git a/Lib/http/client.py b/Lib/http/client.py
|
|
|
b9ffd2 |
index 1a6bd8a..f0d2642 100644
|
|
|
b9ffd2 |
--- a/Lib/http/client.py
|
|
|
b9ffd2 |
+++ b/Lib/http/client.py
|
|
|
b9ffd2 |
@@ -1390,6 +1390,9 @@ else:
|
|
|
b9ffd2 |
self.cert_file = cert_file
|
|
|
b9ffd2 |
if context is None:
|
|
|
b9ffd2 |
context = ssl._create_default_https_context()
|
|
|
b9ffd2 |
+ # enable PHA for TLS 1.3 connections if available
|
|
|
b9ffd2 |
+ if context.post_handshake_auth is not None:
|
|
|
b9ffd2 |
+ context.post_handshake_auth = True
|
|
|
b9ffd2 |
will_verify = context.verify_mode != ssl.CERT_NONE
|
|
|
b9ffd2 |
if check_hostname is None:
|
|
|
b9ffd2 |
check_hostname = context.check_hostname
|
|
|
b9ffd2 |
@@ -1398,6 +1401,10 @@ else:
|
|
|
b9ffd2 |
"either CERT_OPTIONAL or CERT_REQUIRED")
|
|
|
b9ffd2 |
if key_file or cert_file:
|
|
|
b9ffd2 |
context.load_cert_chain(cert_file, key_file)
|
|
|
b9ffd2 |
+ # cert and key file means the user wants to authenticate.
|
|
|
b9ffd2 |
+ # enable TLS 1.3 PHA implicitly even for custom contexts.
|
|
|
b9ffd2 |
+ if context.post_handshake_auth is not None:
|
|
|
b9ffd2 |
+ context.post_handshake_auth = True
|
|
|
b9ffd2 |
self._context = context
|
|
|
b9ffd2 |
self._check_hostname = check_hostname
|
|
|
b9ffd2 |
|
|
|
b9ffd2 |
diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
|
|
|
b9ffd2 |
index 714d521..5795b7a 100644
|
|
|
b9ffd2 |
--- a/Lib/test/test_httplib.py
|
|
|
b9ffd2 |
+++ b/Lib/test/test_httplib.py
|
|
|
b9ffd2 |
@@ -1709,6 +1709,24 @@ class HTTPSTest(TestCase):
|
|
|
b9ffd2 |
self.assertEqual(h, c.host)
|
|
|
b9ffd2 |
self.assertEqual(p, c.port)
|
|
|
b9ffd2 |
|
|
|
b9ffd2 |
+ def test_tls13_pha(self):
|
|
|
b9ffd2 |
+ import ssl
|
|
|
b9ffd2 |
+ if not ssl.HAS_TLSv1_3:
|
|
|
b9ffd2 |
+ self.skipTest('TLS 1.3 support required')
|
|
|
b9ffd2 |
+ # just check status of PHA flag
|
|
|
b9ffd2 |
+ h = client.HTTPSConnection('localhost', 443)
|
|
|
b9ffd2 |
+ self.assertTrue(h._context.post_handshake_auth)
|
|
|
b9ffd2 |
+
|
|
|
b9ffd2 |
+ context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
|
|
b9ffd2 |
+ self.assertFalse(context.post_handshake_auth)
|
|
|
b9ffd2 |
+ h = client.HTTPSConnection('localhost', 443, context=context)
|
|
|
b9ffd2 |
+ self.assertIs(h._context, context)
|
|
|
b9ffd2 |
+ self.assertFalse(h._context.post_handshake_auth)
|
|
|
b9ffd2 |
+
|
|
|
b9ffd2 |
+ h = client.HTTPSConnection('localhost', 443, context=context,
|
|
|
b9ffd2 |
+ cert_file=CERT_localhost)
|
|
|
b9ffd2 |
+ self.assertTrue(h._context.post_handshake_auth)
|
|
|
b9ffd2 |
+
|
|
|
b9ffd2 |
|
|
|
b9ffd2 |
class RequestBodyTest(TestCase):
|
|
|
b9ffd2 |
"""Test cases where a request includes a message body."""
|