Skip to content

Commit 79371ba

Browse files
committed
mhr: insert Windows system CAs into SSL context store
Due to changes in PyOpenSSL, the standard Windows CAs are no longer checked by default. Using the standard library's SSL module, enumerate and add them to the trust store for the SSL context.
1 parent 5e1e747 commit 79371ba

File tree

1 file changed

+33
-1
lines changed

1 file changed

+33
-1
lines changed

src/mhr.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
from nehta_signature import NehtaXMLSignature
2828
from datetime import datetime, timezone
2929
import logging
30+
from sys import platform
31+
if platform == "win32":
32+
from ssl import enum_certificates
33+
import OpenSSL.crypto
3034

3135
# Required to make urllib use PyOpenSSL, which supports PKCS#12 handling
3236
urllib3.contrib.pyopenssl.inject_into_urllib3()
@@ -67,6 +71,34 @@ def hpio_from_certificate(certificate):
6771
return hpio, orgname
6872

6973

74+
def setup_certificate_verification(context, logger):
75+
"""Add default verification paths, and on Windows, the system CA stores to a pyOpenSSL context"""
76+
context.set_default_verify_paths()
77+
if platform == "win32":
78+
# The standard library ssl module does this on Windows, but PyOpenSSL does not (yet)
79+
store = context.get_cert_store()
80+
# "ROOT" is the "Trusted Root Certification Authorities", "CA" is the "Intermediate Certification Authorities"
81+
# The Python SSL module loads both, so do the same
82+
for store_name in ("ROOT", "CA"):
83+
for cert_bytes, encoding_type, trust in enum_certificates(store_name):
84+
if encoding_type == "x509_asn":
85+
# Must be trusted for all purposes (True) or for server authentication
86+
if trust == True or "1.3.6.1.5.5.7.3.1" in trust:
87+
try:
88+
# Load as an OpenSSL X509 object rather than a cryptography object which is then converted to OpenSSL.X509
89+
store.add_cert(
90+
OpenSSL.crypto.load_certificate(
91+
OpenSSL.crypto.FILETYPE_ASN1, cert_bytes
92+
)
93+
)
94+
except OpenSSL.crypto.Error as e:
95+
logger.warn("Unable to load system certificate: {e!s}")
96+
else:
97+
logger.warn(
98+
"Unrecognised certificate type ({type}) when importing from system certificate store."
99+
)
100+
101+
70102
class WsaAnonymisePlugin(zeep.plugins.Plugin):
71103
"""Plugin to force the WS-Addressing To: header to the anonymous value
72104
@@ -157,7 +189,7 @@ def __init__(self, cert_file, cert_password, config):
157189
# The standard library's ssl module does not support loading from memory; the only real
158190
# justification is that this is less secure - see https://github.com/python/cpython/issues/129216
159191
ctx = create_urllib3_context()
160-
ctx.set_default_verify_paths()
192+
setup_certificate_verification(ctx._ctx, self.log)
161193
ctx._ctx.use_certificate(cert_cg)
162194
ctx._ctx.use_privatekey(pkcs_cg.key)
163195

0 commit comments

Comments
 (0)