diff --git a/doc/configuration.txt b/doc/configuration.txt index 9f4d1ef6d..d323c33ae 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -25659,6 +25659,7 @@ ssl_fc_client_early_traffic_secret string ssl_fc_client_handshake_traffic_secret string ssl_fc_client_random binary ssl_fc_client_traffic_secret_0 string +ssl_fc_crtname string ssl_fc_curve string ssl_fc_early_exporter_secret string ssl_fc_ecformats_bin binary @@ -26283,6 +26284,21 @@ ssl_fc_client_traffic_secret_0 : string activated with "tune.ssl.keylog on" in the global section. See also "tune.ssl.keylog" +ssl_fc_crtname : string + Returns the name of the certificate that was selected for the incoming + SSL/TLS connection. This is the name as it appears in "show ssl cert": it + may be the filename with its relative or absolute path, or an alias, + depending on how the certificate was declared in the configuration. + + Example : + crt-store example + load crt "example.com.pem" + + frontend www + bind *:443 ssl crt "@example/example.com.pem" + acl match_certificate ssl_fc_crtname -m beg -i "@example/" + http-request set-header X-Cert-Name %[ssl_fc_crtname] if match_certificate + ssl_fc_curve : string Returns the name of the curve used in the key agreement when the incoming connection was made over an SSL/TLS transport layer. This requires diff --git a/include/haproxy/ssl_sock.h b/include/haproxy/ssl_sock.h index e8edad0e9..d60584397 100644 --- a/include/haproxy/ssl_sock.h +++ b/include/haproxy/ssl_sock.h @@ -54,6 +54,7 @@ extern struct xprt_ops ssl_sock; extern int ssl_capture_ptr_index; extern int ssl_keylog_index; extern int ssl_client_sni_index; +extern int ssl_crtname_index; extern struct pool_head *pool_head_ssl_keylog; extern struct pool_head *pool_head_ssl_keylog_str; extern struct list openssl_providers; diff --git a/src/ssl_sample.c b/src/ssl_sample.c index fdbbdd3e8..35850c29e 100644 --- a/src/ssl_sample.c +++ b/src/ssl_sample.c @@ -2034,6 +2034,39 @@ smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, #endif } +/* ssl_fc_crtname */ +static int smp_fetch_ssl_fc_crtname(const struct arg *args, struct sample *smp, const char *kw, void *private) +{ + struct connection *conn; + SSL *ssl; + SSL_CTX *ctx; + + smp->flags = SMP_F_VOL_SESS | SMP_F_CONST; + smp->data.type = SMP_T_STR; + + if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) + conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL; + else + conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) : + smp->strm ? sc_conn(smp->strm->scb) : NULL; + + ssl = ssl_sock_get_ssl_object(conn); + if (!ssl) + return 0; + + ctx = SSL_get_SSL_CTX(ssl); + if (!ctx) + return 0; + + smp->data.u.str.area = SSL_CTX_get_ex_data(ctx, ssl_crtname_index); + if (!smp->data.u.str.area) + return 0; + smp->data.u.str.data = strlen(smp->data.u.str.area); + + return 1; +} + + #ifdef USE_ECH static int smp_fetch_ssl_fc_ech_status(const struct arg *args, struct sample *smp, @@ -2768,6 +2801,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { #endif { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, + { "ssl_fc_crtname", smp_fetch_ssl_fc_crtname, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, #ifdef USE_ECH { "ssl_fc_ech_status", smp_fetch_ssl_fc_ech_status, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, { "ssl_fc_ech_outer_sni", smp_fetch_ssl_fc_ech_outer_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 9544deffc..5c410f2a8 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -764,6 +764,8 @@ int ssl_client_crt_ref_index = -1; /* Used to store the client's SNI in case of ClientHello callback error */ int ssl_client_sni_index = -1; +/* store the name of the certificate */ +int ssl_crtname_index = -1; #if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0) struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference); @@ -3160,6 +3162,7 @@ int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME STACK_OF(GENERAL_NAME) *names; #endif + char *crtname = NULL; struct ckch_data *data; struct ckch_inst *ckch_inst = NULL; int errcode = 0; @@ -3179,6 +3182,16 @@ int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct goto error; } + crtname = strdup(path); + if (!crtname) { + memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n", + err && *err ? *err : "", path); + errcode |= ERR_ALERT | ERR_FATAL; + goto error; + } + + SSL_CTX_set_ex_data(ctx, ssl_crtname_index, crtname); + if (global_ssl.security_level > -1) SSL_CTX_set_security_level(ctx, global_ssl.security_level); @@ -8361,6 +8374,11 @@ static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA * pool_free(pool_head_ssl_capture, ptr); } +static void ssl_sock_free_crtname(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp) +{ + free(ptr); +} + #ifdef HAVE_SSL_KEYLOG static void ssl_sock_keylog_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp) { @@ -8488,6 +8506,8 @@ static void __ssl_sock_init(void) #endif ssl_client_crt_ref_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_clt_crt_free_func); ssl_client_sni_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_clt_sni_free_func); + ssl_crtname_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_free_crtname); + #if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE) ENGINE_load_builtin_engines(); hap_register_post_check(ssl_check_async_engine_count);