]> granicus.if.org Git - python/commitdiff
bpo-37440: Enable TLS 1.3 post-handshake auth in http.client (GH-14448)
authorChristian Heimes <christian@python.org>
Mon, 1 Jul 2019 06:32:24 +0000 (08:32 +0200)
committerMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 1 Jul 2019 06:32:24 +0000 (23:32 -0700)
Post-handshake authentication is required for conditional client cert authentication with TLS 1.3.

https://bugs.python.org/issue37440

Doc/library/http.client.rst
Lib/http/client.py
Lib/test/test_httplib.py
Misc/NEWS.d/next/Library/2019-06-28-16-40-17.bpo-37440.t3wX-N.rst [new file with mode: 0644]

index beaa720d732b4cc1cad99123d8b9f3b11618ae4f..4e761cd39a0109369a4f9de489569068a35a8001 100644 (file)
@@ -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*.
index 82908ebe3afd65d5109d3e285960f347154483a2..f61267e108a52494665ccc08a50486020d157a1a 100644 (file)
@@ -1358,6 +1358,9 @@ else:
             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 @@ else:
                                  "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
index 968cbd86a1e426ac80df0f27f0d6c377c3596a9b..9148169cc7c2e571fd08e6f736e2458175e8f90b 100644 (file)
@@ -1745,6 +1745,24 @@ class HTTPSTest(TestCase):
             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 (file)
index 0000000..b336e06
--- /dev/null
@@ -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.