]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic-be: modify ssl_sock_srv_try_reuse_sess() to reuse backend session (0...
authorFrederic Lecaille <flecaille@haproxy.com>
Thu, 31 Jul 2025 16:19:24 +0000 (18:19 +0200)
committerFrederic Lecaille <flecaille@haproxy.com>
Mon, 4 Aug 2025 17:30:46 +0000 (19:30 +0200)
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 reused the ALPN and some 0-RTT QUIC
transport parameters. This is what is added by this patch for QUIC 0-RTT SSL sessions.

Note that for now on, ssl_sock_srv_try_reuse_sess() may fail for QUIC connection
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() always succeeds for TCP connections.

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

index 7c53947b1b794845c172abd3e1350a83429ef693..a6b6bf2dd72fa4a33a67b4eb9c2ee1a585ca443e 100644 (file)
@@ -70,7 +70,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 d46dd957cea3c8fccc147a9e117caabbdc48a3c8..bcb14e0cdce02d48bf3a2472dbe00ab914a76643 100644 (file)
@@ -5100,9 +5100,23 @@ int increment_sslconn()
 /* Try to restore the SSL session (SSL_SESSION object) into <ctx> from them
  * which have been stored by thread ID for <srv> server by the callback set by
  * SSL_CTX_sess_set_new_cb().
+ * 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
@@ -5121,6 +5135,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);
@@ -5131,6 +5148,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 {
@@ -5153,6 +5182,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);
                                }
                        }
@@ -5164,6 +5205,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;
 }
 
 /*
@@ -5207,6 +5250,9 @@ static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
        ctx->xprt_st = 0;
        ctx->xprt_ctx = NULL;
        ctx->error_code = 0;
+#ifdef USE_QUIC
+       ctx->qc = NULL;
+#endif
 
        next_sslconn = increment_sslconn();
        if (!next_sslconn) {