]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic-be: Save the backend parameters (0-RTT)
authorFrederic Lecaille <flecaille@haproxy.com>
Thu, 31 Jul 2025 15:56:02 +0000 (17:56 +0200)
committerFrederic Lecaille <flecaille@haproxy.com>
Mon, 4 Aug 2025 17:30:46 +0000 (19:30 +0200)
For both TCP and QUIC connections, this is ssl_sess_new_srv_cb() callback which
is called when a new SSL session. Its role is to save the session to be reused
during the SSL session resumption and 0-RTT session.

This patch modifies this callback to same the QUIC parameters to be reused
for the next 0-RTT sessions (or SSL session resumption).

A new ->alpn member is added to the reused_sess objects allocated by thread
and server alongsise ->tps new quic_early_transport_params struct used to
save the QUIC transport parameters to be reused for 0-RTT sessions.

include/haproxy/server-t.h
src/ssl_sock.c

index ed3c36e957a715ff3b962897151b39ba4beea1c5..ec618bd88c3aed0864b52a660037ee03aaf31365 100644 (file)
@@ -462,6 +462,10 @@ struct server {
                        int size;
                        int allocated_size;
                        char *sni; /* SNI used for the session */
+#ifdef USE_QUIC
+                       struct quic_early_transport_params tps;
+                       char *alpn;
+#endif
                        __decl_thread(HA_RWLOCK_T sess_lock);
                } * reused_sess;
                uint last_ssl_sess_tid;         /* last tid+1 having updated reused_sess (0=none, >0=tid+1) */
index e5ee788aca909ed34827050b2955a051300a2b64..d46dd957cea3c8fccc147a9e117caabbdc48a3c8 100644 (file)
@@ -3660,6 +3660,9 @@ static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
                int len;
                unsigned char *ptr;
                const char *sni;
+#ifdef USE_QUIC
+               struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
+#endif
 
                /* determine the required len to store this new session */
                len = i2d_SSL_SESSION(sess, NULL);
@@ -3712,6 +3715,31 @@ static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
                        /* if there wasn't an old sni but there is a new one */
                        s->ssl_ctx.reused_sess[tid].sni = strdup(sni);
                }
+#ifdef USE_QUIC
+               /* The selected ALPN is not stored without SSL session. */
+               if (qc && (s->ssl_ctx.options & SRV_SSL_O_EARLY_DATA) &&
+                   s->ssl_ctx.reused_sess[tid].ptr) {
+                       const char *alpn = NULL;
+                       int alpn_len;
+
+                       if (ssl_sock_get_alpn(conn, qc->xprt_ctx, &alpn, &alpn_len)) {
+                               char **alpn_addr = &s->ssl_ctx.reused_sess[tid].alpn;
+                               struct quic_early_transport_params *etps =
+                                       &s->ssl_ctx.reused_sess[tid].tps;
+
+                               /* <*alpn_addr> is a NULL terminated string */
+                               if (*alpn_addr == NULL ||
+                                   alpn_len != strlen(*alpn_addr) ||
+                                   memcmp(*alpn_addr, alpn, alpn_len) != 0) {
+                                       ha_free(alpn_addr);
+                                       *alpn_addr = my_strndup((const char *)alpn, alpn_len);
+                                       /* The transport parameters are not stored without ALPN */
+                                       if (*alpn_addr)
+                                               qc_early_transport_params_cpy(qc, etps, &qc->tx.params);
+                               }
+                       }
+               }
+#endif
                HA_RWLOCK_WRUNLOCK(SSL_SERVER_LOCK, &s->ssl_ctx.reused_sess[tid].sess_lock);
                HA_RWLOCK_RDUNLOCK(SSL_SERVER_LOCK, &s->ssl_ctx.lock);
        } else {
@@ -3720,6 +3748,9 @@ static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
                if (s->ssl_ctx.reused_sess[tid].ptr) {
                        HA_RWLOCK_WRLOCK(SSL_SERVER_LOCK, &s->ssl_ctx.reused_sess[tid].sess_lock);
                        ha_free(&s->ssl_ctx.reused_sess[tid].ptr);
+#ifdef USE_QUIC
+                       ha_free(&s->ssl_ctx.reused_sess[tid].alpn);
+#endif
                        HA_RWLOCK_WRUNLOCK(SSL_SERVER_LOCK, &s->ssl_ctx.reused_sess[tid].sess_lock);
                }
 
@@ -4876,6 +4907,9 @@ void ssl_sock_free_srv_ctx(struct server *srv)
                for (i = 0; i < global.nbthread; i++) {
                        ha_free(&srv->ssl_ctx.reused_sess[i].ptr);
                        ha_free(&srv->ssl_ctx.reused_sess[i].sni);
+#ifdef USE_QUIC
+                       ha_free(&srv->ssl_ctx.reused_sess[i].alpn);
+#endif
                }
                ha_free(&srv->ssl_ctx.reused_sess);
        }