|
38 | 38 | ssl = import_helper.import_module("ssl")
|
39 | 39 | import _ssl
|
40 | 40 |
|
41 |
| -from ssl import TLSVersion, _TLSContentType, _TLSMessageType, _TLSAlertType |
| 41 | +from ssl import Purpose, TLSVersion, _TLSContentType, _TLSMessageType, _TLSAlertType |
42 | 42 |
|
43 | 43 | Py_DEBUG_WIN32 = support.Py_DEBUG and sys.platform == 'win32'
|
44 | 44 |
|
@@ -128,6 +128,13 @@ def data_file(*name):
|
128 | 128 | SIGNED_CERTFILE_ECC = data_file("keycertecc.pem")
|
129 | 129 | SIGNED_CERTFILE_ECC_HOSTNAME = 'localhost-ecc'
|
130 | 130 |
|
| 131 | +# A custom testcase, extracted from `rfc5280::aki::leaf-missing-aki` in x509-limbo: |
| 132 | +# The leaf (server) certificate has no AKI, which is forbidden under RFC 5280. |
| 133 | +# See: https://x509-limbo.com/testcases/rfc5280/#rfc5280akileaf-missing-aki |
| 134 | +LEAF_MISSING_AKI_CERTFILE = data_file("leaf-missing-aki.keycert.pem") |
| 135 | +LEAF_MISSING_AKI_CERTFILE_HOSTNAME = "example.com" |
| 136 | +LEAF_MISSING_AKI_CA = data_file("leaf-missing-aki.ca.pem") |
| 137 | + |
131 | 138 | # Same certificate as pycacert.pem, but without extra text in file
|
132 | 139 | SIGNING_CA = data_file("capath", "ceff1710.0")
|
133 | 140 | # cert with all kinds of subject alt names
|
@@ -2949,6 +2956,36 @@ def test_ecc_cert(self):
|
2949 | 2956 | cipher = s.cipher()[0].split('-')
|
2950 | 2957 | self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
|
2951 | 2958 |
|
| 2959 | + def test_verify_strict(self): |
| 2960 | + # verification fails by default, since the server cert is non-conforming |
| 2961 | + client_context = ssl.create_default_context() |
| 2962 | + client_context.load_verify_locations(LEAF_MISSING_AKI_CA) |
| 2963 | + hostname = LEAF_MISSING_AKI_CERTFILE_HOSTNAME |
| 2964 | + |
| 2965 | + server_context = ssl.create_default_context(purpose=Purpose.CLIENT_AUTH) |
| 2966 | + server_context.load_cert_chain(LEAF_MISSING_AKI_CERTFILE) |
| 2967 | + server = ThreadedEchoServer(context=server_context, chatty=True) |
| 2968 | + with server: |
| 2969 | + with client_context.wrap_socket(socket.socket(), |
| 2970 | + server_hostname=hostname) as s: |
| 2971 | + with self.assertRaises(ssl.SSLCertVerificationError): |
| 2972 | + s.connect((HOST, server.port)) |
| 2973 | + |
| 2974 | + # explicitly disabling VERIFY_X509_STRICT allows it to succeed |
| 2975 | + client_context = ssl.create_default_context() |
| 2976 | + client_context.load_verify_locations(LEAF_MISSING_AKI_CA) |
| 2977 | + client_context.verify_flags &= ~ssl.VERIFY_X509_STRICT |
| 2978 | + |
| 2979 | + server_context = ssl.create_default_context(purpose=Purpose.CLIENT_AUTH) |
| 2980 | + server_context.load_cert_chain(LEAF_MISSING_AKI_CERTFILE) |
| 2981 | + server = ThreadedEchoServer(context=server_context, chatty=True) |
| 2982 | + with server: |
| 2983 | + with client_context.wrap_socket(socket.socket(), |
| 2984 | + server_hostname=hostname) as s: |
| 2985 | + s.connect((HOST, server.port)) |
| 2986 | + cert = s.getpeercert() |
| 2987 | + self.assertTrue(cert, "Can't get peer certificate.") |
| 2988 | + |
2952 | 2989 | def test_dual_rsa_ecc(self):
|
2953 | 2990 | client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
2954 | 2991 | client_context.load_verify_locations(SIGNING_CA)
|
|
0 commit comments