diff --git a/doc/configuration.txt b/doc/configuration.txt index 4bcf4ea6b..136a7b749 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -25028,6 +25028,15 @@ ssl_fc_curve : string connection was made over an SSL/TLS transport layer. This requires OpenSSL >= 3.0.0. +ssl_fc_early_rcvd : boolean + Returns true if early data were seen over that connection, regardless of the + fact that the handshake has since completed. It has no practical use case for + traffic processing, however it's about the only way to "see" that a client + used 0-RTT to send early data, and is sometimes useful when debugging, since + the only other alternatives are network traffic captures or logging the front + connection's flags and matching them in the code. It may also be useful to + get statistics on clients' capabilities. See also "ssl_fc_has_early". + ssl_fc_early_exporter_secret : string Return the EARLY_EXPORTER_SECRET as an hexadecimal string for the front connection when the incoming connection was made over an TLS 1.3 @@ -25133,7 +25142,8 @@ ssl_fc_has_crt : boolean ssl_fc_has_early : boolean Returns true if early data were sent, and the handshake didn't complete yet. As it has security implications, it is useful to be able to refuse those, or - wait until the handshake completes (via the "wait-for-handshake" action). + wait until the handshake completes (via the "wait-for-handshake" action). See + also "ssl_fc_early_rcvd". ssl_fc_has_sni : boolean This checks for the presence of a Server Name Indication TLS extension (SNI) diff --git a/src/ssl_sample.c b/src/ssl_sample.c index c64522d24..4746b8c0c 100644 --- a/src/ssl_sample.c +++ b/src/ssl_sample.c @@ -574,6 +574,27 @@ smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const cha return 1; } +static int +smp_fetch_ssl_fc_early_rcvd(const struct arg *args, struct sample *smp, const char *kw, void *private) +{ + SSL *ssl; + struct connection *conn; + + conn = objt_conn(smp->sess->origin); + ssl = ssl_sock_get_ssl_object(conn); + if (!ssl) + return 0; + + smp->flags = 0; + smp->data.type = SMP_T_BOOL; +#ifdef OPENSSL_IS_BORINGSSL + smp->data.u.sint = SSL_early_data_accepted(ssl); +#else + smp->data.u.sint = !!(conn->flags & CO_FL_EARLY_DATA); +#endif + return 1; +} + /* boolean, returns true if client cert was present */ static int smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private) @@ -2515,6 +2536,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { #if (HA_OPENSSL_VERSION_NUMBER >= 0x3000000fL) { "ssl_fc_curve", smp_fetch_ssl_fc_ec, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, #endif + { "ssl_fc_early_rcvd", smp_fetch_ssl_fc_early_rcvd, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI }, { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI }, { "ssl_fc_has_early", smp_fetch_ssl_fc_has_early, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI }, { "ssl_fc_has_sni", smp_fetch_ssl_fc_has_sni, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },