From 5027ba36a99754328845386c0f62a646aa02ea54 Mon Sep 17 00:00:00 2001 From: Frederic Lecaille Date: Wed, 10 Sep 2025 18:11:50 +0200 Subject: [PATCH] MINOR: quic-be: make SSL/QUIC objects use their own indexes (ssl_qc_app_data_index) This index is used to retrieve the quic_conn object from its SSL object, the same way the connection is retrieved from its SSL object for SSL/TCP connections. This patch implements two helper functions to avoid the ugly code with such blocks: #ifdef USE_QUIC else if (qc) { .. } #endif Implement ssl_sock_get_listener() to return the listener from an SSL object. Implement ssl_sock_get_conn() to return the connection from an SSL object and optionally a pointer to the ssl_sock_ctx struct attached to the connections or the quic_conns. Use this functions where applicable: - ssl_tlsext_ticket_key_cb() calls ssl_sock_get_listener() - ssl_sock_infocbk() calls ssl_sock_get_conn() - ssl_sock_msgcbk() calls ssl_sock_get_ssl_conn() - ssl_sess_new_srv_cb() calls ssl_sock_get_conn() - ssl_sock_srv_verifycbk() calls ssl_sock_get_conn() Also modify qc_ssl_sess_init() to initialize the ssl_qc_app_data_index index for the QUIC backends. --- include/haproxy/ssl_sock.h | 50 ++++++++++++++++++++++++++++++++++++ src/quic_ssl.c | 1 - src/ssl_sock.c | 52 ++++++++++++-------------------------- 3 files changed, 66 insertions(+), 37 deletions(-) diff --git a/include/haproxy/ssl_sock.h b/include/haproxy/ssl_sock.h index 7c53947b1..d885a1ba0 100644 --- a/include/haproxy/ssl_sock.h +++ b/include/haproxy/ssl_sock.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -188,6 +189,55 @@ static inline void cert_ignerr_bitfield_set_all(unsigned long long *bitfield) memset(bitfield, -1, IGNERR_BF_SIZE*sizeof(*bitfield)); } +/* Listener only function. + * Return the listener attached to SSL object. + */ +static inline struct listener *ssl_sock_get_listener(const SSL *s) +{ + struct connection *conn = SSL_get_ex_data(s, ssl_app_data_index); +#ifdef USE_QUIC + struct quic_conn *qc = SSL_get_ex_data(s, ssl_qc_app_data_index); +#endif + + if (conn) + return __objt_listener(conn->target); +#ifdef USE_QUIC + else if (qc) + return qc->li; +#endif + return NULL; +} + +/* Return the connection from SSL object. + * Note that for QUIC, this function must be called with very much attention. + * Indeed, for QUIC frontends, qc->conn is not always initialized. + * For QUIC backends, this is always the case if the SSL object is released + * at the same time as the connection. + */ +static inline struct connection *ssl_sock_get_conn(const SSL *s, struct ssl_sock_ctx **ctx) +{ + struct connection *ret = NULL; + struct connection *conn = SSL_get_ex_data(s, ssl_app_data_index); +#ifdef USE_QUIC + struct quic_conn *qc = SSL_get_ex_data(s, ssl_qc_app_data_index); +#endif + + if (conn) { + ret = conn; + if (ctx) + *ctx = conn_get_ssl_sock_ctx(conn); + } +#ifdef USE_QUIC + else if (qc) { + ret = qc->conn; + if (ctx) + *ctx = qc->xprt_ctx; + } +#endif + return ret; +} + + #endif /* USE_OPENSSL */ #endif /* _HAPROXY_SSL_SOCK_H */ diff --git a/src/quic_ssl.c b/src/quic_ssl.c index 7e20a906b..60e79a516 100644 --- a/src/quic_ssl.c +++ b/src/quic_ssl.c @@ -1179,7 +1179,6 @@ static int qc_ssl_sess_init(struct quic_conn *qc, SSL_CTX *ssl_ctx, SSL **ssl, } if (!SSL_set_ex_data(*ssl, ssl_qc_app_data_index, qc) || - (!server && !SSL_set_ex_data(*ssl, ssl_app_data_index, conn)) || !quic_ssl_set_tls_cbs(*ssl)) { SSL_free(*ssl); *ssl = NULL; diff --git a/src/ssl_sock.c b/src/ssl_sock.c index e1aa2936d..b973a3967 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -1121,27 +1121,17 @@ static int ssl_hmac_init(MAC_CTX *hctx, unsigned char *key, int key_len, const E static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned char *iv, EVP_CIPHER_CTX *ectx, MAC_CTX *hctx, int enc) { - struct tls_keys_ref *ref = NULL; union tls_sess_key *keys; int head; int i; int ret = -1; /* error by default */ - struct connection *conn = SSL_get_ex_data(s, ssl_app_data_index); -#ifdef USE_QUIC - struct quic_conn *qc = SSL_get_ex_data(s, ssl_qc_app_data_index); -#endif + struct listener *l; + struct tls_keys_ref *ref; - if (conn) - ref = __objt_listener(conn->target)->bind_conf->keys_ref; -#ifdef USE_QUIC - else if (qc) - ref = qc->li->bind_conf->keys_ref; -#endif - - if (!ref) { - /* must never happen */ - ABORT_NOW(); - } + l = ssl_sock_get_listener(s); + BUG_ON(!l); + ref = l->bind_conf->keys_ref; + BUG_ON(!ref); HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock); @@ -1613,28 +1603,16 @@ out: void ssl_sock_infocbk(const SSL *ssl, int where, int ret) { - struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index); -#ifdef USE_QUIC - struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index); -#endif /* USE_QUIC */ + struct connection *conn; struct ssl_sock_ctx *ctx = NULL; BIO *write_bio; (void)ret; /* shut gcc stupid warning */ + (void)conn; - if (conn) - ctx = conn_get_ssl_sock_ctx(conn); -#ifdef USE_QUIC - else if (qc) - ctx = qc->xprt_ctx; -#endif /* USE_QUIC */ - - if (!ctx) { - /* must never happen */ - ABORT_NOW(); - return; - } - + conn = ssl_sock_get_conn(ssl, &ctx); + /* must never happen */ + BUG_ON(!ctx); #ifndef SSL_OP_NO_RENEGOTIATION /* Please note that BoringSSL defines this macro to zero so don't * change this to #if and do not assign a default value to this macro! @@ -2128,7 +2106,7 @@ static void ssl_init_keylog(struct connection *conn, int write_p, int version, /* Callback is called for ssl protocol analyse */ void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg) { - struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index); + struct connection *conn = ssl_sock_get_conn(ssl, NULL); struct ssl_sock_msg_callback *cbk; /* Try to call all callback functions that were registered by using @@ -3862,10 +3840,11 @@ static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_ /* SSL callback used when a new session is created while connecting to a server */ static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess) { - struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index); + struct connection *conn = ssl_sock_get_conn(ssl, NULL); struct server *s; uint old_tid; + BUG_ON(!conn); s = __objt_server(conn->target); /* RWLOCK: only read lock the SSL cache even when writing in it because there is @@ -4548,7 +4527,8 @@ static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx) return ok; ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); - conn = SSL_get_ex_data(ssl, ssl_app_data_index); + conn = ssl_sock_get_conn(ssl, NULL); + BUG_ON(!conn); ssl_ctx = __conn_get_ssl_sock_ctx(conn); /* We're checking if the provided hostnames match the desired one. The