diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index f888de3c7..2d4f3a07d 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -325,6 +325,9 @@ enum renegotiate_mode { struct path_parameters { __decl_thread(HA_RWLOCK_T param_lock); char nego_alpn[MAX_ALPN_SIZE]; +#ifdef USE_QUIC + struct quic_early_transport_params tps; +#endif }; struct proxy; diff --git a/src/ssl_sock.c b/src/ssl_sock.c index f0cfb1458..1a3fbf6c2 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -4181,6 +4181,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); @@ -4233,6 +4236,29 @@ 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 len; + + if (ssl_sock_get_alpn(conn, qc->xprt_ctx, &alpn, &len)) { + struct quic_early_transport_params *etps = &s->path_params.tps; + + if (len < sizeof(s->path_params.nego_alpn) && + (len != strlen(s->path_params.nego_alpn) || + memcmp(&s->path_params.nego_alpn, alpn, len) != 0)) { + HA_RWLOCK_WRLOCK(SERVER_LOCK, &s->path_params.param_lock); + memcpy(&s->path_params.nego_alpn, alpn, len); + s->path_params.nego_alpn[len] = 0; + /* The transport parameters are not stored without ALPN */ + qc_early_transport_params_cpy(qc, etps, &qc->tx.params); + HA_RWLOCK_WRUNLOCK(SERVER_LOCK, &s->path_params.param_lock); + } + } + } +#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 {