[Python-checkins] [3.8] bpo-37440: Enable TLS 1.3 post-handshake auth in http.client (GH-14448) (GH-14495)
Miss Islington (bot)
webhook-mailer at python.org
Mon Jul 1 03:07:50 EDT 2019
https://github.com/python/cpython/commit/ee72dda9616258b57c19eb5af00f3e80a3fb8e22
commit: ee72dda9616258b57c19eb5af00f3e80a3fb8e22
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: GitHub <noreply at github.com>
date: 2019-07-01T00:07:44-07:00
summary:
[3.8] bpo-37440: Enable TLS 1.3 post-handshake auth in http.client (GH-14448) (GH-14495)
Post-handshake authentication is required for conditional client cert authentication with TLS 1.3.
https://bugs.python.org/issue37440
(cherry picked from commit d1bd6e79da1ee56dc1b902d804216ffd267399db)
Co-authored-by: Christian Heimes <christian at python.org>
https://bugs.python.org/issue37440
files:
A Misc/NEWS.d/next/Library/2019-06-28-16-40-17.bpo-37440.t3wX-N.rst
M Doc/library/http.client.rst
M Lib/http/client.py
M Lib/test/test_httplib.py
diff --git a/Doc/library/http.client.rst b/Doc/library/http.client.rst
index beaa720d732b..4e761cd39a01 100644
--- a/Doc/library/http.client.rst
+++ b/Doc/library/http.client.rst
@@ -94,6 +94,11 @@ The module provides the following classes:
:func:`ssl._create_unverified_context` can be passed to the *context*
parameter.
+ .. versionchanged:: 3.8
+ This class now enables TLS 1.3
+ :attr:`ssl.SSLContext.post_handshake_auth` for the default *context* or
+ when *cert_file* is passed with a custom *context*.
+
.. deprecated:: 3.6
*key_file* and *cert_file* are deprecated in favor of *context*.
diff --git a/Lib/http/client.py b/Lib/http/client.py
index 82908ebe3afd..f61267e108a5 100644
--- a/Lib/http/client.py
+++ b/Lib/http/client.py
@@ -1358,6 +1358,9 @@ def __init__(self, host, port=None, key_file=None, cert_file=None,
self.cert_file = cert_file
if context is None:
context = ssl._create_default_https_context()
+ # 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
@@ -1366,6 +1369,10 @@ def __init__(self, host, port=None, key_file=None, cert_file=None,
"either CERT_OPTIONAL or CERT_REQUIRED")
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
diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
index 968cbd86a1e4..9148169cc7c2 100644
--- a/Lib/test/test_httplib.py
+++ b/Lib/test/test_httplib.py
@@ -1745,6 +1745,24 @@ def test_host_port(self):
self.assertEqual(h, c.host)
self.assertEqual(p, c.port)
+ def test_tls13_pha(self):
+ import ssl
+ if not ssl.HAS_TLSv1_3:
+ self.skipTest('TLS 1.3 support required')
+ # just check status of PHA flag
+ h = client.HTTPSConnection('localhost', 443)
+ self.assertTrue(h._context.post_handshake_auth)
+
+ context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
+ self.assertFalse(context.post_handshake_auth)
+ h = client.HTTPSConnection('localhost', 443, context=context)
+ self.assertIs(h._context, context)
+ self.assertFalse(h._context.post_handshake_auth)
+
+ h = client.HTTPSConnection('localhost', 443, context=context,
+ cert_file=CERT_localhost)
+ self.assertTrue(h._context.post_handshake_auth)
+
class RequestBodyTest(TestCase):
"""Test cases where a request includes a message body."""
diff --git a/Misc/NEWS.d/next/Library/2019-06-28-16-40-17.bpo-37440.t3wX-N.rst b/Misc/NEWS.d/next/Library/2019-06-28-16-40-17.bpo-37440.t3wX-N.rst
new file mode 100644
index 000000000000..b336e061e15e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-06-28-16-40-17.bpo-37440.t3wX-N.rst
@@ -0,0 +1,2 @@
+http.client now enables TLS 1.3 post-handshake authentication for default
+context or if a cert_file is passed to HTTPSConnection.
More information about the Python-checkins
mailing list