diff --git a/include/haproxy/quic_conn.h b/include/haproxy/quic_conn.h index b6a416644..77d9f69be 100644 --- a/include/haproxy/quic_conn.h +++ b/include/haproxy/quic_conn.h @@ -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); diff --git a/include/haproxy/quic_ssl.h b/include/haproxy/quic_ssl.h index 1d4bd590c..485abfa66 100644 --- a/include/haproxy/quic_ssl.h +++ b/include/haproxy/quic_ssl.h @@ -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); diff --git a/src/quic_conn.c b/src/quic_conn.c index 82c630add..64df8bf04 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -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; diff --git a/src/quic_rx.c b/src/quic_rx.c index 6f650c4c1..2398cd8cb 100644 --- a/src/quic_rx.c +++ b/src/quic_rx.c @@ -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; diff --git a/src/quic_ssl.c b/src/quic_ssl.c index 21fe16255..c4c4f037a 100644 --- a/src/quic_ssl.c +++ b/src/quic_ssl.c @@ -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); diff --git a/src/quic_trace.c b/src/quic_trace.c index 3f79c2d46..c8fe5524b 100644 --- a/src/quic_trace.c +++ b/src/quic_trace.c @@ -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);