Skip to content

Commit 71fa44c

Browse files
committed
CONC-698: certificate info is read on every connect
Part 1: Fix for OpenSSL and Schannel
1 parent f97bb2e commit 71fa44c

File tree

5 files changed

+74
-42
lines changed

5 files changed

+74
-42
lines changed

include/ma_tls.h

+2
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp
150150
int ma_tls_get_protocol_version(MARIADB_TLS *ctls);
151151
const char *ma_pvio_tls_get_protocol_version(MARIADB_TLS *ctls);
152152
int ma_pvio_tls_get_protocol_version_id(MARIADB_TLS *ctls);
153+
unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls);
153154
void ma_tls_set_connection(MYSQL *mysql);
154155

155156
/* Function prototypes */
@@ -164,5 +165,6 @@ my_bool ma_pvio_tls_check_fp(MARIADB_TLS *ctls, const char *fp, const char *fp_l
164165
my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio);
165166
void ma_pvio_tls_set_connection(MYSQL *mysql);
166167
void ma_pvio_tls_end();
168+
unsigned int ma_pvio_tls_get_peer_cert_info(MARIADB_TLS *ctls);
167169

168170
#endif /* _ma_tls_h_ */

libmariadb/ma_tls.c

+5
Original file line numberDiff line numberDiff line change
@@ -269,4 +269,9 @@ void ma_pvio_tls_set_connection(MYSQL *mysql)
269269
{
270270
ma_tls_set_connection(mysql);
271271
}
272+
273+
unsigned int ma_pvio_tls_get_peer_cert_info(MARIADB_TLS *ctls)
274+
{
275+
return ma_tls_get_peer_cert_info(ctls);
276+
}
272277
#endif /* HAVE_TLS */

libmariadb/mariadb_lib.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -4537,7 +4537,13 @@ my_bool mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *arg, ...
45374537
switch(value) {
45384538
#ifdef HAVE_TLS
45394539
case MARIADB_TLS_PEER_CERT_INFO:
4540-
*((MARIADB_X509_INFO **)arg)= mysql->net.pvio->ctls ? (MARIADB_X509_INFO *)&mysql->net.pvio->ctls->cert_info : NULL;
4540+
if (mysql->net.pvio->ctls)
4541+
{
4542+
if (!ma_pvio_tls_get_peer_cert_info(mysql->net.pvio->ctls))
4543+
*((MARIADB_X509_INFO **)arg)= (MARIADB_X509_INFO *)&mysql->net.pvio->ctls->cert_info;
4544+
return 0;
4545+
}
4546+
*((MARIADB_X509_INFO **)arg)= NULL;
45414547
break;
45424548
#endif
45434549
case MARIADB_MAX_ALLOWED_PACKET:

libmariadb/secure/openssl.c

+51-35
Original file line numberDiff line numberDiff line change
@@ -459,14 +459,64 @@ void *ma_tls_init(MYSQL *mysql)
459459
return NULL;
460460
}
461461

462+
unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls)
463+
{
464+
X509 *cert;
465+
SSL *ssl;
466+
467+
if (!ctls || !ctls->ssl)
468+
return 1;
469+
470+
/* Did we already read peer cert information ? */
471+
if (ctls->cert_info.version)
472+
return 0;
473+
474+
ssl= (SSL *)ctls->ssl;
475+
476+
/* Store peer certificate information */
477+
if ((cert= SSL_get_peer_certificate(ssl)))
478+
{
479+
char fp[33];
480+
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
481+
const ASN1_TIME *not_before= X509_get0_notBefore(cert),
482+
*not_after= X509_get0_notAfter(cert);
483+
ASN1_TIME_to_tm(not_before, (struct tm *)&ctls->cert_info.not_before);
484+
ASN1_TIME_to_tm(not_after, (struct tm *)&ctls->cert_info.not_after);
485+
#else
486+
const ASN1_TIME *not_before= X509_get_notBefore(cert),
487+
*not_after= X509_get_notAfter(cert);
488+
time_t now, from, to;
489+
int pday, psec;
490+
/* ANS1_TIME_diff returns days and seconds between now and the
491+
specified ASN1_TIME */
492+
time(&now);
493+
ASN1_TIME_diff(&pday, &psec, not_before, NULL);
494+
from= now - (pday * 86400 + psec);
495+
gmtime_r(&from, &ctls->cert_info.not_before);
496+
ASN1_TIME_diff(&pday, &psec, NULL, not_after);
497+
to= now + (pday * 86400 + psec);
498+
gmtime_r(&to, &ctls->cert_info.not_after);
499+
#endif
500+
ctls->cert_info.subject= X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
501+
ctls->cert_info.issuer= X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
502+
ctls->cert_info.version= X509_get_version(cert) + 1;
503+
504+
ma_tls_get_finger_print(ctls, MA_HASH_SHA256, fp, 33);
505+
mysql_hex_string(ctls->cert_info.fingerprint, fp, 32);
506+
507+
X509_free(cert);
508+
return 0;
509+
}
510+
return 1;
511+
}
512+
462513
my_bool ma_tls_connect(MARIADB_TLS *ctls)
463514
{
464515
SSL *ssl = (SSL *)ctls->ssl;
465516
my_bool blocking, try_connect= 1;
466517
MYSQL *mysql;
467518
MARIADB_PVIO *pvio;
468519
int rc;
469-
X509 *cert;
470520
#ifdef OPENSSL_USE_BIOMETHOD
471521
BIO_METHOD *bio_method= NULL;
472522
BIO *bio;
@@ -533,40 +583,6 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
533583
}
534584
pvio->ctls->ssl= ctls->ssl= (void *)ssl;
535585

