Packages
hackney
2.0.0
4.7.2
4.7.1
4.7.0
4.6.1
4.6.0
4.5.2
4.5.1
4.5.0
4.4.5
4.4.3
4.4.2
4.4.1
4.4.0
4.3.0
4.2.3
4.2.2
4.2.1
4.2.0
4.1.0
4.0.3
4.0.2
4.0.1
4.0.0
3.2.1
3.2.0
3.1.2
3.1.1
3.1.0
3.0.3
3.0.2
3.0.1
3.0.0
retired
2.0.1
2.0.0
2.0.0-beta.1
1.25.0
1.24.1
1.24.0
1.23.0
1.22.0
1.21.0
1.20.1
1.20.0
1.19.1
1.19.0
1.18.2
1.18.1
1.18.0
1.17.4
1.17.3
1.17.2
1.17.1
1.17.0
1.16.0
1.15.2
1.15.1
1.15.0
1.14.3
1.14.2
1.14.0
1.13.0
1.12.1
1.12.0
1.11.0
1.10.1
1.10.0
1.9.0
1.8.6
1.8.5
1.8.4
1.8.3
1.8.2
1.8.0
1.7.1
1.7.0
1.6.6
retired
1.6.5
1.6.4
retired
1.6.3
1.6.2
1.6.1
1.6.0
1.5.7
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.10
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.0
1.1.0
1.0.6
1.0.5
1.0.2
1.0.1
0.15.2
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.1
Simple HTTP client with HTTP/1.1, HTTP/2, and HTTP/3 support
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
c_src/lsquic/src/liblsquic/lsquic_hspack_valid.c
/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */
/*
* lsquic_hspack_valid.c -- Handshake packet validator.
*
* We want to eliminate invalid packets as soon as we read them in and not
* feed them to lsquic engine if we can avoid it. The handshake packet
* possesses several characteristics which make it possible to detect
* garbage packets.
*/
#include <assert.h>
#include <string.h>
#include <sys/queue.h>
#include "lsquic.h"
#include "lsquic_types.h"
#include "lsquic_int_types.h"
#include "lsquic_packet_common.h"
#include "lsquic_packet_gquic.h"
#include "lsquic_packet_ietf.h"
#include "lsquic_mm.h"
#include "lsquic_engine_public.h"
#include "lsquic_version.h"
#include "lsquic_parse_common.h"
#define SMALLEST_GQUIC_OVERHEAD \
1 /* Type */ \
+ GQUIC_CID_LEN \
+ sizeof(lsquic_ver_tag_t) \
+ 1 /* Packet number */ \
+ 1 /* Stream frame */ \
+ 1 /* Stream ID */ \
+ 2 /* Data length */ \
+ 12 /* IV */
/* Note that we ignore nonce: even if the flag is set, we know that Chrome
* does not actually include the 32-byte nonce.
*/
static int
is_valid_gquic_hs_packet (const unsigned char *buf, size_t bufsz,
lsquic_ver_tag_t *tag)
{
if (bufsz > GQUIC_MAX_PACKET_SZ ||
/* Data: HPACKed :method GET :path / is 2 bytes */
bufsz < SMALLEST_GQUIC_OVERHEAD + 2 ||
/* Check maximum packet number: */
buf[1 + GQUIC_CID_LEN + sizeof(lsquic_ver_tag_t)] > 64 ||
/* From [draft-hamilton-quic-transport-protocol-01]:
* 0x80 is currently unused, and must be set to 0.
* 0x40 = MULTIPATH. This bit is reserved for multipath use.
*
* 0x30 = Packet number length. We expect these bits to be
* unset.
*
* The reference implementation checks that two high bits are not
* set if version flag is not set or if the version is the same.
* For our purposes, all GQUIC version we support so far have these
* bits set to zero.
*
* Incoming handshake packets must have both connection ID and
* version bits set.
*
* Nonce flag is ignored: Chrome sets it erronesously, but it may
* not be true (a) in the future or (b) in other clients.
*/
((buf[0] ^ (
/* These should be unset: */
(~(0x80|0x40|0x30|PACKET_PUBLIC_FLAGS_RST))
&
/* While these should be set: */
(PACKET_PUBLIC_FLAGS_VERSION|
PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID)
)) & /* Ignore this bit: */ ~PACKET_PUBLIC_FLAGS_NONCE)
)
{
return 0;
}
memcpy(tag, buf + 1 + 8, sizeof(*tag));
return 1;
}
int
lsquic_is_valid_hs_packet (struct lsquic_engine *engine,
const unsigned char *buf, size_t bufsz)
{
lsquic_ver_tag_t tag;
int is_valid;
if (bufsz < 1)
return 0;
switch (buf[0] & 0xF8)
{
/* Xs vary, Gs are iGnored: */
/* 1X11 XGGG: Q046 long header */
case 0x80|0x40|0x20|0x10|0x08:
case 0x80|0x00|0x20|0x10|0x08:
case 0x80|0x40|0x20|0x10|0x00:
case 0x80|0x00|0x20|0x10|0x00:
is_valid = bufsz >= IQUIC_MIN_INIT_PACKET_SZ
&& lsquic_is_valid_iquic_hs_packet(buf, bufsz, &tag);
break;
/* 1X00 XGGG: ID-22 long header */
case 0x80|0x40|0x00|0x00|0x08:
case 0x80|0x00|0x00|0x00|0x08:
case 0x80|0x40|0x00|0x00|0x00:
case 0x80|0x00|0x00|0x00|0x00:
/* 1X01 XGGG: ID-22 long header */
case 0x80|0x40|0x00|0x10|0x08:
case 0x80|0x00|0x00|0x10|0x08:
case 0x80|0x40|0x00|0x10|0x00:
case 0x80|0x00|0x00|0x10|0x00:
/* 1X10 XGGG: ID-22 long header */
case 0x80|0x40|0x20|0x00|0x08:
case 0x80|0x00|0x20|0x00|0x08:
case 0x80|0x40|0x20|0x00|0x00:
case 0x80|0x00|0x20|0x00|0x00:
is_valid = bufsz >= IQUIC_MIN_INIT_PACKET_SZ
&& lsquic_is_valid_ietf_v1_or_Q046plus_hs_packet(buf, bufsz, &tag);
break;
/* 01XX XGGG: ID-22 short header */
case 0x00|0x40|0x00|0x00|0x00:
case 0x00|0x40|0x00|0x00|0x08:
case 0x00|0x40|0x00|0x10|0x00:
case 0x00|0x40|0x00|0x10|0x08:
case 0x00|0x40|0x20|0x00|0x00:
case 0x00|0x40|0x20|0x00|0x08:
case 0x00|0x40|0x20|0x10|0x00:
case 0x00|0x40|0x20|0x10|0x08:
is_valid = 0;
break;
/* 00XX 0GGG: Q046 short header */
case 0x00|0x00|0x00|0x00|0x00:
case 0x00|0x00|0x00|0x10|0x00:
case 0x00|0x00|0x20|0x00|0x00:
case 0x00|0x00|0x20|0x10|0x00:
is_valid = 0;
break;
/* 00XX 1GGG: GQUIC */
case 0x00|0x00|0x00|0x00|0x08:
case 0x00|0x00|0x00|0x10|0x08:
case 0x00|0x00|0x20|0x00|0x08:
case 0x00|0x00|0x20|0x10|0x08:
is_valid = is_valid_gquic_hs_packet(buf, bufsz, &tag);
break;
default: /* gcc thinks this is possible?! */
assert(0);
is_valid = 0;
break;
}
if (is_valid)
{
return 1;
}
else
return 0;
}