MINOR: ssl: Add ciphers in ssl traces

Decode the contents of the ClientHello ciphers extension and dump a
human readable list in the ssl traces.
This commit is contained in:
Remi Tricot-Le Breton 2025-07-15 10:45:07 +02:00 committed by William Lallemand
parent b0fe453079
commit f00d9bf12d
3 changed files with 56 additions and 5 deletions

View File

@ -22,6 +22,14 @@ extern struct trace_source trace_ssl;
#define SSL_EV_CONN_SWITCHCTX_CB (1ULL << 12)
#define SSL_EV_CONN_CHOOSE_SNI_CTX (1ULL << 13)
#define SSL_EV_CONN_SIGALG_EXT (1ULL << 14)
#define SSL_EV_CONN_CIPHERS_EXT (1ULL << 15)
#define SSL_VERB_CLEAN 1
#define SSL_VERB_MINIMAL 2
#define SSL_VERB_SIMPLE 3
#define SSL_VERB_ADVANCED 4
#define SSL_VERB_COMPLETE 5
#define TRACE_SOURCE &trace_ssl

View File

@ -345,6 +345,21 @@ int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
TRACE_DEVEL("Sigalg parsing: has_rsa_sig (default)", SSL_EV_CONN_SWITCHCTX_CB, conn);
has_rsa_sig = 1;
}
if ((TRACE_SOURCE)->verbosity > SSL_VERB_ADVANCED &&
TRACE_ENABLED(TRACE_LEVEL_DATA, SSL_EV_CONN_CIPHERS_EXT, conn, 0, 0, 0)) {
const uint8_t *cipher_suites;
size_t len;
#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
len = ctx->cipher_suites_len;
cipher_suites = ctx->cipher_suites;
#else
len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
#endif
TRACE_DATA("Ciphers value", SSL_EV_CONN_CIPHERS_EXT, conn, ssl, cipher_suites, &len);
}
if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
const SSL_CIPHER *cipher;
STACK_OF(SSL_CIPHER) *ha_ciphers; /* haproxy side ciphers */

View File

@ -41,6 +41,7 @@ static const struct trace_event ssl_trace_events[] = {
{ .mask = SSL_EV_CONN_SWITCHCTX_CB, .name = "sslc_switchctx_cb", .desc = "SSL switchctx callback"},
{ .mask = SSL_EV_CONN_CHOOSE_SNI_CTX, .name = "sslc_choose_sni_ctx", .desc = "SSL choose sni context"},
{ .mask = SSL_EV_CONN_SIGALG_EXT, .name = "sslc_sigalg_ext", .desc = "SSL sigalg extension parsing"},
{ .mask = SSL_EV_CONN_CIPHERS_EXT, .name = "sslc_ciphers_ext", .desc = "SSL ciphers extension parsing"},
{ }
};
@ -53,15 +54,10 @@ static const struct name_desc ssl_trace_lockon_args[4] = {
};
static const struct name_desc ssl_trace_decoding[] = {
#define SSL_VERB_CLEAN 1
{ .name="clean", .desc="only user-friendly stuff, generally suitable for level \"user\"" },
#define SSL_VERB_MINIMAL 2
{ .name="minimal", .desc="report only conn, no real decoding" },
#define SSL_VERB_SIMPLE 3
{ .name="simple", .desc="add error messages" },
#define SSL_VERB_ADVANCED 4
{ .name="advanced", .desc="add handshake-related details" },
#define SSL_VERB_COMPLETE 5
{ .name="complete", .desc="add full data dump when available" },
{ /* end */ }
};
@ -247,5 +243,37 @@ static void ssl_trace(enum trace_level level, uint64_t mask, const struct trace_
}
}
}
if (mask & SSL_EV_CONN_CIPHERS_EXT && src->verbosity > SSL_VERB_ADVANCED) {
if (a2 && a3 && a4) {
SSL *ssl = (SSL*)a2;
const uint16_t *extension_data = a3;
size_t extension_len = *((size_t*)a4);
int first = 1;
chunk_appendf(&trace_buf, " value=");
while (extension_len > 1) {
const char *str;
const SSL_CIPHER *cipher;
uint16_t id = ntohs(*extension_data);
#if defined(OPENSSL_IS_BORINGSSL)
cipher = SSL_get_cipher_by_value(id);
#else
cipher = SSL_CIPHER_find(ssl, (unsigned char*)extension_data);
#endif
str = SSL_CIPHER_get_name(cipher);
if (!str || strcmp(str, "(NONE)") == 0)
chunk_appendf(&trace_buf, "%sUNKNOWN(%04x)", first ? "" : ",", id);
else
chunk_appendf(&trace_buf, "%s%s", first ? "" : ",", str);
first = 0;
extension_len-=sizeof(*extension_data);
++extension_data;
}
}
}
}