1
0
mirror of https://github.com/mariadb-corporation/mariadb-connector-c.git synced 2025-08-08 14:02:17 +03:00

CONC-698: certificate info is read on every connect

Part 1: Fix for OpenSSL and Schannel
This commit is contained in:
Georg Richter
2024-06-20 08:34:19 +02:00
parent f97bb2e92e
commit 71fa44cff0
5 changed files with 74 additions and 42 deletions

View File

@@ -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_ */

View File

@@ -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 */

View File

@@ -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:

View File

@@ -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;
}

View File

@@ -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;