MINOR: quic: extend Retry token check function
On Initial packet reception, token is checked for validity through
quic_retry_token_check() function. However, some related parts were left
in the parent function quic_rx_pkt_retrieve_conn(). Move this code
directly into quic_retry_token_check() to facilitate its call in various
context.
The API of quic_retry_token_check() has also been refactored. Instead of
working on a plain char* buffer, it now uses a quic_rx_packet instance.
This helps to reduce the number of parameters.
This change will allow to check Retry token even if data were received
with a FD-owned quic-conn socket. Indeed, in this case,
quic_rx_pkt_retrieve_conn() call will probably be skipped.
This should be backported up to 2.6.
(cherry picked from commit 9e3026c58d
)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
This commit is contained in:
committed by
Christopher Faulet
parent
8bcc6909f4
commit
05f9c5c266
@ -5548,20 +5548,28 @@ static int quic_generate_retry_token(unsigned char *buf, size_t len,
|
||||
}
|
||||
|
||||
/* QUIC server only function.
|
||||
* Check the validity of the Retry token from <token> buffer with <tokenlen>
|
||||
* as length. If valid, the ODCID of <qc> QUIC connection will be put
|
||||
* into <odcid> connection ID. <dcid> is our side destination connection ID
|
||||
* of client source connection ID.
|
||||
*
|
||||
* Check the validity of the Retry token from Initial packet <pkt>. <dgram> is
|
||||
* the UDP datagram containing <pkt> and <l> is the listener instance on which
|
||||
* it was received. If the token is valid, the ODCID of <qc> QUIC connection
|
||||
* will be put into <odcid>. <qc> is used to retrieve the QUIC version needed
|
||||
* to validate the token but it can be NULL : in this case the version will be
|
||||
* retrieved from the packet.
|
||||
*
|
||||
* Return 1 if succeeded, 0 if not.
|
||||
*/
|
||||
static int quic_retry_token_check(unsigned char *token, size_t tokenlen,
|
||||
const struct quic_version *qv,
|
||||
struct quic_cid *odcid,
|
||||
const struct quic_cid *dcid,
|
||||
|
||||
static int quic_retry_token_check(struct quic_rx_packet *pkt,
|
||||
struct quic_dgram *dgram,
|
||||
struct listener *l,
|
||||
struct quic_conn *qc,
|
||||
struct sockaddr_storage *addr)
|
||||
struct quic_cid *odcid)
|
||||
{
|
||||
struct proxy *prx;
|
||||
struct quic_counters *prx_counters;
|
||||
int ret = 0;
|
||||
unsigned char *token = pkt->token;
|
||||
const uint64_t tokenlen = pkt->token_len;
|
||||
unsigned char buf[128];
|
||||
unsigned char aad[sizeof(uint32_t) + sizeof(in_port_t) +
|
||||
sizeof(struct in6_addr) + QUIC_CID_MAXLEN];
|
||||
@ -5573,15 +5581,29 @@ static int quic_retry_token_check(unsigned char *token, size_t tokenlen,
|
||||
size_t seclen = strlen(global.cluster_secret);
|
||||
EVP_CIPHER_CTX *ctx = NULL;
|
||||
const EVP_CIPHER *aead = EVP_aes_128_gcm();
|
||||
const struct quic_version *qv = qc ? qc->original_version :
|
||||
pkt->version;
|
||||
|
||||
TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
|
||||
|
||||
/* The caller must ensure this. */
|
||||
BUG_ON(!global.cluster_secret || !pkt->token_len);
|
||||
|
||||
prx = l->bind_conf->frontend;
|
||||
prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module);
|
||||
|
||||
if (*pkt->token != QUIC_TOKEN_FMT_RETRY) {
|
||||
/* TODO: New token check */
|
||||
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc, NULL, NULL, pkt->version);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (sizeof buf < tokenlen) {
|
||||
TRACE_ERROR("too short buffer", QUIC_EV_CONN_LPKT, qc);
|
||||
goto err;
|
||||
}
|
||||
|
||||
aadlen = quic_generate_retry_token_aad(aad, qv->num, dcid, addr);
|
||||
aadlen = quic_generate_retry_token_aad(aad, qv->num, &pkt->scid, &dgram->saddr);
|
||||
salt = token + tokenlen - QUIC_RETRY_TOKEN_SALTLEN;
|
||||
if (!quic_tls_derive_retry_token_secret(EVP_sha256(), key, sizeof key, iv, sizeof iv,
|
||||
salt, QUIC_RETRY_TOKEN_SALTLEN, sec, seclen)) {
|
||||
@ -5609,11 +5631,14 @@ static int quic_retry_token_check(unsigned char *token, size_t tokenlen,
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
ret = 1;
|
||||
HA_ATOMIC_INC(&prx_counters->retry_validated);
|
||||
|
||||
leave:
|
||||
TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
|
||||
return ret;
|
||||
|
||||
err:
|
||||
HA_ATOMIC_INC(&prx_counters->retry_error);
|
||||
if (ctx)
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
goto leave;
|
||||
@ -5935,8 +5960,7 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
||||
struct quic_dgram *dgram,
|
||||
struct listener *l)
|
||||
{
|
||||
struct quic_cid odcid;
|
||||
const struct quic_cid *token_odcid = NULL; // ODCID received from client token
|
||||
struct quic_cid token_odcid = { .len = 0 };
|
||||
struct quic_conn *qc = NULL;
|
||||
struct proxy *prx;
|
||||
struct quic_counters *prx_counters;
|
||||
@ -5952,27 +5976,8 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
||||
BUG_ON(!pkt->version); /* This must not happen. */
|
||||
|
||||
if (global.cluster_secret && pkt->token_len) {
|
||||
if (*pkt->token == QUIC_TOKEN_FMT_RETRY) {
|
||||
const struct quic_version *ver = qc ? qc->original_version : pkt->version;
|
||||
if (!quic_retry_token_check(pkt->token, pkt->token_len, ver, &odcid,
|
||||
&pkt->scid, qc, &dgram->saddr)) {
|
||||
HA_ATOMIC_INC(&prx_counters->retry_error);
|
||||
TRACE_PROTO("Wrong retry token",
|
||||
QUIC_EV_CONN_LPKT, qc, NULL, NULL, pkt->version);
|
||||
/* TODO: RFC 9000 8.1.2 A server SHOULD immediately close the connection
|
||||
* with an INVALID_TOKEN error.
|
||||
*/
|
||||
goto out;
|
||||
}
|
||||
|
||||
token_odcid = &odcid;
|
||||
HA_ATOMIC_INC(&prx_counters->retry_validated);
|
||||
}
|
||||
else {
|
||||
/* TODO: New token check */
|
||||
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc, NULL, NULL, pkt->version);
|
||||
goto out;
|
||||
}
|
||||
if (!quic_retry_token_check(pkt, dgram, l, qc, &token_odcid))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!qc) {
|
||||
@ -6007,7 +6012,7 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
||||
pkt->saddr = dgram->saddr;
|
||||
ipv4 = dgram->saddr.ss_family == AF_INET;
|
||||
|
||||
qc = qc_new_conn(pkt->version, ipv4, &pkt->dcid, &pkt->scid, token_odcid,
|
||||
qc = qc_new_conn(pkt->version, ipv4, &pkt->dcid, &pkt->scid, &token_odcid,
|
||||
&dgram->daddr, &pkt->saddr, 1,
|
||||
!!pkt->token_len, l);
|
||||
if (qc == NULL)
|
||||
|
@ -657,7 +657,7 @@ int qc_lstnr_params_init(struct quic_conn *qc,
|
||||
memcpy(rx_params->stateless_reset_token, stateless_reset_token,
|
||||
sizeof rx_params->stateless_reset_token);
|
||||
/* Copy original_destination_connection_id transport parameter. */
|
||||
if (token_odcid) {
|
||||
if (token_odcid->len) {
|
||||
memcpy(odcid_param->data, token_odcid->data, token_odcid->len);
|
||||
odcid_param->len = token_odcid->len;
|
||||
/* Copy retry_source_connection_id transport parameter. */
|
||||
|
Reference in New Issue
Block a user