Skip to content

TLS 1.3 Post Handshake Auth no longer working with urllib 2.1.0 when ignoring cert validation #3325

@jborean93

Description

@jborean93

Subject

The change ae06688#diff-f2922ee77cbe0497677cfadf8dff15456050c6670d37d012c9416f37970f0d13R324-R330 introduced when Python 3.7 support was dropped broke TLS 1.3 post_handshake_auth support when a context that was not verifying the server's certificate was being set. Previously the check was

if (cert_reqs == ssl.CERT_REQUIRED or sys.version_info >= (3, 7, 4)) and getattr(
    context, "post_handshake_auth", None
) is not None:
    context.post_handshake_auth = True

Which meant that context.post_handshake_auth was being set if Python 3.7.4 or newer was being used regardless of the cert_reqs value. With the change in the linked commit the check is now

if (
    cert_reqs == ssl.CERT_REQUIRED
    and getattr(context, "post_handshake_auth", None) is not None
):
    context.post_handshake_auth = True

This means it's now only being set if cert_reqs == ssl.CERT_REQUIRED so using ssl.CERT_NONE to ignore the cert checks breaks this setting. Now that Python 3.8 is the baseline you can just have the context.post_handshake_auth is not None

Edit: ignore that, looks like SSLContext from pyOpenSSL can be used in some scenario which does not have this attribute so the getattr is still needed.

See diyan/pywinrm#376 (comment) for more info.

Environment

Describe your environment.
At least, paste here the output of:

import platform
import ssl
import urllib3

print("OS", platform.platform())
print("Python", platform.python_version())
print(ssl.OPENSSL_VERSION)
print("urllib3", urllib3.__version__)
OS Linux-6.7.1-arch1-1-x86_64-with-glibc2.38
>>> print("Python", platform.python_version())
Python 3.12.0
>>> print(ssl.OPENSSL_VERSION)
OpenSSL 3.2.0 23 Nov 2023
>>> print("urllib3", urllib3.__version__)
urllib3 2.1.0

Steps to Reproduce

I unfortunately don't know of a simple web server that provides PHA with TLS 1.3. My tests are against a Windows host with WinRM and Certificate auth which isn't the simplest to setup.

Expected Behavior

Authentication works

Actual Behavior

Authentication fails and the TLS socket is closed by the server because it never receives a certificate from the client.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions