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-80192: Use windows api if ssl cert verification fails #127622

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

tobil4sk
Copy link

@tobil4sk tobil4sk commented Dec 5, 2024

This avoids rejecting certificates that should be accepted, see #80192.

Here is the relevant openssl documentation: https://docs.openssl.org/master/man3/SSL_CTX_set_verify/.

Also, here are the windows api docs:

I've been testing manually by deleting DigiCert Global Root G2 from Third Party Root Certificates in the user certificate store (this is safe, the certificate will be added back automatically), and running the following code:

import http.client
conn = http.client.HTTPSConnection("www.verisign.com")
conn.request("GET", "/")
conn.close()

The main branch errors with:

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1025)

Whereas with this patch, the certificate is verified and the connection is established.

This avoids rejecting certificates that should be accepted, see python#80192
Copy link

cpython-cla-bot bot commented Dec 5, 2024

All commit authors signed the Contributor License Agreement.
CLA signed

@asvetlov
Copy link
Contributor

asvetlov commented Dec 5, 2024

Such change requires some tests at least I guess.

Copy link
Member

@ZeroIntensity ZeroIntensity left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this needs a test. FYI, test_ssl is failing.

@@ -0,0 +1 @@
Fixed valid ssl certificates being rejected.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use a reference:

Suggested change
Fixed valid ssl certificates being rejected.
Fixed valid :mod:`ssl` certificates being rejected.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reference added

Copy link
Contributor

@asvetlov asvetlov Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would see a broader text, e.g. the PR verifies certifications rejected by OpenSSL by additional calls to Windows specific API functions.
The exact proposed text is definitely not fine, but you have got my idea.

return NULL;
}

cert_bytes = PyMem_RawMalloc(cert_bytes_length);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use pymalloc (PyMem_Malloc) here? Typically, we only need RawMalloc if we plan on using it inside Py_BEGIN_ALLOW_THREADS areas.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using PyMem_Malloc I got the following error in my sample program:
Fatal Python error: _PyMem_DebugMalloc: Python memory allocator called without holding the GIL

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured. It might be worth adding a comment mentioning that the GIL isn't held (so no Python APIs can get called).

Modules/_ssl.c Outdated Show resolved Hide resolved
Modules/_ssl.c Outdated
Comment on lines 3088 to 3090
case CERT_E_WRONG_USAGE:
case CERT_E_CRITICAL:
case CERT_E_PURPOSE:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a chance we need to use _Py_FALLTHROUGH here, but it looks like build isn't complaining. If it does start failing feel free to use that.

CERT_E_UNTRUSTEDROOT:
A certification chain processed correctly but terminated in a root
certificate that is not trusted by the trust provider.

X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
The issuer certificate could not be found: this occurs if the issuer
certificate of an untrusted certificate cannot be found.

- https://docs.openssl.org/master/man3/X509_STORE_CTX_get_error/#error-codes
- https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cert_chain_policy_status#members
Modules/_ssl.c Show resolved Hide resolved
@tobil4sk
Copy link
Author

tobil4sk commented Dec 5, 2024

Such change requires some tests at least I guess.

Ok, I'll have to look into how to create a sample certificate chain that reproduces the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants