]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic-be: modify ssl_sock_srv_try_reuse_sess() to reuse backend sessions (0...
authorFrederic Lecaille <flecaille@haproxy.com>
Thu, 31 Jul 2025 16:19:24 +0000 (18:19 +0200)
committerFrederic Lecaille <flecaille@haproxy.com>
Thu, 6 Nov 2025 09:28:47 +0000 (10:28 +0100)
This function is called for both TCP and QUIC connections to reuse SSL sessions
saved by ssl_sess_new_srv_cb() callback called upon new SSL session creation.

In addition to this, a QUIC SSL session must reuse the ALPN and some specific QUIC
transport parameters. This is what is added by this patch for QUIC 0-RTT sessions.

Note that for now on, ssl_sock_srv_try_reuse_sess() may fail for QUIC connections
if it did not managed to reuse the ALPN. The caller must be informed of such an
issue. It must not enable 0-RTT for the current session in this case. This is
impossible without ALPN which is required to start a mux.

ssl_sock_srv_try_reuse_sess() is modified to always succeeds for TCP connections.

include/haproxy/ssl_sock.h
src/ssl_sock.c

index d421061cac6a89331299e5726779951a997def2c..f974110fda60df0d2b07abbc23681d04522d108a 100644 (file)
@@ -71,7 +71,7 @@ int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx,
                       const char **str, int *len);
 int ssl_bio_and_sess_init(struct connection *conn, SSL_CTX *ssl_ctx,
                           SSL **ssl, BIO **bio, BIO_METHOD *bio_meth, void *ctx);
-void ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv);
+int ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv);
 const char *ssl_sock_get_sni(struct connection *conn);
 const char *ssl_sock_get_cert_sig(struct connection *conn);
 const char *ssl_sock_get_cipher_name(struct connection *conn);
index 70104ed2353d6ae02688feae1831f5ce8d8011ed..deda64812d90bb4bc7ce3a9576256eab9a2d5bde 100644 (file)
@@ -5663,9 +5663,23 @@ int increment_sslconn()
 
 /* Try to reuse an SSL session (SSL_SESSION object) for <srv> server with <ctx>
  * as SSL socket context.
+ * Return 1 if succeeded, 0 if not. Always succeeds for TCP socket. May fail
+ * for QUIC sockets.
  */
-void ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv)
+int ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv)
 {
+#ifdef USE_QUIC
+       struct quic_conn *qc = ctx->qc;
+       /* Default status for QUIC sockets + 0-RTT is failure(0). The status will
+        * be set to success(1) only if the QUIC connection parameters
+        * (transport parameters and ALPN) are successfully reused.
+        */
+       int ret = qc && (srv->ssl_ctx.options & SRV_SSL_O_EARLY_DATA) ? 0 : 1;
+#else
+       /* Always succeeds for TCP sockets. */
+       int ret = 1;
+#endif
+
        HA_RWLOCK_RDLOCK(SSL_SERVER_LOCK, &srv->ssl_ctx.lock);
        if (srv->ssl_ctx.reused_sess[tid].ptr) {
                /* let's recreate a session from (ptr,size) and assign
@@ -5684,6 +5698,9 @@ void ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv)
                        SSL_SESSION_free(sess);
                        HA_RWLOCK_WRLOCK(SSL_SERVER_LOCK, &srv->ssl_ctx.reused_sess[tid].sess_lock);
                        ha_free(&srv->ssl_ctx.reused_sess[tid].ptr);
+#ifdef USE_QUIC
+                       ha_free(&srv->ssl_ctx.reused_sess[tid].alpn);
+#endif
                        HA_RWLOCK_WRTORD(SSL_SERVER_LOCK, &srv->ssl_ctx.reused_sess[tid].sess_lock);
                        if (srv->ssl_ctx.reused_sess[tid].sni)
                                SSL_set_tlsext_host_name(ctx->ssl, srv->ssl_ctx.reused_sess[tid].sni);
@@ -5694,6 +5711,18 @@ void ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv)
                        HA_RWLOCK_RDLOCK(SSL_SERVER_LOCK, &srv->ssl_ctx.reused_sess[tid].sess_lock);
                        if (srv->ssl_ctx.reused_sess[tid].sni)
                                SSL_set_tlsext_host_name(ctx->ssl, srv->ssl_ctx.reused_sess[tid].sni);
+#ifdef USE_QUIC
+                       if (qc && srv->ssl_ctx.options & SRV_SSL_O_EARLY_DATA) {
+                               const unsigned char *alpn =
+                                       (unsigned char *)srv->ssl_ctx.reused_sess[tid].alpn;
+                               struct quic_early_transport_params *etps =
+                                       &srv->ssl_ctx.reused_sess[tid].tps;
+
+                               if (quic_reuse_srv_params(qc, alpn, etps))
+                                       /* Success */
+                                   ret = 1;
+                       }
+#endif
                        HA_RWLOCK_RDUNLOCK(SSL_SERVER_LOCK, &srv->ssl_ctx.reused_sess[tid].sess_lock);
                }
        } else {
@@ -5716,6 +5745,18 @@ void ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv)
                                if (sess) {
                                        if (!SSL_set_session(ctx->ssl, sess))
                                                HA_ATOMIC_CAS(&srv->ssl_ctx.last_ssl_sess_tid, &old_tid, 0); // no more valid
+#ifdef USE_QUIC
+                                       else if (qc && srv->ssl_ctx.options & SRV_SSL_O_EARLY_DATA) {
+                                               const unsigned char *alpn =
+                                                       (unsigned char *)srv->ssl_ctx.reused_sess[old_tid-1].alpn;
+                                               struct quic_early_transport_params *etps =
+                                                       &srv->ssl_ctx.reused_sess[old_tid-1].tps;
+
+                                               if (quic_reuse_srv_params(qc, alpn, etps))
+                                                       /* Success */
+                                                       ret = 1;
+                                       }
+#endif
                                        SSL_SESSION_free(sess);
                                }
                        }
@@ -5727,6 +5768,8 @@ void ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv)
                }
        }
        HA_RWLOCK_RDUNLOCK(SSL_SERVER_LOCK, &srv->ssl_ctx.lock);
+
+       return ret;
 }
 
 /*
@@ -5774,6 +5817,9 @@ static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
 #ifdef HA_USE_KTLS
        ctx->record_type = 0;
 #endif
+#ifdef USE_QUIC
+       ctx->qc = NULL;
+#endif
 
        next_sslconn = increment_sslconn();
        if (!next_sslconn) {