536-
/* Store peer certificate information */
537-
if ((cert= SSL_get_peer_certificate(ssl)))
538-
{
539-
char fp[33];
540-
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
541-
const ASN1_TIME *not_before= X509_get0_notBefore(cert),
542-
*not_after= X509_get0_notAfter(cert);
543-
ASN1_TIME_to_tm(not_before, (struct tm *)&ctls->cert_info.not_before);
544-
ASN1_TIME_to_tm(not_after, (struct tm *)&ctls->cert_info.not_after);
545-
#else
546-
const ASN1_TIME *not_before= X509_get_notBefore(cert),
547-
*not_after= X509_get_notAfter(cert);
548-
time_t now, from, to;
549-
int pday, psec;
550-
/* ANS1_TIME_diff returns days and seconds between now and the
551-
specified ASN1_TIME */
552-
time(&now);
553-
ASN1_TIME_diff(&pday, &psec, not_before, NULL);
554-
from= now - (pday * 86400 + psec);
555-
gmtime_r(&from, &ctls->cert_info.not_before);
556-
ASN1_TIME_diff(&pday, &psec, NULL, not_after);
557-
to= now + (pday * 86400 + psec);
558-
gmtime_r(&to, &ctls->cert_info.not_after);
559-
#endif
560-
ctls->cert_info.subject= X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
561-
ctls->cert_info.issuer= X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
562-
ctls->cert_info.version= X509_get_version(cert) + 1;
563-
564-
ma_tls_get_finger_print(ctls, MA_HASH_SHA256, fp, 33);
565-
mysql_hex_string(ctls->cert_info.fingerprint, fp, 32);
566-
567-
X509_free(cert);
568-
}
569-
570586
return 0;
571587
}
572588

libmariadb/secure/schannel.c

+9-6
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ char tls_library_version[] = "Schannel";
3232
#define PROT_TLS1_2 4
3333
#define PROT_TLS1_3 8
3434

35-
unsigned int ma_set_tls_x509_info(MARIADB_TLS *ctls);
36-
3735
static struct
3836
{
3937
DWORD cipher_id;
@@ -450,16 +448,14 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
450448
if (ma_schannel_client_handshake(ctls) != SEC_E_OK)
451449
goto end;
452450

453-
verify_certs = mysql->options.ssl_ca || mysql->options.ssl_capath ||
451+
verify_certs = mysql->options.ssl_ca || mysql->options.ssl_capath ||
454452
!mysql->options.extension->tls_allow_invalid_server_cert;
455453

456454
if (verify_certs)
457455
{
458456
if (!ma_schannel_verify_certs(ctls, !mysql->options.extension->tls_allow_invalid_server_cert))
459457
goto end;
460458
}
461-
462-
ma_set_tls_x509_info(ctls);
463459
rc = 0;
464460

465461
end:
@@ -580,7 +576,7 @@ static void ma_systime_to_tm(SYSTEMTIME sys_tm, struct tm *tm)
580576
tm->tm_min = sys_tm.wMinute;
581577
}
582578

583-
unsigned int ma_set_tls_x509_info(MARIADB_TLS *ctls)
579+
unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls)
584580
{
585581
PCCERT_CONTEXT pCertCtx= NULL;
586582
SC_CTX *sctx= (SC_CTX *)ctls->ssl;
@@ -589,6 +585,13 @@ unsigned int ma_set_tls_x509_info(MARIADB_TLS *ctls)
589585
SYSTEMTIME tm;
590586
char fp[33];
591587

588+
if (!ctls || !sctx)
589+
return 1;
590+
591+
/* Did we already read peer cert information ? */
592+
if (ctls->cert_info.version)
593+
return 0;
594+
592595
if (QueryContextAttributes(&sctx->hCtxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pCertCtx) != SEC_E_OK)
593596
return 1;
594597

0 commit comments

Comments
 (0)