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.
This commit is contained in:
Frederic Lecaille 2025-09-10 18:11:50 +02:00
parent 47bb15ca84
commit 5027ba36a9
3 changed files with 66 additions and 37 deletions

View File

@ -28,6 +28,7 @@
#include <haproxy/openssl-compat.h>
#include <haproxy/pool-t.h>
#include <haproxy/proxy-t.h>
#include <haproxy/quic_conn-t.h>
#include <haproxy/ssl_sock-t.h>
#include <haproxy/thread.h>
@ -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 <s> 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 <s> 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 */

View File

@ -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;

View File

@ -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