http/3: report handshake with version and cipher as for TCP connections

Make reporting into separate functions, to be called from QUIC handshakes
as well.

Closes #17922
This commit is contained in:
Stefan Eissing 2025-07-14 09:33:53 +02:00 committed by Daniel Stenberg
parent f98c0ba834
commit 674ad27f77
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
9 changed files with 107 additions and 43 deletions

View file

@ -468,6 +468,7 @@ static int cf_ngtcp2_handshake_completed(ngtcp2_conn *tconn, void *user_data)
ctx->handshake_at = curlx_now();
ctx->tls_handshake_complete = TRUE;
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
Curl_vquic_report_handshake(&ctx->tls, cf, data);
ctx->tls_vrfy_result = Curl_vquic_tls_verify_peer(&ctx->tls, cf,
data, &ctx->peer);

View file

@ -221,4 +221,22 @@ bool Curl_vquic_tls_get_ssl_info(struct curl_tls_ctx *ctx,
#endif
}
void Curl_vquic_report_handshake(struct curl_tls_ctx *ctx,
struct Curl_cfilter *cf,
struct Curl_easy *data)
{
(void)cf;
#ifdef USE_OPENSSL
(void)cf;
Curl_ossl_report_handshake(data, &ctx->ossl);
#elif defined(USE_GNUTLS)
Curl_gtls_report_handshake(data, &ctx->gtls);
#elif defined(USE_WOLFSSL)
Curl_wssl_report_handshake(data, &ctx->wssl);
#else
(void)data;
(void)ctx;
#endif
}
#endif /* !USE_HTTP3 && (USE_OPENSSL || USE_GNUTLS || USE_WOLFSSL) */

View file

@ -111,6 +111,10 @@ bool Curl_vquic_tls_get_ssl_info(struct curl_tls_ctx *ctx,
bool give_ssl_ctx,
struct curl_tlssessioninfo *info);
void Curl_vquic_report_handshake(struct curl_tls_ctx *ctx,
struct Curl_cfilter *cf,
struct Curl_easy *data);
#endif /* !USE_HTTP3 && (USE_OPENSSL || USE_GNUTLS || USE_WOLFSSL) */
#endif /* HEADER_CURL_VQUIC_TLS_H */

View file

