From d1452424beced04dc42bbadd68878d9e1c24da9c Mon Sep 17 00:00:00 2001 From: Kyle Morton Date: Sat, 20 Jun 2015 13:07:23 -0700 Subject: [PATCH] Cleaning up upstream server verification. Adding storage of cerificate verification errors on TCPClient object to enable warnings in downstream projects. --- netlib/tcp.py | 16 ++-- test/data/not-server.crt | 15 ---- test/data/verificationcerts/9d45e6a9.0 | 1 + test/data/verificationcerts/interm.key | 16 ++++ test/data/verificationcerts/trusted-chain.crt | 35 ++++++++ .../data/verificationcerts/trusted-interm.crt | 19 ++++ test/data/verificationcerts/trusted.key | 15 ++++ test/data/verificationcerts/trusted.pem | 15 ++++ .../verificationcerts/untrusted-chain.crt | 33 +++++++ .../verificationcerts/untrusted-interm.crt | 17 ++++ test/data/verificationcerts/untrusted.crt | 16 ++++ .../verificationcerts/verification-server.key | 16 ++++ test/test_tcp.py | 86 ++++++++++++++++--- 13 files changed, 266 insertions(+), 34 deletions(-) delete mode 100644 test/data/not-server.crt create mode 120000 test/data/verificationcerts/9d45e6a9.0 create mode 100644 test/data/verificationcerts/interm.key create mode 100644 test/data/verificationcerts/trusted-chain.crt create mode 100644 test/data/verificationcerts/trusted-interm.crt create mode 100644 test/data/verificationcerts/trusted.key create mode 100644 test/data/verificationcerts/trusted.pem create mode 100644 test/data/verificationcerts/untrusted-chain.crt create mode 100644 test/data/verificationcerts/untrusted-interm.crt create mode 100644 test/data/verificationcerts/untrusted.crt create mode 100644 test/data/verificationcerts/verification-server.key diff --git a/netlib/tcp.py b/netlib/tcp.py index 61306e4e5..2cae34ecf 100644 --- a/netlib/tcp.py +++ b/netlib/tcp.py @@ -401,14 +401,13 @@ class _Connection(object): if options is not None: context.set_options(options) - # Verify Options (NONE/PEER/PEER|FAIL_IF_... and trusted CAs) - if verify_options is not None and verify_options is not SSL.VERIFY_NONE: - def verify_cert(conn_, cert_, errno, err_depth, is_cert_verified): - if is_cert_verified: - return True - raise NetLibError( - "Upstream certificate validation failed at depth: %s with error number: %s" % - (err_depth, errno)) + # Verify Options (NONE/PEER and trusted CAs) + if verify_options is not None: + def verify_cert(conn, x509, errno, err_depth, is_cert_verified): + if not is_cert_verified: + self.ssl_verification_error = dict(errno=errno, + depth=err_depth) + return is_cert_verified context.set_verify(verify_options, verify_cert) context.load_verify_locations(ca_pemfile, ca_path) @@ -469,6 +468,7 @@ class TCPClient(_Connection): self.connection, self.rfile, self.wfile = None, None, None self.cert = None self.ssl_established = False + self.ssl_verification_error = None self.sni = None def create_ssl_context(self, cert=None, alpn_protos=None, **sslctx_kwargs): diff --git a/test/data/not-server.crt b/test/data/not-server.crt deleted file mode 100644 index 08c015c2c..000000000 --- a/test/data/not-server.crt +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICRTCCAa4CCQD/j4qq1h3iCjANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJV -UzELMAkGA1UECBMCQ0ExETAPBgNVBAcTCFNvbWVDaXR5MRcwFQYDVQQKEw5Ob3RU -aGVSaWdodE9yZzELMAkGA1UECxMCTkExEjAQBgNVBAMTCU5vdFNlcnZlcjAeFw0x -NTA2MTMwMTE2MDZaFw0yNTA2MTAwMTE2MDZaMGcxCzAJBgNVBAYTAlVTMQswCQYD -VQQIEwJDQTERMA8GA1UEBxMIU29tZUNpdHkxFzAVBgNVBAoTDk5vdFRoZVJpZ2h0 -T3JnMQswCQYDVQQLEwJOQTESMBAGA1UEAxMJTm90U2VydmVyMIGfMA0GCSqGSIb3 -DQEBAQUAA4GNADCBiQKBgQDPkJlXAOCMKF0R7aDn5QJ7HtrJgOUDk/LpbhKhRZZR -dRGnJ4/HQxYYHh9k/4yZamYcvQPUxvFJt7UJUocf+84LUcIusUk7GvJMgsMVtFMq -7UKNXBN5tl3oOtoFDWGMZ8ksaIxS6oW3V/9v2WgU23PfvwE0EZqy+QhMLZZP5GOH -RwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAJI6UtMKdCS2ghjqhAek2W1rt9u+Wuvx -776WYm5VyrJEtBDc/axLh0OteXzy/A31JrYe15fnVWIeFbDF0Ief9/Ezv6Jn+Pk8 -DErw5IHk2B399O4K3L3Eig06piu7uf3vE4l8ZanY02ZEnw7DyL6kmG9lX98VGenF -uXPfu3yxKbR4 ------END CERTIFICATE----- diff --git a/test/data/verificationcerts/9d45e6a9.0 b/test/data/verificationcerts/9d45e6a9.0 new file mode 120000 index 000000000..2f34cfaab --- /dev/null +++ b/test/data/verificationcerts/9d45e6a9.0 @@ -0,0 +1 @@ +trusted.pem \ No newline at end of file diff --git a/test/data/verificationcerts/interm.key b/test/data/verificationcerts/interm.key new file mode 100644 index 000000000..76c05cf47 --- /dev/null +++ b/test/data/verificationcerts/interm.key @@ -0,0 +1,16 @@ +# Key used to sign trusted-interm.crt and untrusted-interm.crt +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC1E80qCHhZ1gaZTYB7pN/Yxt3ehpEj+5hCbpop5iTWLuDjULS9 +WjA1wP+p02kZQ2dqL8pqT1qcc5jKmk2jvMeB/cQ7zNDg1NCmQMqx0KptRByMZ+GN +Zcqc7D4jl6vhGP4zAzV/lxvBvxtgeJI+ZdrHN0vT9I1cYADKz9SzCDCRTwIDAQAB +AoGAfKHocKnrzEmXuSSy7meI+vfF9kfA1ndxUSg3S+dwK0uQ1mTSQhI1ZIo2bnlo +uU6/e0Lxm0KLJ2wZGjoifjSNTC8pcxIfAQY4kM9fqoUcXVSBVSS2kByTunhNSVZQ +yQyc+UTq9g1zBnJsZAltn7/PaihU4heWgP/++lposuShqmECQQDaG+7l0qul1xak +9kuZgc88BSTfn9iMK2zIQRcVKuidK4dT3QEp0wmWR5Ue8jq8lvTmVTGNGZbHcheh +KhoZfLgLAkEA1IjwAw/8z02yV3lbc2QUjIl9m9lvjHBoE2sGuSfq/cZskLKrGat+ +CVj3spqVAg22tpQwVBuHiipBziWVnEtiTQJAB9FKfchQSLBt6lm9mfHyKJeSm8VR +8Kw5yO+0URjpn4CI6DOasBIVXOKR8LsD6fCLNJpHHWSWZ+2p9SfaKaGzwwJBAM31 +Scld89qca4fzNZkT0goCrvOZeUy6HVE79Q72zPVSFSD/02kT1BaQ3bB5to5/5aD2 +6AKJjwZoPs7bgykrsD0CQBzU8U/8x2dNQnG0QeqaKQu5kKhZSZ9bsawvrCkxSl6b +WAjl/Jehi5bbQ07zQo3cge6qeR38FCWVCHQ/5wNbc54= +-----END RSA PRIVATE KEY----- diff --git a/test/data/verificationcerts/trusted-chain.crt b/test/data/verificationcerts/trusted-chain.crt new file mode 100644 index 000000000..dd30bff3f --- /dev/null +++ b/test/data/verificationcerts/trusted-chain.crt @@ -0,0 +1,35 @@ +# untrusted.crt, signed by trusted-interm.crt +-----BEGIN CERTIFICATE----- +MIICYzCCAcwCAhAIMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAkFVMRMwEQYD +VQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBM +dGQxFDASBgNVBAsTC0lOVEVSTSBVTklUMSEwHwYDVQQDExhPUkcgV0lUSCBJTlRF +Uk1FRElBVEUgQ0EwIBcNMTUwNjIwMDEyMDI1WhgPMjExNTA1MjcwMTIwMjVaMHMx +CzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRl +cm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAsTCUxFQUYgVU5JVDEYMBYGA1UE +AxMPTk9UIFRSVVNURUQgT1JHMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDf +NZx/tugICrWGcpP8sa+EBX9WhazCsYIm8YgQrQO9B19dK7cHsWB+vIdFuDKHxfS2 +JBIeVSaZ6H4onWGnZRAMpi5xnitVhBQKCZP1yOewtrg2umZIbcTz8A+BwAcvmmQN +7RZMfpxN9PMccWDfgtAXsjZ2E47o9EfhpGvxfcFc0wIDAQABMA0GCSqGSIb3DQEB +BQUAA4GBABtmc8zn5efVi3iVIgODadKkTv43elIwNZBqEJ6IaoVXvi5Mp1m4VxML +LQGPTNG1lpuVDz2z/Ml78942316ailCTOx48oDnb/yy4jI6hsp+N8p6T28/Wvkbm +cCgohk6/Cwat5gf+HwoIe5Z3B3HRJaIcB0OteluuLsHAvverBjc4 +-----END CERTIFICATE----- +# trusted-interm.crt, signed by trusted.pem +-----BEGIN CERTIFICATE----- +MIIC8jCCAlugAwIBAgICEAcwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQVUx +EzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMg +UHR5IEx0ZDEQMA4GA1UEAxMHVFJVU1RFRDAgFw0xNTA2MjAwMTE4MjdaGA8yMTE1 +MDUyNzAxMTgyN1owfjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx +ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UECxMLSU5U +RVJNIFVOSVQxITAfBgNVBAMTGE9SRyBXSVRIIElOVEVSTUVESUFURSBDQTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtRPNKgh4WdYGmU2Ae6Tf2Mbd3oaRI/uY +Qm6aKeYk1i7g41C0vVowNcD/qdNpGUNnai/Kak9anHOYyppNo7zHgf3EO8zQ4NTQ +pkDKsdCqbUQcjGfhjWXKnOw+I5er4Rj+MwM1f5cbwb8bYHiSPmXaxzdL0/SNXGAA +ys/UswgwkU8CAwEAAaOBozCBoDAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBTPkPQW +DAPOIy8mipuEsZcP1694EDBxBgNVHSMEajBooVukWTBXMQswCQYDVQQGEwJBVTET +MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMRAwDgYDVQQDEwdUUlVTVEVEggkAqNQXaKXXTf0wDQYJKoZIhvcNAQEF +BQADgYEApaPbwonY8l+zSxlY2Fw4WNKfl5nwcTW4fuv/0tZLzvsS6P4hTXxbYJNa +k3hQ1qlrr8DiWJewF85hYvEI2F/7eqS5dhhPTEUFPpsjhbgiqnASvW+WKQIgoY2r +aHgOXi7RNFtTcCgk0UZISWOY7ORLy8Xu6vKrLRjDhyfIbGlqnAs= +-----END CERTIFICATE----- diff --git a/test/data/verificationcerts/trusted-interm.crt b/test/data/verificationcerts/trusted-interm.crt new file mode 100644 index 000000000..d577db7de --- /dev/null +++ b/test/data/verificationcerts/trusted-interm.crt @@ -0,0 +1,19 @@ +# trusted-interm.crt, signed by trusted.pem +-----BEGIN CERTIFICATE----- +MIIC8jCCAlugAwIBAgICEAcwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQVUx +EzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMg +UHR5IEx0ZDEQMA4GA1UEAxMHVFJVU1RFRDAgFw0xNTA2MjAwMTE4MjdaGA8yMTE1 +MDUyNzAxMTgyN1owfjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx +ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UECxMLSU5U +RVJNIFVOSVQxITAfBgNVBAMTGE9SRyBXSVRIIElOVEVSTUVESUFURSBDQTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtRPNKgh4WdYGmU2Ae6Tf2Mbd3oaRI/uY +Qm6aKeYk1i7g41C0vVowNcD/qdNpGUNnai/Kak9anHOYyppNo7zHgf3EO8zQ4NTQ +pkDKsdCqbUQcjGfhjWXKnOw+I5er4Rj+MwM1f5cbwb8bYHiSPmXaxzdL0/SNXGAA +ys/UswgwkU8CAwEAAaOBozCBoDAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBTPkPQW +DAPOIy8mipuEsZcP1694EDBxBgNVHSMEajBooVukWTBXMQswCQYDVQQGEwJBVTET +MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMRAwDgYDVQQDEwdUUlVTVEVEggkAqNQXaKXXTf0wDQYJKoZIhvcNAQEF +BQADgYEApaPbwonY8l+zSxlY2Fw4WNKfl5nwcTW4fuv/0tZLzvsS6P4hTXxbYJNa +k3hQ1qlrr8DiWJewF85hYvEI2F/7eqS5dhhPTEUFPpsjhbgiqnASvW+WKQIgoY2r +aHgOXi7RNFtTcCgk0UZISWOY7ORLy8Xu6vKrLRjDhyfIbGlqnAs= +-----END CERTIFICATE----- diff --git a/test/data/verificationcerts/trusted.key b/test/data/verificationcerts/trusted.key new file mode 100644 index 000000000..3c26edf62 --- /dev/null +++ b/test/data/verificationcerts/trusted.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC00Jf3KrBAmLQWl+Dz8Qrig8ActB94kv0/Lu03P/2DwOR8kH2h +3w4OC3b3CFKX31h7hm/H1PPHq7cIX6IRfwrYCtBE77UbxklSlrwn06j6YSotz0/d +wLEQEFDXWITJq7AyntaiafDHazbbXESNm/+I/YEl2wKemEHE//qWbeM9kwIDAQAB +AoGAVs2FBs1hi8FDQ01qWvGuzgt94MnACfxWw0xd6RY5OFUT25DqHxmb/7YVSIag +T/SS38osQ3zCA2s2FTkD7u5UX5AzJyqYJwmJhe6ZmaVly6IpebMxkX5w/hy15/N4 +uy+kzdtEBUUTNLL3DM7THkDYUxmeDzCBrHsMvYUqFgsBLOECQQDeNc1pDC++ovg5 +d9sKqMnEykBfvuvR6ra/343tYxy9zNFBvYjU3BA83MITIbEa/KtlSkIppz/K/jk5 +IRwSrwsJAkEA0E9aZfjDZbC9Z4oL7T8gtj2ftSh2g37KE5AWW2OxMJwrzoJ/6wjB +nG26ATlHEFP9bRzL2O1iovFLalqEjQo+uwJAMjtZXvjZRjATCvK0Onmjeu/5k2tW +ZdK4UzGXJOW11pYZa9ILv4qrxQZmfOqt3Zrmp/QcdswPGLVVfDum2/Zj+QJABJO5 +yMPOh0162+uMl4nrjhWMjM52zCzdA9EGrLtkCU1lKQR1CxUGLAm9LIm1pgYya1NW +p02P/USQA6Y5g1/WQQJBAIwl42Bebgaxl7dUbQX/vF+TryoCkM3B3eSM+P4XKB4f +kKSkNxvp59uq+b40gkoqEowhdq97y+pmrCxJHK43NJM= +-----END RSA PRIVATE KEY----- diff --git a/test/data/verificationcerts/trusted.pem b/test/data/verificationcerts/trusted.pem new file mode 100644 index 000000000..8ebc0e5c8 --- /dev/null +++ b/test/data/verificationcerts/trusted.pem @@ -0,0 +1,15 @@ +# Self signed +-----BEGIN CERTIFICATE----- +MIICJzCCAZACCQCo1BdopddN/TANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJB +VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMRAwDgYDVQQDEwdUUlVTVEVEMCAXDTE1MDYxOTE4MDEzMVoYDzIx +MTUwNTI2MTgwMTMxWjBXMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0 +ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRAwDgYDVQQDEwdU +UlVTVEVEMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC00Jf3KrBAmLQWl+Dz +8Qrig8ActB94kv0/Lu03P/2DwOR8kH2h3w4OC3b3CFKX31h7hm/H1PPHq7cIX6IR +fwrYCtBE77UbxklSlrwn06j6YSotz0/dwLEQEFDXWITJq7AyntaiafDHazbbXESN +m/+I/YEl2wKemEHE//qWbeM9kwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAF0NREP3 +X+fTebzJGttzrFkDhGVFKRNyLXblXRVanlGOYF+q8grgZY2ufC/55gqf+ub6FRT5 +gKPhL4V2rqL8UAvCE7jq8ujpVfTB8kRAKC675W2DBZk2EJX9mjlr89t7qXGsI5nF +onpfJ1UtiJshNoV7h/NFHeoag91kx628807n +-----END CERTIFICATE----- diff --git a/test/data/verificationcerts/untrusted-chain.crt b/test/data/verificationcerts/untrusted-chain.crt new file mode 100644 index 000000000..272779d88 --- /dev/null +++ b/test/data/verificationcerts/untrusted-chain.crt @@ -0,0 +1,33 @@ +# untrusted.crt, signed by trusted-interm.crt +-----BEGIN CERTIFICATE----- +MIICYzCCAcwCAhAIMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAkFVMRMwEQYD +VQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBM +dGQxFDASBgNVBAsTC0lOVEVSTSBVTklUMSEwHwYDVQQDExhPUkcgV0lUSCBJTlRF +Uk1FRElBVEUgQ0EwIBcNMTUwNjIwMDEyMDI1WhgPMjExNTA1MjcwMTIwMjVaMHMx +CzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRl +cm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAsTCUxFQUYgVU5JVDEYMBYGA1UE +AxMPTk9UIFRSVVNURUQgT1JHMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDf +NZx/tugICrWGcpP8sa+EBX9WhazCsYIm8YgQrQO9B19dK7cHsWB+vIdFuDKHxfS2 +JBIeVSaZ6H4onWGnZRAMpi5xnitVhBQKCZP1yOewtrg2umZIbcTz8A+BwAcvmmQN +7RZMfpxN9PMccWDfgtAXsjZ2E47o9EfhpGvxfcFc0wIDAQABMA0GCSqGSIb3DQEB +BQUAA4GBABtmc8zn5efVi3iVIgODadKkTv43elIwNZBqEJ6IaoVXvi5Mp1m4VxML +LQGPTNG1lpuVDz2z/Ml78942316ailCTOx48oDnb/yy4jI6hsp+N8p6T28/Wvkbm +cCgohk6/Cwat5gf+HwoIe5Z3B3HRJaIcB0OteluuLsHAvverBjc4 +-----END CERTIFICATE----- +# untrusted-interm.crt, self-signed +-----BEGIN CERTIFICATE----- +MIICdTCCAd4CCQDRSKOnIMbTgDANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJB +VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMRQwEgYDVQQLEwtJTlRFUk0gVU5JVDEhMB8GA1UEAxMYT1JHIFdJ +VEggSU5URVJNRURJQVRFIENBMCAXDTE1MDYyMDAxMzY0M1oYDzIxMTUwNTI3MDEz +NjQzWjB+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UE +ChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRQwEgYDVQQLEwtJTlRFUk0gVU5J +VDEhMB8GA1UEAxMYT1JHIFdJVEggSU5URVJNRURJQVRFIENBMIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQC1E80qCHhZ1gaZTYB7pN/Yxt3ehpEj+5hCbpop5iTW +LuDjULS9WjA1wP+p02kZQ2dqL8pqT1qcc5jKmk2jvMeB/cQ7zNDg1NCmQMqx0Kpt +RByMZ+GNZcqc7D4jl6vhGP4zAzV/lxvBvxtgeJI+ZdrHN0vT9I1cYADKz9SzCDCR +TwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAGbObAMEajCz4kj7OP2/DB5SRy2+H/G3 +8Qvc43xlMMNQyYxsDuLOFL0UMRzoKgntrrm2nni8jND+tuMt+hv3ZlBcJlYJ6ynR +sC1ITTC/1SwwwO0AFIyduUEIJYr/B3sgcVYPLcEfeDZgmEQc9Tnc01aEu3lx2+l9 +0JTSPL2L9LdA +-----END CERTIFICATE----- diff --git a/test/data/verificationcerts/untrusted-interm.crt b/test/data/verificationcerts/untrusted-interm.crt new file mode 100644 index 000000000..875cdcd60 --- /dev/null +++ b/test/data/verificationcerts/untrusted-interm.crt @@ -0,0 +1,17 @@ +# untrusted-interm.crt, self-signed +-----BEGIN CERTIFICATE----- +MIICdTCCAd4CCQDRSKOnIMbTgDANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJB +VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMRQwEgYDVQQLEwtJTlRFUk0gVU5JVDEhMB8GA1UEAxMYT1JHIFdJ +VEggSU5URVJNRURJQVRFIENBMCAXDTE1MDYyMDAxMzY0M1oYDzIxMTUwNTI3MDEz +NjQzWjB+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UE +ChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRQwEgYDVQQLEwtJTlRFUk0gVU5J +VDEhMB8GA1UEAxMYT1JHIFdJVEggSU5URVJNRURJQVRFIENBMIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQC1E80qCHhZ1gaZTYB7pN/Yxt3ehpEj+5hCbpop5iTW +LuDjULS9WjA1wP+p02kZQ2dqL8pqT1qcc5jKmk2jvMeB/cQ7zNDg1NCmQMqx0Kpt +RByMZ+GNZcqc7D4jl6vhGP4zAzV/lxvBvxtgeJI+ZdrHN0vT9I1cYADKz9SzCDCR +TwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAGbObAMEajCz4kj7OP2/DB5SRy2+H/G3 +8Qvc43xlMMNQyYxsDuLOFL0UMRzoKgntrrm2nni8jND+tuMt+hv3ZlBcJlYJ6ynR +sC1ITTC/1SwwwO0AFIyduUEIJYr/B3sgcVYPLcEfeDZgmEQc9Tnc01aEu3lx2+l9 +0JTSPL2L9LdA +-----END CERTIFICATE----- diff --git a/test/data/verificationcerts/untrusted.crt b/test/data/verificationcerts/untrusted.crt new file mode 100644 index 000000000..2dab470b5 --- /dev/null +++ b/test/data/verificationcerts/untrusted.crt @@ -0,0 +1,16 @@ +# untrusted.crt, signed by trusted-interm.crt +-----BEGIN CERTIFICATE----- +MIICYzCCAcwCAhAIMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAkFVMRMwEQYD +VQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBM +dGQxFDASBgNVBAsTC0lOVEVSTSBVTklUMSEwHwYDVQQDExhPUkcgV0lUSCBJTlRF +Uk1FRElBVEUgQ0EwIBcNMTUwNjIwMDEyMDI1WhgPMjExNTA1MjcwMTIwMjVaMHMx +CzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRl +cm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAsTCUxFQUYgVU5JVDEYMBYGA1UE +AxMPTk9UIFRSVVNURUQgT1JHMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDf +NZx/tugICrWGcpP8sa+EBX9WhazCsYIm8YgQrQO9B19dK7cHsWB+vIdFuDKHxfS2 +JBIeVSaZ6H4onWGnZRAMpi5xnitVhBQKCZP1yOewtrg2umZIbcTz8A+BwAcvmmQN +7RZMfpxN9PMccWDfgtAXsjZ2E47o9EfhpGvxfcFc0wIDAQABMA0GCSqGSIb3DQEB +BQUAA4GBABtmc8zn5efVi3iVIgODadKkTv43elIwNZBqEJ6IaoVXvi5Mp1m4VxML +LQGPTNG1lpuVDz2z/Ml78942316ailCTOx48oDnb/yy4jI6hsp+N8p6T28/Wvkbm +cCgohk6/Cwat5gf+HwoIe5Z3B3HRJaIcB0OteluuLsHAvverBjc4 +-----END CERTIFICATE----- diff --git a/test/data/verificationcerts/verification-server.key b/test/data/verificationcerts/verification-server.key new file mode 100644 index 000000000..c527b09f5 --- /dev/null +++ b/test/data/verificationcerts/verification-server.key @@ -0,0 +1,16 @@ +# Key used for untrusted.crt, untrusted-chain.crt and trusted-chain.crt +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDfNZx/tugICrWGcpP8sa+EBX9WhazCsYIm8YgQrQO9B19dK7cH +sWB+vIdFuDKHxfS2JBIeVSaZ6H4onWGnZRAMpi5xnitVhBQKCZP1yOewtrg2umZI +bcTz8A+BwAcvmmQN7RZMfpxN9PMccWDfgtAXsjZ2E47o9EfhpGvxfcFc0wIDAQAB +AoGAE4B9ofL7Jui4n3yXTXbA3QoV7BtV0tTriDeGKd7T+soQHPXa0gM/aRNTxlWn +pJE5JkjUhG3wJ3ZWv3mwtI1x718y0yL9uEgQJYsrNN+VJQwbGxXPio5SaG39gs+y +/8xklytMIgvuCXxmcfljemW9+PGT8otYlHeIU3wvHQennDECQQD2vWAEU9k02R9w +EkCM7mZEaW+WwrzyAD1NqatsVWErbNeXFPcHwU6y+DiDg2s5iEk89+xN2rX5mW2S +PF/2RpaNAkEA55YpZN5nN4P8yCYNz5mWN0kuSPytSgJ3fQY3BY2GkdIft/KcAuDV +1pf6jxubwP4vlamnZpqLfylbGdlRBoMY3wJBALQVE3cVG3qO3XsWVzaE6O8VZPRL +vUuDETsVkp/G0Ny428DQ9FscoyvMLrMNv7yF065D5JwN/LLnYClTF1bPviECQQCo +1BavO1eh6C3DN8K/wmb5PPdqLBKkrrGvSnWYLbmZ2sZW0p4blw8tVzRJWcYtZuEH +yVuJeEcT1/FbIcto5O+fAkASbZXZka3nm41wWNYg479Sl8I+qvtScfJgpyByYhCx +QaUAtZ791U+WNNHLqfZhSzP9lFZNRI0WNBSAy3SBR2Ur +-----END RSA PRIVATE KEY----- diff --git a/test/test_tcp.py b/test/test_tcp.py index 4253e073b..52398ef38 100644 --- a/test/test_tcp.py +++ b/test/test_tcp.py @@ -183,52 +183,115 @@ class TestSSLv3Only(tservers.ServerTestBase): tutils.raises(tcp.NetLibError, c.convert_to_ssl, sni="foo.com") -class TestSSLUpstreamCertVerification(tservers.ServerTestBase): +class TestSSLUpstreamCertVerificationWBadServerCert(tservers.ServerTestBase): handler = EchoHandler ssl = dict( - cert=tutils.test_data.path("data/server.crt") - ) + cert=tutils.test_data.path("data/verificationcerts/untrusted.crt"), + key=tutils.test_data.path("data/verificationcerts/verification-server.key")) - def test_mode_default(self): + def test_mode_default_should_pass(self): c = tcp.TCPClient(("127.0.0.1", self.port)) c.connect() c.convert_to_ssl() + # Verification errors should be saved even if connection isn't aborted + # aborted + assert c.ssl_verification_error is not None + testval = "echo!\n" c.wfile.write(testval) c.wfile.flush() assert c.rfile.readline() == testval - def test_mode_none(self): + def test_mode_none_should_pass(self): c = tcp.TCPClient(("127.0.0.1", self.port)) c.connect() c.convert_to_ssl(verify_options=SSL.VERIFY_NONE) + # Verification errors should be saved even if connection isn't aborted + assert c.ssl_verification_error is not None + testval = "echo!\n" c.wfile.write(testval) c.wfile.flush() assert c.rfile.readline() == testval - def test_mode_strict_w_bad_cert(self): + def test_mode_strict_should_fail(self): c = tcp.TCPClient(("127.0.0.1", self.port)) c.connect() tutils.raises( tcp.NetLibError, c.convert_to_ssl, - verify_options=SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT, - ca_pemfile=tutils.test_data.path("data/not-server.crt")) + verify_options=SSL.VERIFY_PEER, + ca_pemfile=tutils.test_data.path("data/verificationcerts/trusted.pem")) - def test_mode_strict_w_cert(self): + assert c.ssl_verification_error is not None + + # Unknown issuing certificate authority for first certificate + assert c.ssl_verification_error['errno'] == 20 + assert c.ssl_verification_error['depth'] == 0 + + +class TestSSLUpstreamCertVerificationWBadCertChain(tservers.ServerTestBase): + handler = EchoHandler + + ssl = dict( + cert=tutils.test_data.path("data/verificationcerts/untrusted-chain.crt"), + key=tutils.test_data.path("data/verificationcerts/verification-server.key")) + + def test_mode_strict_should_fail(self): + c = tcp.TCPClient(("127.0.0.1", self.port)) + c.connect() + + tutils.raises( + "certificate verify failed", + c.convert_to_ssl, + verify_options=SSL.VERIFY_PEER, + ca_pemfile=tutils.test_data.path("data/verificationcerts/trusted.pem")) + + assert c.ssl_verification_error is not None + + # Untrusted self-signed certificate at second position in certificate + # chain + assert c.ssl_verification_error['errno'] == 19 + assert c.ssl_verification_error['depth'] == 1 + + +class TestSSLUpstreamCertVerificationWValidCertChain(tservers.ServerTestBase): + handler = EchoHandler + + ssl = dict( + cert=tutils.test_data.path("data/verificationcerts/trusted-chain.crt"), + key=tutils.test_data.path("data/verificationcerts/verification-server.key")) + + def test_mode_strict_w_pemfile_should_pass(self): c = tcp.TCPClient(("127.0.0.1", self.port)) c.connect() c.convert_to_ssl( - verify_options=SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT, - ca_pemfile=tutils.test_data.path("data/server.crt")) + verify_options=SSL.VERIFY_PEER, + ca_pemfile=tutils.test_data.path("data/verificationcerts/trusted.pem")) + + assert c.ssl_verification_error is None + + testval = "echo!\n" + c.wfile.write(testval) + c.wfile.flush() + assert c.rfile.readline() == testval + + def test_mode_strict_w_cadir_should_pass(self): + c = tcp.TCPClient(("127.0.0.1", self.port)) + c.connect() + + c.convert_to_ssl( + verify_options=SSL.VERIFY_PEER, + ca_path=tutils.test_data.path("data/verificationcerts/")) + + assert c.ssl_verification_error is None testval = "echo!\n" c.wfile.write(testval) @@ -457,6 +520,7 @@ class TestALPNClient(tservers.ServerTestBase): assert c.get_alpn_proto_negotiated() == "" assert c.rfile.readline() == "NONE" + class TestNoSSLNoALPNClient(tservers.ServerTestBase): handler = ALPNHandler