]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic-be: SSL sessions initializations
authorFrederic Lecaille <flecaille@haproxy.com>
Tue, 19 Dec 2023 07:16:42 +0000 (08:16 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 11 Jun 2025 16:37:34 +0000 (18:37 +0200)
Modify qc_alloc_ssl_sock_ctx() to pass the connection object as parameter. It is
NULL for a QUIC listener, not NULL for a QUIC server. This connection object is
set as value for ->conn quic_conn struct member. Initialise the SSL session object from
this function for QUIC servers.
qc_ssl_set_quic_transport_params() is also modified to pass the SSL object as parameter.
This is the unique parameter this function needs. <qc> parameter is used only for
the trace.
SSL_do_handshake() must be calle as soon as the SSL object is initialized for
the QUIC backend connection. This triggers the TLS CRYPTO data delivery.
tasklet_wakeup() is also called to send asap these CRYPTO data.
Modify the QUIC_EV_CONN_NEW event trace to dump the potential errors returned by
SSL_do_handshake().

include/haproxy/quic_conn.h
include/haproxy/quic_ssl.h
src/quic_conn.c
src/quic_rx.c
src/quic_ssl.c
src/quic_trace.c

index b6a416644778f97a1d19348594f86980874e96f1..77d9f69beee05b8a8b75e06cf21b5635211b5679 100644 (file)
@@ -69,7 +69,8 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
                               struct quic_connection_id *conn_id,
                               struct sockaddr_storage *local_addr,
                               struct sockaddr_storage *peer_addr,
-                              int server, int token, void *owner);
+                              int server, int token, void *owner,
+                              struct connection *conn);
 int quic_build_post_handshake_frames(struct quic_conn *qc);
 const struct quic_version *qc_supported_version(uint32_t version);
 int quic_peer_validated_addr(struct quic_conn *qc);
index 1d4bd590c2e60917e7214dba58de91d46c020a72..485abfa668d6aba9f450ce88c24982ab7a8ff90f 100644 (file)
@@ -35,7 +35,7 @@
 
 int ssl_quic_initial_ctx(struct bind_conf *bind_conf);
 SSL_CTX *ssl_quic_srv_new_ssl_ctx(void);
-int qc_alloc_ssl_sock_ctx(struct quic_conn *qc);
+int qc_alloc_ssl_sock_ctx(struct quic_conn *qc, struct connection *conn);
 int qc_ssl_provide_all_quic_data(struct quic_conn *qc, struct ssl_sock_ctx *ctx);
 int quic_ssl_set_tls_cbs(SSL *ssl);
 
index 82c630add99c79337917ba20d8201a32721313d1..64df8bf04bbf6a581e7fa7c5322ef4a7c199a793 100644 (file)
@@ -1032,7 +1032,8 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
                               struct quic_connection_id *conn_id,
                               struct sockaddr_storage *local_addr,
                               struct sockaddr_storage *peer_addr,