@ -1307,6 +1307,28 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
return result;
}
void Curl_gtls_report_handshake(struct Curl_easy *data,
struct gtls_ctx *gctx)
{
#ifndef CURL_DISABLE_VERBOSE_STRINGS
if(Curl_trc_is_verbose(data)) {
const char *ptr;
gnutls_protocol_t version = gnutls_protocol_get_version(gctx->session);
/* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(gctx->session),
gnutls_cipher_get(gctx->session),
gnutls_mac_get(gctx->session));
infof(data, "SSL connection using %s / %s",
gnutls_protocol_get_name(version), ptr);
}
#else
(void)data;
(void)gctx;
#endif
}
CURLcode
Curl_gtls_verifyserver(struct Curl_easy *data,
gnutls_session_t session,
@ -1327,23 +1349,11 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
int rc;
CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
const char *ptr;
int algo;
unsigned int bits;
gnutls_protocol_t version = gnutls_protocol_get_version(session);
#endif
long * const certverifyresult = &ssl_config->certverifyresult;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
/* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
gnutls_cipher_get(session),
gnutls_mac_get(session));
infof(data, "SSL connection using %s / %s",
gnutls_protocol_get_name(version), ptr);
#endif
/* This function will return the peer's raw certificate (chain) as sent by
the peer. These certificates are in raw format (DER encoded for
X.509). In case of a X.509 then a certificate list may be present. The
@ -1876,6 +1886,9 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
if(connssl->connecting_state == ssl_connect_3) {
gnutls_datum_t proto;
int rc;
Curl_gtls_report_handshake(data, &backend->gtls);
result = gtls_verifyserver(cf, data, backend->gtls.session);
if(result)
goto out;

View file

@ -117,6 +117,10 @@ CURLcode Curl_gtls_cache_session(struct Curl_cfilter *cf,
unsigned char *quic_tp,
size_t quic_tp_len);
/* Report properties of a successful handshake */
void Curl_gtls_report_handshake(struct Curl_easy *data,
struct gtls_ctx *gctx);
extern const struct Curl_ssl Curl_ssl_gnutls;
#endif /* USE_GNUTLS */

View file

@ -4334,6 +4334,38 @@ static CURLcode ossl_on_session_reuse(struct Curl_cfilter *cf,
return result;
}
void Curl_ossl_report_handshake(struct Curl_easy *data,
struct ossl_ctx *octx)
{
#ifndef CURL_DISABLE_VERBOSE_STRINGS
if(Curl_trc_is_verbose(data)) {
int psigtype_nid = NID_undef;
const char *negotiated_group_name = NULL;
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
SSL_get_peer_signature_type_nid(octx->ssl, &psigtype_nid);
#if (OPENSSL_VERSION_NUMBER >= 0x30200000L)
negotiated_group_name = SSL_get0_group_name(octx->ssl);
#else
negotiated_group_name =
OBJ_nid2sn(SSL_get_negotiated_group(octx->ssl) & 0x0000FFFF);
#endif
#endif
/* Informational message */
infof(data, "SSL connection using %s / %s / %s / %s",
SSL_get_version(octx->ssl),
SSL_get_cipher(octx->ssl),
negotiated_group_name ? negotiated_group_name : "[blank]",
OBJ_nid2sn(psigtype_nid));
}
#else
(void)data;
(void)octx;
#endif /* CURL_DISABLE_VERBOSE_STRINGS */
}
static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
@ -4599,28 +4631,9 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
}
}
else {
int psigtype_nid = NID_undef;
const char *negotiated_group_name = NULL;
/* we connected fine, we are not waiting for anything else. */
connssl->connecting_state = ssl_connect_3;
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
SSL_get_peer_signature_type_nid(octx->ssl, &psigtype_nid);
#if (OPENSSL_VERSION_NUMBER >= 0x30200000L)
negotiated_group_name = SSL_get0_group_name(octx->ssl);
#else
negotiated_group_name =
OBJ_nid2sn(SSL_get_negotiated_group(octx->ssl) & 0x0000FFFF);
#endif
#endif
/* Informational message */
infof(data, "SSL connection using %s / %s / %s / %s",
SSL_get_version(octx->ssl),
SSL_get_cipher(octx->ssl),
negotiated_group_name ? negotiated_group_name : "[blank]",
OBJ_nid2sn(psigtype_nid));
Curl_ossl_report_handshake(data, octx);
#ifdef USE_ECH_OPENSSL
# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
@ -4677,10 +4690,10 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
infof(data, "ECH: ech-hard failed");
return CURLE_SSL_CONNECT_ERROR;
}
}
else {
}
else {
infof(data, "ECH: result: status is not attempted");
}
}
# endif /* !OPENSSL_IS_BORINGSSL && !OPENSSL_IS_AWSLC */
#endif /* USE_ECH_OPENSSL */

View file

@ -142,5 +142,9 @@ CURLcode Curl_oss_check_peer_cert(struct Curl_cfilter *cf,
struct ossl_ctx *octx,
struct ssl_peer *peer);
/* Report properties of a successful handshake */
void Curl_ossl_report_handshake(struct Curl_easy *data,
struct ossl_ctx *octx);
#endif /* USE_OPENSSL */
#endif /* HEADER_CURL_SSLUSE_H */

View file

@ -2087,6 +2087,18 @@ static bool wssl_data_pending(struct Curl_cfilter *cf,
return FALSE;
}
void Curl_wssl_report_handshake(struct Curl_easy *data,
struct wssl_ctx *wssl)
{
#if (LIBWOLFSSL_VERSION_HEX >= 0x03009010)
infof(data, "SSL connection using %s / %s",
wolfSSL_get_version(wssl->ssl),
wolfSSL_get_cipher_name(wssl->ssl));
#else
infof(data, "SSL connected");
#endif
}
static CURLcode wssl_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *done)
@ -2160,16 +2172,9 @@ static CURLcode wssl_connect(struct Curl_cfilter *cf,
}
#endif /* HAVE_ALPN */
#if (LIBWOLFSSL_VERSION_HEX >= 0x03009010)
infof(data, "SSL connection using %s / %s",
wolfSSL_get_version(wssl->ssl),
wolfSSL_get_cipher_name(wssl->ssl));
#else
infof(data, "SSL connected");
#endif
connssl->connecting_state = ssl_connect_done;
connssl->state = ssl_connection_complete;
Curl_wssl_report_handshake(data, wssl);
#ifdef WOLFSSL_EARLY_DATA
if(connssl->earlydata_state > ssl_earlydata_none) {

View file

@ -88,6 +88,8 @@ CURLcode Curl_wssl_verify_pinned(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct wssl_ctx *wssl);
void Curl_wssl_report_handshake(struct Curl_easy *data,
struct wssl_ctx *wssl);
#endif /* USE_WOLFSSL */
#endif /* HEADER_CURL_WOLFSSL_H */