From 2594747525e7aee2f29dc4ad18fa5ac4f8a8975b Mon Sep 17 00:00:00 2001 From: Max Dymond Date: Thu, 4 Mar 2021 14:13:52 +0000 Subject: [PATCH] Iterate over all certificates in a trusted cert BIO, not just the first Previously the code which loaded a trusted certificate from file only assumed that there was a single certificate in that file, meaning that using a certificate bundle for certificate verification would not work. This fix allows the driver to read multiple trusted certificates out of a BIO and provision them in the trusted certificate store. --- src/ssl/ssl_openssl_impl.cpp | 45 ++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/ssl/ssl_openssl_impl.cpp b/src/ssl/ssl_openssl_impl.cpp index 80e2ab6a4..7810fd24f 100644 --- a/src/ssl/ssl_openssl_impl.cpp +++ b/src/ssl/ssl_openssl_impl.cpp @@ -240,22 +240,6 @@ static int SSL_CTX_use_certificate_chain_bio(SSL_CTX* ctx, BIO* in) { return ret; } -static X509* load_cert(const char* cert, size_t cert_size) { - BIO* bio = BIO_new_mem_buf(const_cast(cert), cert_size); - if (bio == NULL) { - return NULL; - } - - X509* x509 = PEM_read_bio_X509(bio, NULL, pem_password_callback, NULL); - if (x509 == NULL) { - ssl_log_errors("Unable to load certificate"); - } - - BIO_free_all(bio); - - return x509; -} - static EVP_PKEY* load_key(const char* key, size_t key_size, const char* password) { BIO* bio = BIO_new_mem_buf(const_cast(key), key_size); if (bio == NULL) { @@ -568,13 +552,34 @@ SslSession* OpenSslContext::create_session(const Address& address, const String& } CassError OpenSslContext::add_trusted_cert(const char* cert, size_t cert_length) { - X509* x509 = load_cert(cert, cert_length); - if (x509 == NULL) { + BIO* bio = BIO_new_mem_buf(const_cast(cert), cert_length); + if (bio == NULL) { return CASS_ERROR_SSL_INVALID_CERT; } - X509_STORE_add_cert(trusted_store_, x509); - X509_free(x509); + 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)) + { + X509_STORE_add_cert(trusted_store_, cert); + X509_free(cert); + num_certs++; + } + + // Retrieve and discard the error tht terminated the loop, + // so it doesn't cause the next PEM operation to fail mysteriously. + ERR_get_error(); + + BIO_free_all(bio); + + // If no certificates were read from the bio, that is an error. + if (num_certs == 0) { + ssl_log_errors("Unable to load certificate(s)"); + return CASS_ERROR_SSL_INVALID_CERT; + } return CASS_OK; }