wbond / certvalidator

Python library for validating X.509 certificates and paths
MIT License
107 stars 31 forks source link

Validation fails if subject_alt_name extension is critical #44

Open c0r0n3r opened 1 year ago

c0r0n3r commented 1 year ago

Validation of no-subject.badssl.com certificate chain causes the following Python traceback.

Traceback (most recent call last):
  File "//no-subject.py", line 151, in <module>
    cert_validator.validate_usage(set())
  File "/usr/local/lib/python3.11/site-packages/certvalidator/__init__.py", line 193, in validate_usage
    self._validate_path()
  File "/usr/local/lib/python3.11/site-packages/certvalidator/__init__.py", line 128, in _validate_path
    raise exceptions[0]
  File "/usr/local/lib/python3.11/site-packages/certvalidator/__init__.py", line 121, in _validate_path
    validate_path(self._context, candidate_path)
  File "/usr/local/lib/python3.11/site-packages/certvalidator/validate.py", line 50, in validate_path
    return _validate_path(validation_context, path)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/certvalidator/validate.py", line 684, in _validate_path
    raise PathValidationError(pretty_message(
certvalidator.errors.PathValidationError: The path could not be validated because the end-entity certificate contains the following unsupported critical extension: subject_alt_name

I used the following versions:

You can use the following code to reproduce the issue:

import asn1crypto.pem
import asn1crypto.x509
import certvalidator

NO_SUBJECT_BADSSL_COM_LEAF_CERTIFICATE = asn1crypto.x509.Certificate.load(asn1crypto.pem.unarmor(b"""
 0 s:
   i:C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = UbiquiTLS\\E2\\84\\A2 DV RSA Server CA
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Mar 17 00:00:00 2017 GMT; NotAfter: Jun 16 23:59:59 2020 GMT
-----BEGIN CERTIFICATE-----
MIIGdTCCBV2gAwIBAgIQI+ZPIMN8DYcQH3GS78XTcjANBgkqhkiG9w0BAQsFADCB
gDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJjAkBgNV
BAMMHVViaXF1aVRMU+KEoiBEViBSU0EgU2VydmVyIENBMB4XDTE3MDMxNzAwMDAw
MFoXDTIwMDYxNjIzNTk1OVowADCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAMIE7PiM7gTCs9hQ1XBYzJMY61yoaEmwIrX5lZ6xKyx2PmzAS2BMTOqytMAP
gLaw+XLJhgL5XEFdEyt/ccRLvOmULlA3pmccYYz2QULFRtMWhyefdOsKnRFSJiFz
bIRMeVXk0WvoBj1IFVKtsyjbqv9u/2CVSndrOfEk0TG23U3AxPxTuW1CrbV8/q71
FdIzSOciccfCFHpsKOo3St/qbLVytH5aohbcabFXRNsKEqveww9HdFxBIuGa+RuT
5q0iBikusbpJHAwnnqP7i/dAcgCskgjZjFeEU4EFy+b+a1SYQCeFxxC7c3DvaRhB
B0VVfPlkPz0sw6l865MaTIbRyoUCAwEAAaOCA2gwggNkMB8GA1UdIwQYMBaAFDgS
xnkCZjgC4zck5YsP/0WVaeYxMB0GA1UdDgQWBBSd7sF7gQs6R2lxGH0RN5O8pRs/
+zAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEF
BQcDAQYIKwYBBQUHAwIwUAYDVR0gBEkwRzA7BgwrBgEEAbIxAQIBAwQwKzApBggr
BgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLm5ldC9DUFMwCAYGZ4EMAQIB
MHQGCCsGAQUFBwEBBGgwZjA+BggrBgEFBQcwAoYyaHR0cDovL2NydC5jb21vZG9j
YS5jb20vVWJpcXVpVExTRFZSU0FTZXJ2ZXJDQS5jcnQwJAYIKwYBBQUHMAGGGGh0
dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTAjBgNVHREBAf8EGTAXghVuby1zdWJqZWN0
LmJhZHNzbC5jb20wggH2BgorBgEEAdZ5AgQCBIIB5gSCAeIB4AB2AKS5CZC0GFgU
h7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABWt5t4gUAAAQDAEcwRQIhAIQE7oHj
PQvtURUCoh6+dM8GdC6OEfAANupRYHYMo6a8AiBgL5fwtsOp+XR8vQ8XkMKMXYRs
0awe+B3ZNuIaXGmEWQB3AFYUBpov18Ls0/XhvUSyPsdGdrm8mRFcwO+UmFXWidDd
AAABWt5t4CwAAAQDAEgwRgIhAIlY3Jz655VWCZm6WMoEcU2nExX1pyK8SL7oj+fp
3HmPAiEAmHu87c0EInS/wDJrnbiSWzyc47UM2xr3kYhY/lP8OVwAdQDuS723dc5g
uuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAVrebeHfAAAEAwBGMEQCIFMOvF7H
hM3jdnhdM2BwMohT35uuzrGL3DNJhmKtqTg8AiBL8Mjn00eDbR4a1HKipKgmvt87
MfXLexBSoRb/lgXT5QB2ALvZ37wfinG1k5Qjl6qSe0c4V5UKq1LoGpCWZDaOHtGF
AAABWt56EsgAAAQDAEcwRQIhAN7MnjhZoLr3ci0nNfSZ9Ftu/+FT+N3gIfC75fyw
XQR+AiAiExEXXf+G09W8F93gJDPZwC7bM2VoWb1bZlkVcvtRdTANBgkqhkiG9w0B
AQsFAAOCAQEAHv5koaT/MZ+zhKQs+6fHJDgTQ2+66u8k6PKQLV3OcfFusJBt/TrD
P/nNgidru2vObn5NUu2MydVrCfoKwK8hf+7j+fjyLSKZYOvrqhRnN0svqlrX4wWC
01rrEttc5H8UNf/oaylbOG4vePw8bF5n2aiU4vmGkuTPIkvqxtZ6IJjxqSQqaRhA
ZRc7d/YAS+MyFF5JXAo9aSyi+AIvhFeTFi+0nmzPwp6wpxz97ylm6DymFMY3IqmP
RYq4/yqbWE2yz4tRfnedeWBzGSAO4kWDQIN6NDjYwVjGsTk9rSpq/sEtPhUrXWB0
yd8BGrY2DQplAarq7e1IBIK+tBSRIYF3Ag==
-----END CERTIFICATE-----
""")[2])

NO_SUBJECT_BADSSL_COM_INTERMEDIATE_CA = asn1crypto.x509.Certificate.load(asn1crypto.pem.unarmor(b"""
 1 s:C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = UbiquiTLS\\E2\\84\\A2 DV RSA Server CA
   i:C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Certification Authority
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA384
   v:NotBefore: Mar 29 00:00:00 2016 GMT; NotAfter: Mar 29 23:59:59 2031 GMT
-----BEGIN CERTIFICATE-----
MIIF+TCCA+GgAwIBAgIRALEh69i9ODvCDLdUvBhDX/swDQYJKoZIhvcNAQEMBQAw
gYUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYD
VQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTE2MDMy
OTAwMDAwMFoXDTMxMDMyOTIzNTk1OVowgYAxCzAJBgNVBAYTAkdCMRswGQYDVQQI
ExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoT
EUNPTU9ETyBDQSBMaW1pdGVkMSYwJAYDVQQDDB1VYmlxdWlUTFPihKIgRFYgUlNB
IFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL23CxiN
bAfZclMlGi9tHpl6dCSxT4yRM79i/h3u/HbErdS+3jiq9oPZfCqgbJ0PVIOBelGb
EhvBBbkW/wPlDq3vEEt9nP/P3cRVGu+i0X/puXA51E5TgrEn5/jdorBANmhItrG4
uZietPJmFx6awA3ANC2MVnvmT1s5qS0cnrdFh2rLRwfANm4S0UbJNpHSItFinh0J
XtQFyc/QE+fGAH1sC8aW34Rt+qQ1+msY7hvNpXKZLR8Fy5AVi089iv5cK8bqzVaQ
F8kJTiukJ9vQ/e9CC7x9/TxX/oYn5bIejxsaoGPi1BgeRkS7J42MeNpYmh7kUFN6
ZZm5Yh8OB571L30CAwEAAaOCAWUwggFhMB8GA1UdIwQYMBaAFLuvfgI9+qbxPISO
re44mOzZMjLUMB0GA1UdDgQWBBQ4EsZ5AmY4AuM3JOWLD/9FlWnmMTAOBgNVHQ8B
Af8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHSUEFjAUBggrBgEFBQcD
AQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgGBmeBDAECATBMBgNVHR8E
RTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9SU0FDZXJ0
aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggrBgEFBQcBAQRlMGMwOwYIKwYBBQUH
MAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET1JTQUFkZFRydXN0Q0Eu
Y3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZI
hvcNAQEMBQADggIBAC3C7NUxneoMxtAT5QcdKTxVO2TmjbQtmYaZ6b06ySZC+RZm
GrktbzTwGh0jb33K/Wx9X1GXhsZIACgZM9bbeopskqlg/x5UDtHzaDWs+XtWMhET
aRtQRyRJ6bxTU64DSjnHbgLedToXmA2H8BF+DrRwEGG0twg9EjhIOJbvJ8Jcsdzh
b2hE4w48VwpQzH+Sg78TnGr6MimbnkFpuE+DO5q/x2AmeuOdmcl/3ufs3EjKeJTr
ybyjutGfI+LM3UTw1FhVzeMUPJBrebiy8tTP2/Rn8sJRdK3J+lmfY+sgfkcpXjMO
PA8esFM43Wawn2fLaQALi0Vpm36oc9ECIqjAunxQ/OmLl2uSvERNln/hmSlKvPEY
vA7lUXzRAxbpR0K7n+GBOMvkT9n1JGscHR9Oy3QGVksCT5bVvuGhH9m6BM3lnskp
3eyOXy0PpT9eJVflrpA8HVcJXGNCFDBT3iWUtHXXfopJvBe6RcEyu7aLWPNJ0/wM
n+EdLjUShlFqczNfw15eAdnTHkPCFW588pj7Hz0MaTeIqOBZWTHvc/BADJbRZuh7
jVXvr24Pv15WVEt/GKqm+VkvusRTVMVQm9fDH8rBIxBmpzt0uBTcg8IWY8HtGfEt
5R+qkfsm6EWtj4APtivR5qC2mzEDxbZSlduxifzG194rAGGbcn2KeOA0QwNE
-----END CERTIFICATE-----
""")[2])

NO_SUBJECT_BADSSL_COM_ROOT_CA = asn1crypto.x509.Certificate.load(asn1crypto.pem.unarmor(b"""
 2 s:C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Certification Authority
   i:C = SE, O = AddTrust AB, OU = AddTrust External TTP Network, CN = AddTrust External CA Root
   a:PKEY: rsaEncryption, 4096 (bit); sigalg: RSA-SHA384
   v:NotBefore: May 30 10:48:38 2000 GMT; NotAfter: May 30 10:48:38 2020 GMT
-----BEGIN CERTIFICATE-----
MIIFdDCCBFygAwIBAgIQJ2buVutJ846r13Ci/ITeIjANBgkqhkiG9w0BAQwFADBv
MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk
ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF
eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow
gYUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYD
VQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkq
hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAkehUktIKVrGsDSTdxc9EZ3SZKzejfSNw
AHG8U9/E+ioSj0t/EFa9n3Byt2F/yUsPF6c947AEYe7/EZfH9IY+Cvo+XPmT5jR6
2RRr55yzhaCCenavcZDX7P0N+pxs+t+wgvQUfvm+xKYvT3+Zf7X8Z0NyvQwA1onr
ayzT7Y+YHBSrfuXjbvzYqOSSJNpDa2K4Vf3qwbxstovzDo2a5JtsaZn4eEgwRdWt
4Q08RWD8MpZRJ7xnw8outmvqRsfHIKCxH2XeSAi6pE6p8oNGN4Tr6MyBSENnTnIq
m1y9TBsoilwie7SrmNnu4FGDwwlGTm0+mfqVF9p8M1dBPI1R7Qu2XK8sYxrfV8g/
vOldxJuvRZnio1oktLqpVj3Pb6r/SVi+8Kj/9Lit6Tf7urj0Czr56ENCHonYhMsT
8dm74YlguIwoVqwUHZwK53Hrzw7dPamWoUi9PPevtQ0iTMARgexWO/bTouJbt7IE
IlKVgJNp6I5MZfGRAy1wdALqi2cVKWlSArvX31BqVUa/oKMoYX9w0MOiqiwhqkfO
KJwGRXa/ghgntNWutMtQ5mv0TIZxMOmm3xaG4Nj/QN370EKIf6MzOi5cHkERgWPO
GHFrK+ymircxXDpqR+DDeVnWIBqv8mqYqnK8V0rSS527EPywTEHl7R09XiidnMy/
s1Hap0flhFMCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73g
JMtUGjAdBgNVHQ4EFgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQD
AgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9
MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVy
bmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6
Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggEBAGS/g/FfmoXQ
zbihKVcN6Fr30ek+8nYEbvFScLsePP9NDXRqzIGCJdPDoCpdTPW6i6FtxFQJdcfj
Jw5dhHk3QBN39bSsHNA7qxcS1u80GH4r6XnTq1dFDK8o+tDb5VCViLvfhVdpfZLY
Uspzgb8c8+a4bmYRBbMelC1/kZWSWfFMzqORcUx8Rww7Cxn2obFshj5cqsQugsv5
B5a6SE2Q8pTIqXOi6wZ7I53eovNNVZ96YUWYGGjHXkBrI/V5eu+MtWuLt29G9Hvx
PUsE2JOAWVrgQSQdso8VYFhH2+9uRv0V9dlfmrPb2LjkQLPNlzmuhbsdjrzch5vR
pu/xO28QOG8=
-----END CERTIFICATE-----
""")[2])

no_common_name_badssl_com_certificate_chain = (
    NO_SUBJECT_BADSSL_COM_ROOT_CA,
    NO_SUBJECT_BADSSL_COM_INTERMEDIATE_CA,
    NO_SUBJECT_BADSSL_COM_LEAF_CERTIFICATE,
)

context = certvalidator.context.ValidationContext(
    whitelisted_certs=list(map(
        lambda certificate: certificate.sha1_fingerprint, no_common_name_badssl_com_certificate_chain
    )),
    trust_roots=[NO_SUBJECT_BADSSL_COM_ROOT_CA],
)
cert_validator = certvalidator.CertificateValidator(
    end_entity_cert=NO_SUBJECT_BADSSL_COM_LEAF_CERTIFICATE,
    intermediate_certs=[NO_SUBJECT_BADSSL_COM_INTERMEDIATE_CA],
    validation_context=context,
)
cert_validator.validate_usage(set())

Please use the following patch just as a hint:

diff --git a/certvalidator/validate.py b/certvalidator/validate.py
index b0cfb05..61693ef 100644
--- a/certvalidator/validate.py
+++ b/certvalidator/validate.py
@@ -677,6 +677,7 @@ def _validate_path(validation_context, path, end_entity_name_override=None):
             'certificate_policies',
             'policy_mappings',
             'policy_constraints',
+            'subject_alt_name',
             'inhibit_any_policy',
         ])
         unsupported_critical_extensions = cert.critical_extensions - supported_extensions