mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-11-29 14:50:59 +01:00
BUG/MEDIUM: quic-be: prevent use of MUX for 0-RTT sessions without secrets
The QUIC backend crashes when its peer does not support 0-RTT. In this case,
when the sessions are reused, no early-data level secrets are derived by
the TLS stack. This leads to crashes from qc_send_mux() which does not suppose
that both early-data level (qc->eel) and application level (qc->ael) cipher levels
could be non initialized.
To fix this:
- prevent qc_send_mux() to send data if these two encryption level are not
intialized. In this case it returns QUIC_TX_ERR_NONE;
- avoid waking up the MUX from XPRT ->start() callback if the MUX is ready
but without early-data level secrets to send them;
- ensure the MUX is woken up by qc_ssl_do_handshake() after handshake completion
if it is ready calling qc_notify_send()
Thank you to @InputOutputZ for having reported this issue in GH #3188.
No need to backport because QUIC backends is a current 3.3 development feature.
This commit is contained in:
parent
0367227375
commit
37d01eea37
@ -1018,6 +1018,14 @@ int qc_ssl_do_hanshake(struct quic_conn *qc, struct ssl_sock_ctx *ctx)
|
||||
/* Wake up MUX after its creation. Operation similar to TLS+ALPN on TCP stack. */
|
||||
qc->conn->mux->wake(qc->conn);
|
||||
}
|
||||
else {
|
||||
/* Wake up upper layer if the MUX is alreay initialized.
|
||||
* This is the case when the MUX was started for a 0-RTT session
|
||||
* but without early-data secrets to send them (when the server
|
||||
* does not support 0-RTT).
|
||||
*/
|
||||
qc_notify_send(qc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
TRACE_PROTO("could not start the mux", QUIC_EV_CONN_IO_CB, qc);
|
||||
|
||||
@ -521,6 +521,16 @@ enum quic_tx_err qc_send_mux(struct quic_conn *qc, struct list *frms,
|
||||
|
||||
TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
|
||||
|
||||
if (!qel) {
|
||||
BUG_ON(!qc_is_back(qc) ||
|
||||
!(__objt_server(qc->conn->target)->ssl_ctx.options & SRV_SSL_O_EARLY_DATA));
|
||||
/* This may happen when 0-RTT is enabled without early-data level secrets.
|
||||
* This always occurs when the server peer does not support 0-RTT.
|
||||
*/
|
||||
TRACE_DEVEL("cannot send at 0-RTT level", QUIC_EV_CONN_TXPKT, qc);
|
||||
return QUIC_TX_ERR_NONE;
|
||||
}
|
||||
|
||||
if (qc->conn->flags & CO_FL_SOCK_WR_SH) {
|
||||
qc->conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH;
|
||||
TRACE_DEVEL("connection on error", QUIC_EV_CONN_TXPKT, qc);
|
||||
|
||||
@ -209,8 +209,11 @@ static int qc_xprt_start(struct connection *conn, void *ctx)
|
||||
/* Schedule quic-conn to ensure post handshake frames are emitted. This
|
||||
* is not done for 0-RTT as xprt->start happens before handshake
|
||||
* completion.
|
||||
* Note that, when 0-RTT is enabled for backend connections, it is
|
||||
* possible that the ealy-data secrets could not be derived. This is the
|
||||
* case when the server does not support 0-RTT.
|
||||
*/
|
||||
if ((qc_is_back(qc) && !qc_is_conn_ready(qc)) ||
|
||||
if ((qc_is_back(qc) && (!qc_is_conn_ready(qc) || !qc->eel)) ||
|
||||
(qc->flags & QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS))
|
||||
tasklet_wakeup(qc->wait_event.tasklet);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user