-                              int server, int token, void *owner)
+                              int server, int token, void *owner,
+                              struct connection *conn)
 {
        struct quic_conn *qc = NULL;
        struct listener *l = server ? owner : NULL;
@@ -1263,7 +1264,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
        qc->wait_event.events = 0;
        qc->subs = NULL;
 
-       if (qc_alloc_ssl_sock_ctx(qc) ||
+       if (qc_alloc_ssl_sock_ctx(qc, conn) ||
            !quic_conn_init_timer(qc) ||
            !quic_conn_init_idle_timer_task(qc, prx))
                goto err;
index 6f650c4c1df799ec977e5524f9c58c2457bc64f5..2398cd8cbea016ef9dcd365e13e7e8b20671188c 100644 (file)
@@ -1820,7 +1820,7 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
 
                        qc = qc_new_conn(pkt->version, ipv4, &pkt->dcid, &pkt->scid, &token_odcid,
                                         conn_id, &dgram->daddr, &pkt->saddr, 1,
-                                        !!pkt->token_len, l);
+                                        !!pkt->token_len, l, NULL);
                        if (qc == NULL) {
                                pool_free(pool_head_quic_connection_id, conn_id);
                                goto err;
index 21fe16255f02cece19fbdbfc28a2b622a47cbad5..c4c4f037adb856d5b0095385a77ed9e520b39370 100644 (file)
@@ -17,7 +17,7 @@ DECLARE_POOL(pool_head_quic_ssl_sock_ctx, "quic_ssl_sock_ctx", sizeof(struct ssl
  * be set to 1 for a QUIC server, 0 for a client.
  * Return 1 if succeeded, 0 if not.
  */
-static int qc_ssl_set_quic_transport_params(struct quic_conn *qc,
+static int qc_ssl_set_quic_transport_params(SSL *ssl, struct quic_conn *qc,
                                             const struct quic_version *ver, int server)
 {
        int ret = 0;
@@ -40,7 +40,7 @@ static int qc_ssl_set_quic_transport_params(struct quic_conn *qc,
                goto leave;
        }
 
-       if (!SSL_set_quic_transport_params(qc->xprt_ctx->ssl, in, *enclen)) {
+       if (!SSL_set_quic_transport_params(ssl, in, *enclen)) {
                TRACE_ERROR("SSL_set_quic_transport_params() failed", QUIC_EV_CONN_RWSEC);
                goto leave;
        }
@@ -274,7 +274,7 @@ write:
 
        /* Set the transport parameters in the TLS stack. */
        if (level == ssl_encryption_handshake && qc_is_listener(qc) &&
-           !qc_ssl_set_quic_transport_params(qc, ver, 1))
+           !qc_ssl_set_quic_transport_params(qc->xprt_ctx->ssl, qc, ver, 1))
                goto leave;
 
  keyupdate_init:
@@ -570,7 +570,7 @@ static int ha_quic_ossl_got_transport_params(SSL *ssl, const unsigned char *para
        }
        else {
                if (!quic_transport_params_store(qc, 0, params, params + params_len) ||
-                   !qc_ssl_set_quic_transport_params(qc, ver, 1))
+                   !qc_ssl_set_quic_transport_params(ssl, qc, ver, 1))
                        goto err;
        }
 
@@ -1150,10 +1150,9 @@ static int qc_set_quic_early_data_enabled(struct quic_conn *qc, SSL *ssl)
  *
  * Returns 0 on success else non-zero.
  */
-int qc_alloc_ssl_sock_ctx(struct quic_conn *qc)
+int qc_alloc_ssl_sock_ctx(struct quic_conn *qc, struct connection *conn)
 {
        int ret = 0;
-       struct bind_conf *bc = qc->li->bind_conf;
        struct ssl_sock_ctx *ctx = NULL;
 
        TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
@@ -1164,7 +1163,7 @@ int qc_alloc_ssl_sock_ctx(struct quic_conn *qc)
                goto err;
        }
 
-       ctx->conn = NULL;
+       ctx->conn = conn;
        ctx->bio = NULL;
        ctx->xprt = NULL;
        ctx->xprt_ctx = NULL;
@@ -1177,6 +1176,8 @@ int qc_alloc_ssl_sock_ctx(struct quic_conn *qc)
        ctx->qc = qc;
 
        if (qc_is_listener(qc)) {
+               struct bind_conf *bc = qc->li->bind_conf;
+
                if (qc_ssl_sess_init(qc, bc->initial_ctx, &ctx->ssl) == -1)
                        goto err;
 #if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) && defined(HAVE_SSL_0RTT_QUIC)
@@ -1187,6 +1188,36 @@ int qc_alloc_ssl_sock_ctx(struct quic_conn *qc)
 
                SSL_set_accept_state(ctx->ssl);
        }
+       else {
+               int ssl_err;
+               struct server *srv = __objt_server(ctx->conn->target);
+
+               if (qc_ssl_sess_init(qc, srv->ssl_ctx.ctx, &ctx->ssl) == -1)
+                       goto err;
+
+               if (!qc_ssl_set_quic_transport_params(ctx->ssl, qc, quic_version_1, 0))
+                       goto err;
+
+               SSL_set_connect_state(ctx->ssl);
+               ssl_err = SSL_do_handshake(ctx->ssl);
+               TRACE_PROTO("SSL_do_handshake() called", QUIC_EV_CONN_NEW, qc, &ssl_err);
+               if (ssl_err != 1) {
+                       ssl_err = SSL_get_error(ctx->ssl, ssl_err);
+                       if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
+                               TRACE_PROTO("SSL handshake in progress", QUIC_EV_CONN_NEW, qc, &ssl_err);
+                       }
+                       else {
+                               TRACE_ERROR("SSL handshake error", QUIC_EV_CONN_NEW, qc, &ssl_err);
+                               HA_ATOMIC_INC(&qc->prx_counters->hdshk_fail);
+                               qc_ssl_dump_errors(ctx->conn);
+                               ERR_clear_error();
+                               goto err;
+                       }
+               }
+
+               /* Wakeup the handshake I/O handler tasklet asap to send data */
+               tasklet_wakeup(qc->wait_event.tasklet);
+       }
 
        ctx->xprt = xprt_get(XPRT_QUIC);
 
index 3f79c2d46130de040ae611a85cfe9faf9179079d..c8fe5524b61bb6fd8568ca34a3d0dc996c7248b9 100644 (file)
@@ -117,6 +117,13 @@ static void quic_trace(enum trace_level level, uint64_t mask, const struct trace
 
                chunk_appendf(&trace_buf, " : qc@%p idle_timer_task@%p flags=0x%x",
                              qc, qc->idle_timer_task, qc->flags);
+               if (mask & QUIC_EV_CONN_NEW) {
+                       const int *ssl_err = a2;
+
+                       if (ssl_err)
+                               chunk_appendf(&trace_buf, " ssl_err=%d", *ssl_err);
+               }
+
                if (mask & QUIC_EV_CONN_INIT) {
                        chunk_appendf(&trace_buf, "\n  odcid");
                        quic_cid_dump(&trace_buf, &qc->odcid);