diff --git a/include/ma_tls.h b/include/ma_tls.h index 6601f896..23f53560 100644 --- a/include/ma_tls.h +++ b/include/ma_tls.h @@ -150,6 +150,7 @@ unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp int ma_tls_get_protocol_version(MARIADB_TLS *ctls); const char *ma_pvio_tls_get_protocol_version(MARIADB_TLS *ctls); int ma_pvio_tls_get_protocol_version_id(MARIADB_TLS *ctls); +unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls); void ma_tls_set_connection(MYSQL *mysql); /* Function prototypes */ @@ -164,5 +165,6 @@ my_bool ma_pvio_tls_check_fp(MARIADB_TLS *ctls, const char *fp, const char *fp_l my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio); void ma_pvio_tls_set_connection(MYSQL *mysql); void ma_pvio_tls_end(); +unsigned int ma_pvio_tls_get_peer_cert_info(MARIADB_TLS *ctls); #endif /* _ma_tls_h_ */ diff --git a/libmariadb/ma_tls.c b/libmariadb/ma_tls.c index 432a0f4a..1bda7dcf 100644 --- a/libmariadb/ma_tls.c +++ b/libmariadb/ma_tls.c @@ -269,4 +269,9 @@ void ma_pvio_tls_set_connection(MYSQL *mysql) { ma_tls_set_connection(mysql); } + +unsigned int ma_pvio_tls_get_peer_cert_info(MARIADB_TLS *ctls) +{ + return ma_tls_get_peer_cert_info(ctls); +} #endif /* HAVE_TLS */ diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index b4a36585..14185b0b 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -4537,7 +4537,13 @@ my_bool mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *arg, ... switch(value) { #ifdef HAVE_TLS case MARIADB_TLS_PEER_CERT_INFO: - *((MARIADB_X509_INFO **)arg)= mysql->net.pvio->ctls ? (MARIADB_X509_INFO *)&mysql->net.pvio->ctls->cert_info : NULL; + if (mysql->net.pvio->ctls) + { + if (!ma_pvio_tls_get_peer_cert_info(mysql->net.pvio->ctls)) + *((MARIADB_X509_INFO **)arg)= (MARIADB_X509_INFO *)&mysql->net.pvio->ctls->cert_info; + return 0; + } + *((MARIADB_X509_INFO **)arg)= NULL; break; #endif case MARIADB_MAX_ALLOWED_PACKET: diff --git a/libmariadb/secure/openssl.c b/libmariadb/secure/openssl.c index 828c3121..8231a244 100644 --- a/libmariadb/secure/openssl.c +++ b/libmariadb/secure/openssl.c @@ -459,6 +459,57 @@ error: return NULL; } +unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls) +{ + X509 *cert; + SSL *ssl; + + if (!ctls || !ctls->ssl) + return 1; + + /* Did we already read peer cert information ? */ + if (ctls->cert_info.version) + return 0; + + ssl= (SSL *)ctls->ssl; + + /* Store peer certificate information */ + if ((cert= SSL_get_peer_certificate(ssl))) + { + char fp[33]; +#if OPENSSL_VERSION_NUMBER >= 0x10101000L + const ASN1_TIME *not_before= X509_get0_notBefore(cert), + *not_after= X509_get0_notAfter(cert); + ASN1_TIME_to_tm(not_before, (struct tm *)&ctls->cert_info.not_before); + ASN1_TIME_to_tm(not_after, (struct tm *)&ctls->cert_info.not_after); +#else + const ASN1_TIME *not_before= X509_get_notBefore(cert), + *not_after= X509_get_notAfter(cert); + time_t now, from, to; + int pday, psec; + /* ANS1_TIME_diff returns days and seconds between now and the + specified ASN1_TIME */ + time(&now); + ASN1_TIME_diff(&pday, &psec, not_before, NULL); + from= now - (pday * 86400 + psec); + gmtime_r(&from, &ctls->cert_info.not_before); + ASN1_TIME_diff(&pday, &psec, NULL, not_after); + to= now + (pday * 86400 + psec); + gmtime_r(&to, &ctls->cert_info.not_after); +#endif + ctls->cert_info.subject= X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); + ctls->cert_info.issuer= X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); + ctls->cert_info.version= X509_get_version(cert) + 1; + + ma_tls_get_finger_print(ctls, MA_HASH_SHA256, fp, 33); + mysql_hex_string(ctls->cert_info.fingerprint, fp, 32); + + X509_free(cert); + return 0; + } + return 1; +} + my_bool ma_tls_connect(MARIADB_TLS *ctls) { SSL *ssl = (SSL *)ctls->ssl; @@ -466,7 +517,6 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls) MYSQL *mysql; MARIADB_PVIO *pvio; int rc; - X509 *cert; #ifdef OPENSSL_USE_BIOMETHOD BIO_METHOD *bio_method= NULL; BIO *bio; @@ -533,40 +583,6 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls) } pvio->ctls->ssl= ctls->ssl= (void *)ssl; - /* Store peer certificate information */ - if ((cert= SSL_get_peer_certificate(ssl))) - { - char fp[33]; -#if OPENSSL_VERSION_NUMBER >= 0x10101000L - const ASN1_TIME *not_before= X509_get0_notBefore(cert), - *not_after= X509_get0_notAfter(cert); - ASN1_TIME_to_tm(not_before, (struct tm *)&ctls->cert_info.not_before); - ASN1_TIME_to_tm(not_after, (struct tm *)&ctls->cert_info.not_after); -#else - const ASN1_TIME *not_before= X509_get_notBefore(cert), - *not_after= X509_get_notAfter(cert); - time_t now, from, to; - int pday, psec; - /* ANS1_TIME_diff returns days and seconds between now and the - specified ASN1_TIME */ - time(&now); - ASN1_TIME_diff(&pday, &psec, not_before, NULL); - from= now - (pday * 86400 + psec); - gmtime_r(&from, &ctls->cert_info.not_before); - ASN1_TIME_diff(&pday, &psec, NULL, not_after); - to= now + (pday * 86400 + psec); - gmtime_r(&to, &ctls->cert_info.not_after); -#endif - ctls->cert_info.subject= X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); - ctls->cert_info.issuer= X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); - ctls->cert_info.version= X509_get_version(cert) + 1; - - ma_tls_get_finger_print(ctls, MA_HASH_SHA256, fp, 33); - mysql_hex_string(ctls->cert_info.fingerprint, fp, 32); - - X509_free(cert); - } - return 0; } diff --git a/libmariadb/secure/schannel.c b/libmariadb/secure/schannel.c index a6617d2e..b71d9cf1 100644 --- a/libmariadb/secure/schannel.c +++ b/libmariadb/secure/schannel.c @@ -32,8 +32,6 @@ char tls_library_version[] = "Schannel"; #define PROT_TLS1_2 4 #define PROT_TLS1_3 8 -unsigned int ma_set_tls_x509_info(MARIADB_TLS *ctls); - static struct { DWORD cipher_id; @@ -450,7 +448,7 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls) if (ma_schannel_client_handshake(ctls) != SEC_E_OK) goto end; - verify_certs = mysql->options.ssl_ca || mysql->options.ssl_capath || + verify_certs = mysql->options.ssl_ca || mysql->options.ssl_capath || !mysql->options.extension->tls_allow_invalid_server_cert; if (verify_certs) @@ -458,8 +456,6 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls) if (!ma_schannel_verify_certs(ctls, !mysql->options.extension->tls_allow_invalid_server_cert)) goto end; } - - ma_set_tls_x509_info(ctls); rc = 0; end: @@ -580,7 +576,7 @@ static void ma_systime_to_tm(SYSTEMTIME sys_tm, struct tm *tm) tm->tm_min = sys_tm.wMinute; } -unsigned int ma_set_tls_x509_info(MARIADB_TLS *ctls) +unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls) { PCCERT_CONTEXT pCertCtx= NULL; SC_CTX *sctx= (SC_CTX *)ctls->ssl; @@ -589,6 +585,13 @@ unsigned int ma_set_tls_x509_info(MARIADB_TLS *ctls) SYSTEMTIME tm; char fp[33]; + if (!ctls || !sctx) + return 1; + + /* Did we already read peer cert information ? */ + if (ctls->cert_info.version) + return 0; + if (QueryContextAttributes(&sctx->hCtxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pCertCtx) != SEC_E_OK) return 1;