From c1c58ef0d16221b78d5d39980ded0d157455fc89 Mon Sep 17 00:00:00 2001 From: Bret McGuire Date: Fri, 25 Mar 2022 14:28:46 -0500 Subject: [PATCH 1/3] Multi-certificate test cases --- tests/src/integration/ssl_certificates.hpp | 44 ++++++++++++++++++++++ tests/src/integration/tests/test_ssl.cpp | 32 ++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/tests/src/integration/ssl_certificates.hpp b/tests/src/integration/ssl_certificates.hpp index ea737386b..b56cf25ee 100644 --- a/tests/src/integration/ssl_certificates.hpp +++ b/tests/src/integration/ssl_certificates.hpp @@ -140,6 +140,20 @@ namespace test { * ssh-keygen -p \ * -N invalid \ * -f ssl/invalid/driver-private-invalid.pem + * + * # Building mock PEM (to support multiple certs in a PEM file) + * keytool -genkeypair -noprompt -keyalg RSA -validity 36500 \ + * -alias mock \ + * -keystore ssl/keystore.jks \ + * -storepass cassandra \ + * -keypass cassandra \ + * -dname "CN=127.0.0.1, OU=SomeOU, O=SomeO, L=Somewhere, ST=SomeState, C=US" + * + * keytool -exportcert -rfc -noprompt \ + * -alias mock \ + * -keystore ssl/keystore.jks \ + * -storepass cassandra \ + * -file ssl/mock.pem */ static const unsigned char cassandra_crt[953] = { @@ -557,6 +571,36 @@ class SslCertificates { "cAHazCFHOKxSQ/G7n+8xDx3r6jHxyE956u5jf5FRqUbaVIBMdg==\12" "-----END CERTIFICATE-----\12"; } + static const char* mock_pem() { + return "-----BEGIN CERTIFICATE-----\12" + "MIIDdTCCAl2gAwIBAgIEWUhnfDANBgkqhkiG9w0BAQsFADBqMQswCQYDVQQGEwJV\12" + "UzESMBAGA1UECBMJU29tZVN0YXRlMRIwEAYDVQQHEwlTb21ld2hlcmUxDjAMBgNV\12" + "BAoTBVNvbWVPMQ8wDQYDVQQLEwZTb21lT1UxEjAQBgNVBAMTCTEyNy4wLjAuMTAg\12" + "Fw0yMjAzMjUxODQ0MzVaGA8yMTIyMDMwMTE4NDQzNVowajELMAkGA1UEBhMCVVMx\12" + "EjAQBgNVBAgTCVNvbWVTdGF0ZTESMBAGA1UEBxMJU29tZXdoZXJlMQ4wDAYDVQQK\12" + "EwVTb21lTzEPMA0GA1UECxMGU29tZU9VMRIwEAYDVQQDEwkxMjcuMC4wLjEwggEi\12" + "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQClc1veJUZSLwl/RNVTzAf4O729\12" + "JA8kgL0z3o2pk3ZLNm18uf/JgROh1DtzbSXAqzT2J1Xz1hnr/tIeM/xr11tC87JY\12" + "7W4XgStB1hQJzb9VZegjIKCJkpYSToG0JnFTaa5419fil9JBhYxFI9RA+PxWh3nK\12" + "idqvr5zZzEVASbOUaUDk+KdmXyVRzh1IH3J1RSSbPrBsHk7cKurLD5kpxDnlFE36\12" + "2oxEt9qSBoXYLPlb8TWHnm5N8bPs9+ABifRq0dYk5ACpA9bKJB8aYyRQKFuwv3v+\12" + "2iDE3YvU5E9TtpMPWc0tPbr793I3bbv/HCZ1YiSKTE7rVmiD4/dxJwxmjxrbAgMB\12" + "AAGjITAfMB0GA1UdDgQWBBQoE3QwP1us/GcEf3dDYpD+TiWxPzANBgkqhkiG9w0B\12" + "AQsFAAOCAQEAeM/dG4lIBWtZGJ3OZDtK0NriNWe5bMHgHPJnGtTzwYvP8fmp55yN\12" + "fVt56qYr9CeQXCuL2d0PgVZLcSrza1mjdvZzQIB77Jwzm5peOVaOUswrIQQeEkeV\12" + "w5XvVx9ywJqPALpeKpJuTgJsgmjA82a2A6gdh5BG8IqWxPzXH9XpEWFACjpz2/eU\12" + "x0nOh6fzrGr0Vp2TSzriOxW2ikM2LzenoyErD/3eCeH75fzH/pT8iQqqlM1Xpu/z\12" + "lddbgced8jJNj5MQQpKpDJMBTuRJtg1KtbgiS+eexxo1jXh9lpn3/47DUe3sNl5O\12" + "5TiDOVzNL4Lo/61ZRfngJJpeu6rYvvw5iA==\12" + "-----END CERTIFICATE-----\12"; + } + static const char* combined_pem() { + std::string combo = mock_pem(); + combo.append(cassandra_pem()); + combo.append("\n"); + return combo.c_str(); + } + static const char* driver_private_pem_password() { return "driver"; } static void write_ccm_server_files() { diff --git a/tests/src/integration/tests/test_ssl.cpp b/tests/src/integration/tests/test_ssl.cpp index 1a6c1e345..f76bb646c 100644 --- a/tests/src/integration/tests/test_ssl.cpp +++ b/tests/src/integration/tests/test_ssl.cpp @@ -170,6 +170,38 @@ CASSANDRA_INTEGRATION_TEST_F(SslTests, VerifyPeerIdentity) { write_and_read(); } +/** + * Ensures SSL connection verifying peer/server certificate while performing write and read + * operations. + */ +CASSANDRA_INTEGRATION_TEST_F(SslTests, VerifyPeerMultipleCerts) { + CHECK_FAILURE; + + Ssl ssl; + ssl.with_verify_flags(CASS_SSL_VERIFY_PEER_CERT); + ssl.add_trusted_cert(SslCertificates::combined_pem()); + + Cluster cluster = default_cluster().with_ssl(ssl); + connect(cluster); + write_and_read(); +} + +/** + * Ensures SSL connection verifying peer/server certificate and identity while performing write and + * read operations. + */ +CASSANDRA_INTEGRATION_TEST_F(SslTests, VerifyPeerIdentityMultipleCerts) { + CHECK_FAILURE; + + Ssl ssl; + ssl.with_verify_flags(CASS_SSL_VERIFY_PEER_IDENTITY); + ssl.add_trusted_cert(SslCertificates::combined_pem()); + + Cluster cluster = default_cluster().with_ssl(ssl); + connect(cluster); + write_and_read(); +} + /** * Ensures that when one node (in this case the whole cluster) is terminated and restarted the * driver will reconnect without throwing errors. Each stage (connect and reconnect) write and read From 028b7c5c8f04675b88cf09a2b9c1287b3034a29a Mon Sep 17 00:00:00 2001 From: Bret McGuire Date: Mon, 28 Mar 2022 11:32:43 -0500 Subject: [PATCH 2/3] Fixes to the multi-cert test case --- tests/src/integration/ssl_certificates.hpp | 56 +++++++++++----------- tests/src/integration/tests/test_ssl.cpp | 18 +------ 2 files changed, 30 insertions(+), 44 deletions(-) diff --git a/tests/src/integration/ssl_certificates.hpp b/tests/src/integration/ssl_certificates.hpp index b56cf25ee..ffac0116b 100644 --- a/tests/src/integration/ssl_certificates.hpp +++ b/tests/src/integration/ssl_certificates.hpp @@ -141,19 +141,21 @@ namespace test { * -N invalid \ * -f ssl/invalid/driver-private-invalid.pem * - * # Building mock PEM (to support multiple certs in a PEM file) + * # Building dummy PEM. Some tests below require multiple PEM-encoded + * # certs in order to verify that we consider all input certs (and + * # not just the first one) * keytool -genkeypair -noprompt -keyalg RSA -validity 36500 \ - * -alias mock \ + * -alias dummy \ * -keystore ssl/keystore.jks \ * -storepass cassandra \ * -keypass cassandra \ - * -dname "CN=127.0.0.1, OU=SomeOU, O=SomeO, L=Somewhere, ST=SomeState, C=US" + * -dname "CN=1.2.3.4, OU=SomeOU, O=SomeO, L=Somewhere, ST=SomeState, C=US" * * keytool -exportcert -rfc -noprompt \ - * -alias mock \ + * -alias dummy \ * -keystore ssl/keystore.jks \ * -storepass cassandra \ - * -file ssl/mock.pem + * -file ssl/dummy.pem */ static const unsigned char cassandra_crt[953] = { @@ -571,33 +573,33 @@ class SslCertificates { "cAHazCFHOKxSQ/G7n+8xDx3r6jHxyE956u5jf5FRqUbaVIBMdg==\12" "-----END CERTIFICATE-----\12"; } - static const char* mock_pem() { + static const char* dummy_pem() { return "-----BEGIN CERTIFICATE-----\12" - "MIIDdTCCAl2gAwIBAgIEWUhnfDANBgkqhkiG9w0BAQsFADBqMQswCQYDVQQGEwJV\12" + "MIIDcTCCAlmgAwIBAgIEKDL8hDANBgkqhkiG9w0BAQsFADBoMQswCQYDVQQGEwJV\12" "UzESMBAGA1UECBMJU29tZVN0YXRlMRIwEAYDVQQHEwlTb21ld2hlcmUxDjAMBgNV\12" - "BAoTBVNvbWVPMQ8wDQYDVQQLEwZTb21lT1UxEjAQBgNVBAMTCTEyNy4wLjAuMTAg\12" - "Fw0yMjAzMjUxODQ0MzVaGA8yMTIyMDMwMTE4NDQzNVowajELMAkGA1UEBhMCVVMx\12" - "EjAQBgNVBAgTCVNvbWVTdGF0ZTESMBAGA1UEBxMJU29tZXdoZXJlMQ4wDAYDVQQK\12" - "EwVTb21lTzEPMA0GA1UECxMGU29tZU9VMRIwEAYDVQQDEwkxMjcuMC4wLjEwggEi\12" - "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQClc1veJUZSLwl/RNVTzAf4O729\12" - "JA8kgL0z3o2pk3ZLNm18uf/JgROh1DtzbSXAqzT2J1Xz1hnr/tIeM/xr11tC87JY\12" - "7W4XgStB1hQJzb9VZegjIKCJkpYSToG0JnFTaa5419fil9JBhYxFI9RA+PxWh3nK\12" - "idqvr5zZzEVASbOUaUDk+KdmXyVRzh1IH3J1RSSbPrBsHk7cKurLD5kpxDnlFE36\12" - "2oxEt9qSBoXYLPlb8TWHnm5N8bPs9+ABifRq0dYk5ACpA9bKJB8aYyRQKFuwv3v+\12" - "2iDE3YvU5E9TtpMPWc0tPbr793I3bbv/HCZ1YiSKTE7rVmiD4/dxJwxmjxrbAgMB\12" - "AAGjITAfMB0GA1UdDgQWBBQoE3QwP1us/GcEf3dDYpD+TiWxPzANBgkqhkiG9w0B\12" - "AQsFAAOCAQEAeM/dG4lIBWtZGJ3OZDtK0NriNWe5bMHgHPJnGtTzwYvP8fmp55yN\12" - "fVt56qYr9CeQXCuL2d0PgVZLcSrza1mjdvZzQIB77Jwzm5peOVaOUswrIQQeEkeV\12" - "w5XvVx9ywJqPALpeKpJuTgJsgmjA82a2A6gdh5BG8IqWxPzXH9XpEWFACjpz2/eU\12" - "x0nOh6fzrGr0Vp2TSzriOxW2ikM2LzenoyErD/3eCeH75fzH/pT8iQqqlM1Xpu/z\12" - "lddbgced8jJNj5MQQpKpDJMBTuRJtg1KtbgiS+eexxo1jXh9lpn3/47DUe3sNl5O\12" - "5TiDOVzNL4Lo/61ZRfngJJpeu6rYvvw5iA==\12" + "BAoTBVNvbWVPMQ8wDQYDVQQLEwZTb21lT1UxEDAOBgNVBAMTBzEuMi4zLjQwIBcN\12" + "MjIwMzI1MjAzNzM3WhgPMjEyMjAzMDEyMDM3MzdaMGgxCzAJBgNVBAYTAlVTMRIw\12" + "EAYDVQQIEwlTb21lU3RhdGUxEjAQBgNVBAcTCVNvbWV3aGVyZTEOMAwGA1UEChMF\12" + "U29tZU8xDzANBgNVBAsTBlNvbWVPVTEQMA4GA1UEAxMHMS4yLjMuNDCCASIwDQYJ\12" + "KoZIhvcNAQEBBQADggEPADCCAQoCggEBAIEmKUqWeRb9WGFLjE4OVOC99643Xz2s\12" + "BahaHpoEvUW7r0gO6BxQ6b6KkiZbs5OfqX4MYheEUePQq3v2OJ1nAUTSiXDwCOUq\12" + "3ZhS9CS4NlNaIqF4MIoPxaQYqG3jhUB/fNkg9o4DgrH0DmnGd6Mgw2/hUvNGq8IW\12" + "JdlMgZGnX2cIhGQ0Cu/HV372IoYNotGEncyJEg/0ZiJDUyTWV91WoRY767GqIxn/\12" + "lROrsiTzF/xzqcBdOCaMWP3et3X+jrk/i2957mw7bYYRuD415/pHlQqQQItkrmip\12" + "uHJXHF8Ah0blqvFeUsBNMmzIAZblbLBbnc27tbqzUkRRjtR59suExukCAwEAAaMh\12" + "MB8wHQYDVR0OBBYEFCECHg0GKw4U7/NSdq7QmEXgLydVMA0GCSqGSIb3DQEBCwUA\12" + "A4IBAQAz5CAdtEcTa830ClNmR/FRLi0OkjmBd2neylflvQcpoMP/26vkdcf+5JqH\12" + "+WRemkv5X7BgkdAyiQcQXal33i7ykPFjYzH0myMfknIFvmuxexgBth0cPFOsZw3x\12" + "ouQSEkvVuR4q8hW77o9um0e61cTI5Qi6oToA1VXTzkwu8tcY4JcFkgskf4xRX9Qf\12" + "VhuoLllozdhjShd8abWvYdZZEX3EdNVjMHWojPgEvgQzjKOOMz+EbT8YsF9+Nu1p\12" + "INYMLWZ/2KDTcKOHEF2E0YbCbxiSEi32tjD40u39XcidA7vh0w9bHEujeqdQa9fs\12" + "LDeLr91cBnfxzH8fxEj4iMkyV7gj\12" "-----END CERTIFICATE-----\12"; } - static const char* combined_pem() { - std::string combo = mock_pem(); - combo.append(cassandra_pem()); + static const char* multi_cert_pem() { + std::string combo = dummy_pem(); combo.append("\n"); + combo.append(cassandra_pem()); return combo.c_str(); } diff --git a/tests/src/integration/tests/test_ssl.cpp b/tests/src/integration/tests/test_ssl.cpp index f76bb646c..01904597d 100644 --- a/tests/src/integration/tests/test_ssl.cpp +++ b/tests/src/integration/tests/test_ssl.cpp @@ -179,23 +179,7 @@ CASSANDRA_INTEGRATION_TEST_F(SslTests, VerifyPeerMultipleCerts) { Ssl ssl; ssl.with_verify_flags(CASS_SSL_VERIFY_PEER_CERT); - ssl.add_trusted_cert(SslCertificates::combined_pem()); - - Cluster cluster = default_cluster().with_ssl(ssl); - connect(cluster); - write_and_read(); -} - -/** - * Ensures SSL connection verifying peer/server certificate and identity while performing write and - * read operations. - */ -CASSANDRA_INTEGRATION_TEST_F(SslTests, VerifyPeerIdentityMultipleCerts) { - CHECK_FAILURE; - - Ssl ssl; - ssl.with_verify_flags(CASS_SSL_VERIFY_PEER_IDENTITY); - ssl.add_trusted_cert(SslCertificates::combined_pem()); + ssl.add_trusted_cert(SslCertificates::multi_cert_pem()); Cluster cluster = default_cluster().with_ssl(ssl); connect(cluster); From 7e4d6a33f88c6af2bc1d041b60e6004007217c2f Mon Sep 17 00:00:00 2001 From: Bret McGuire Date: Mon, 28 Mar 2022 15:45:28 -0500 Subject: [PATCH 3/3] Formatting fix (to make clang-format happy) --- src/ssl/ssl_openssl_impl.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ssl/ssl_openssl_impl.cpp b/src/ssl/ssl_openssl_impl.cpp index 7810fd24f..06d1ba73d 100644 --- a/src/ssl/ssl_openssl_impl.cpp +++ b/src/ssl/ssl_openssl_impl.cpp @@ -560,10 +560,8 @@ CassError OpenSslContext::add_trusted_cert(const char* cert, size_t cert_length) int num_certs = 0; // Iterate over the bio, reading out as many certificates as possible. - for (X509* cert = PEM_read_bio_X509(bio, NULL, pem_password_callback, NULL); - cert != NULL; - cert = PEM_read_bio_X509(bio, NULL, pem_password_callback, NULL)) - { + for (X509* cert = PEM_read_bio_X509(bio, NULL, pem_password_callback, NULL); cert != NULL; + cert = PEM_read_bio_X509(bio, NULL, pem_password_callback, NULL)) { X509_STORE_add_cert(trusted_store_, cert); X509_free(cert); num_certs++;