Skip to content

Commit

Permalink
Merge pull request #1816 from private-octopus/refactor-incoming-initial
Browse files Browse the repository at this point in the history
Tighten initial packet screening
  • Loading branch information
huitema authored Jan 8, 2025
2 parents 7a88998 + 1b465cb commit e0223d4
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 44 deletions.
85 changes: 42 additions & 43 deletions picoquic/packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ int picoquic_screen_initial_packet(
picoquic_packet_header* ph,
uint64_t current_time,
picoquic_cnx_t** pcnx,
int * new_ctx_created)
int* new_ctx_created)
{
int ret = 0;

Expand All @@ -107,6 +107,15 @@ int picoquic_screen_initial_packet(
/* Cannot have reserved bit set before negotiation completes */
ret = PICOQUIC_ERROR_PACKET_HEADER_PARSING;
}
else if (quic->enforce_client_only) {
/* Cannot create a client connection if the context is client only */
ret = PICOQUIC_ERROR_SERVER_BUSY;
}
else if (quic->server_busy ||
quic->current_number_connections >= quic->tentative_max_number_connections) {
/* Cannot create a client connection now, send immediate close. */
ret = PICOQUIC_ERROR_SERVER_BUSY;
}
else {
/* This code assumes that *pcnx is always null when screen initial is called. */
/* Verify the AEAD checkum */
Expand Down Expand Up @@ -143,52 +152,42 @@ int picoquic_screen_initial_packet(
}

if (ret == 0) {
if (quic->enforce_client_only) {
/* Cannot create a client connection if the context is client only */
ret = PICOQUIC_ERROR_SERVER_BUSY;
int is_address_blocked = !quic->is_port_blocking_disabled && picoquic_check_addr_blocked(addr_from);
int is_new_token = 0;
int has_good_token = 0;
int has_bad_token = 0;
picoquic_connection_id_t original_cnxid = { 0 };
if (ph->token_length > 0) {
/* If a token is present, verify it. */
if (picoquic_verify_retry_token(quic, addr_from, current_time,
&is_new_token, &original_cnxid, &ph->dest_cnx_id, (uint32_t)dph.pn64,
ph->token_bytes, ph->token_length, 1) == 0) {
has_good_token = 1;
}
else {
has_bad_token = 1;
}
}

if (has_bad_token && !is_new_token) {
/* sending a bad retry token is fatal, sending an old new token is not */
ret = PICOQUIC_ERROR_INVALID_TOKEN;
}
else if (quic->server_busy) {
/* Cannot create a client connection now, send immediate close. */
ret = PICOQUIC_ERROR_SERVER_BUSY;
else if (!has_good_token && (quic->force_check_token || quic->max_half_open_before_retry <= quic->current_number_half_open || is_address_blocked)) {
/* tokens are required before accepting new connections, so ask to queue a retry packet. */
ret = PICOQUIC_ERROR_RETRY_NEEDED;
}
else {
int is_address_blocked = !quic->is_port_blocking_disabled && picoquic_check_addr_blocked(addr_from);
int is_new_token = 0;
int has_good_token = 0;
int has_bad_token = 0;
picoquic_connection_id_t original_cnxid = { 0 };
if (ph->token_length > 0) {
/* If a token is present, verify it. */
if (picoquic_verify_retry_token(quic, addr_from, current_time,
&is_new_token, &original_cnxid, &ph->dest_cnx_id, (uint32_t)dph.pn64,
ph->token_bytes, ph->token_length, 1) == 0) {
has_good_token = 1;
}
else {
has_bad_token = 1;
}
}

if (has_bad_token && !is_new_token) {
/* sending a bad retry token is fatal, sending an old new token is not */
ret = PICOQUIC_ERROR_INVALID_TOKEN;
}
else if (!has_good_token && (quic->force_check_token || quic->max_half_open_before_retry <= quic->current_number_half_open || is_address_blocked)) {
/* tokens are required before accepting new connections, so ask to queue a retry packet. */
ret = PICOQUIC_ERROR_RETRY_NEEDED;
/* All clear */
/* Check: what do do with odcid? */
*pcnx = picoquic_create_cnx(quic, ph->dest_cnx_id, ph->srce_cnx_id, addr_from, current_time, ph->vn, NULL, NULL, 0);
if (*pcnx == NULL) {
/* Could not allocate the context */
ret = PICOQUIC_ERROR_MEMORY;
}
else {
/* All clear */
/* Check: what do do with odcid? */
*pcnx = picoquic_create_cnx(quic, ph->dest_cnx_id, ph->srce_cnx_id, addr_from, current_time, ph->vn, NULL, NULL, 0);
if (*pcnx == NULL) {
/* Could not allocate the context */
ret = PICOQUIC_ERROR_MEMORY;
}
else if (has_good_token) {
(*pcnx)->initial_validated = 1;
(void)picoquic_parse_connection_id(original_cnxid.id, original_cnxid.id_len, &(*pcnx)->original_cnxid);
}
else if (has_good_token) {
(*pcnx)->initial_validated = 1;
(void)picoquic_parse_connection_id(original_cnxid.id, original_cnxid.id_len, &(*pcnx)->original_cnxid);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions picoquic/picoquic_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@ typedef struct st_picoquic_quic_t {
uint8_t reset_seed[PICOQUIC_RESET_SECRET_SIZE];
uint8_t retry_seed[PICOQUIC_RETRY_SECRET_SIZE];
uint64_t* p_simulated_time;
uint8_t hash_seed[8];
char const* ticket_file_name;
char const* token_file_name;
picoquic_stored_ticket_t * p_first_ticket;
Expand Down
11 changes: 10 additions & 1 deletion picoquic/quicctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,17 @@ static int picoquic_net_id_compare(const void* key1, const void* key2)

static uint64_t picoquic_net_icid_hash(const void* key)
{
/* The ICID is controlled by the peer. We mix a random seed in the
* hash to avoid possible shenanigans. */
const picoquic_cnx_t* cnx = (const picoquic_cnx_t*)key;
picoquic_connection_id_t cid = cnx->initial_cnxid;

for (int i = 0; i < 8; i++) {
cid.id[i] ^= cnx->quic->hash_seed[i];
}

return picohash_hash_mix(picoquic_hash_addr((struct sockaddr*) & cnx->registered_icid_addr),
picoquic_connection_id_hash(&cnx->initial_cnxid));
picoquic_connection_id_hash(&cid));
}

static int picoquic_net_icid_compare(const void* key1, const void* key2)
Expand Down Expand Up @@ -716,6 +723,7 @@ picoquic_quic_t* picoquic_create(uint32_t max_nb_connections,
memcpy(quic->reset_seed, reset_seed, sizeof(quic->reset_seed));

picoquic_crypto_random(quic, quic->retry_seed, sizeof(quic->retry_seed));
picoquic_crypto_random(quic, quic->hash_seed, sizeof(quic->hash_seed));

/* If there is no root certificate context specified, use a null certifier. */
/* Load tickets */
Expand Down Expand Up @@ -4755,6 +4763,7 @@ picoquic_cnx_t* picoquic_cnx_by_icid(picoquic_quic_t* quic, picoquic_connection_

picoquic_store_addr(&dummy_cnx.registered_icid_addr, addr);
dummy_cnx.initial_cnxid = *icid;
dummy_cnx.quic = quic;

item = picohash_retrieve(quic->table_cnx_by_icid, &dummy_cnx);

Expand Down

0 comments on commit e0223d4

Please sign in to comment.