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); int ma_tls_get_protocol_version(MARIADB_TLS *ctls);
const char *ma_pvio_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); 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); void ma_tls_set_connection(MYSQL *mysql);
/* Function prototypes */ /* 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); my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio);
void ma_pvio_tls_set_connection(MYSQL *mysql); void ma_pvio_tls_set_connection(MYSQL *mysql);
void ma_pvio_tls_end(); void ma_pvio_tls_end();
unsigned int ma_pvio_tls_get_peer_cert_info(MARIADB_TLS *ctls);
#endif /* _ma_tls_h_ */ #endif /* _ma_tls_h_ */

View File

@@ -269,4 +269,9 @@ void ma_pvio_tls_set_connection(MYSQL *mysql)
{ {
ma_tls_set_connection(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 */ #endif /* HAVE_TLS */

View File

@@ -4537,7 +4537,13 @@ my_bool mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *arg, ...
switch(value) { switch(value) {
#ifdef HAVE_TLS #ifdef HAVE_TLS
case MARIADB_TLS_PEER_CERT_INFO: 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; break;
#endif #endif
case MARIADB_MAX_ALLOWED_PACKET: case MARIADB_MAX_ALLOWED_PACKET:

View File

@@ -459,6 +459,57 @@ error:
return NULL; 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) my_bool ma_tls_connect(MARIADB_TLS *ctls)
{ {
SSL *ssl = (SSL *)ctls->ssl; SSL *ssl = (SSL *)ctls->ssl;
@@ -466,7 +517,6 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
MYSQL *mysql; MYSQL *mysql;
MARIADB_PVIO *pvio; MARIADB_PVIO *pvio;
int rc; int rc;
X509 *cert;
#ifdef OPENSSL_USE_BIOMETHOD #ifdef OPENSSL_USE_BIOMETHOD
BIO_METHOD *bio_method= NULL; BIO_METHOD *bio_method= NULL;
BIO *bio; BIO *bio;
@@ -533,40 +583,6 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
} }
pvio->ctls->ssl= ctls->ssl= (void *)ssl; 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; return 0;
} }

View File

@@ -32,8 +32,6 @@ char tls_library_version[] = "Schannel";
#define PROT_TLS1_2 4 #define PROT_TLS1_2 4
#define PROT_TLS1_3 8 #define PROT_TLS1_3 8
unsigned int ma_set_tls_x509_info(MARIADB_TLS *ctls);
static struct static struct
{ {
DWORD cipher_id; DWORD cipher_id;
@@ -450,7 +448,7 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
if (ma_schannel_client_handshake(ctls) != SEC_E_OK) if (ma_schannel_client_handshake(ctls) != SEC_E_OK)
goto end; 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; !mysql->options.extension->tls_allow_invalid_server_cert;
if (verify_certs) 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)) if (!ma_schannel_verify_certs(ctls, !mysql->options.extension->tls_allow_invalid_server_cert))
goto end; goto end;
} }
ma_set_tls_x509_info(ctls);
rc = 0; rc = 0;
end: end:
@@ -580,7 +576,7 @@ static void ma_systime_to_tm(SYSTEMTIME sys_tm, struct tm *tm)
tm->tm_min = sys_tm.wMinute; 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; PCCERT_CONTEXT pCertCtx= NULL;
SC_CTX *sctx= (SC_CTX *)ctls->ssl; SC_CTX *sctx= (SC_CTX *)ctls->ssl;
@@ -589,6 +585,13 @@ unsigned int ma_set_tls_x509_info(MARIADB_TLS *ctls)
SYSTEMTIME tm; SYSTEMTIME tm;
char fp[33]; 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) if (QueryContextAttributes(&sctx->hCtxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pCertCtx) != SEC_E_OK)
return 1; return 1;