TSG-8364: 增加校验长度的逻辑避免导致段错误
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* quic_process.c
|
||||
*
|
||||
* Created on: 2019<31><39>4<EFBFBD><34>2<EFBFBD><32>
|
||||
* Created on: 2019<31><39>4<EFBFBD><34>2<EFBFBD><32>
|
||||
* Author: root
|
||||
*/
|
||||
|
||||
@@ -1134,12 +1134,20 @@ int parse_encrypt_parameter(struct _quic_stream *quic_stream, unsigned char *pay
|
||||
case EXT_QUIC_PARAM_USER_AGENT: // 2021-10-20 deprecated
|
||||
quic_stream->ua_idx=quic_stream->ext_tag_num++;
|
||||
length=get_value(payload, &used_len, 1); // length=1
|
||||
if(length+used_len>payload_len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
get_quic_tlv((char *)payload+used_len, &(quic_stream->ext_tags[quic_stream->ua_idx]), length, EXT_QUIC_PARAM_USER_AGENT, thread_seq);
|
||||
used_len+=length;
|
||||
break;
|
||||
case EXT_QUIC_PARAM_QUIC_VERSION:
|
||||
quic_stream->ver_idx=quic_stream->ext_tag_num++;
|
||||
length=get_value(payload, &used_len, 1); // length=1
|
||||
if(length+used_len>payload_len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
get_quic_tlv((char *)payload+used_len, &(quic_stream->ext_tags[quic_stream->ver_idx]), length, EXT_QUIC_PARAM_QUIC_VERSION, thread_seq);
|
||||
*(unsigned int *)quic_stream->ext_tags[quic_stream->ver_idx].value=(unsigned int)htonl(*(unsigned int *)quic_stream->ext_tags[quic_stream->ver_idx].value);
|
||||
used_len+=length;
|
||||
@@ -1448,7 +1456,7 @@ int quic_process(struct streaminfo *pstream, struct _quic_context* _context, int
|
||||
{
|
||||
_context->is_decrypt=1;
|
||||
ret=dissect_quic((char *)udp_detail->pdata, udp_detail->datalen, decrypt_payload, &decrypt_payload_len);
|
||||
if(ret!=1 || decrypt_payload_len>2048 || decrypt_payload_len<0)
|
||||
if(ret!=1 || decrypt_payload_len>2048 || decrypt_payload_len<=0)
|
||||
{
|
||||
return APP_STATE_GIVEME;
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ typedef struct _quic_packet_info {
|
||||
guint8 first_byte;
|
||||
} quic_packet_info_t;
|
||||
|
||||
|
||||
/**
|
||||
* Given a QUIC message (header + non-empty payload), the actual packet number,
|
||||
* try to decrypt it using the PP cipher.
|
||||
@@ -168,7 +169,8 @@ static void quic_decrypt_message(quic_pp_cipher *pp_cipher, const char *payload,
|
||||
// buffer_length = length - (header_length + 16);
|
||||
// buffer_length = 297 - (2 + 16);
|
||||
buffer_length = length - (pkn_len + 16);
|
||||
if (buffer_length == 0 || buffer_length >1500) {
|
||||
if (buffer_length == 0 || buffer_length >1500)
|
||||
{
|
||||
*error = (const guchar *)"Decryption not possible, ciphertext is too short or too long";
|
||||
return;
|
||||
}
|
||||
@@ -669,10 +671,9 @@ static gboolean quic_create_initial_decoders(const quic_cid_t *cid, const gchar
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int quic_extract_header(const char *payload, unsigned char *long_packet_type, unsigned int *version, quic_cid_t *dcid, quic_cid_t *scid)
|
||||
static int quic_extract_header(const char *payload, unsigned int payload_len, unsigned char *long_packet_type, unsigned int *version, quic_cid_t *dcid, quic_cid_t *scid)
|
||||
{
|
||||
unsigned int offset = 0;
|
||||
|
||||
int offset = 0;
|
||||
unsigned char packet_type = payload[offset];
|
||||
unsigned char is_long_header = packet_type & 0x80;
|
||||
if (is_long_header)
|
||||
@@ -682,7 +683,10 @@ static int quic_extract_header(const char *payload, unsigned char *long_packet_t
|
||||
// short header form, store dummy value that is not a long packet type.
|
||||
*long_packet_type = QUIC_SHORT_PACKET;
|
||||
offset++;
|
||||
|
||||
if(offset+6>=(int)payload_len) //verion_lenght: 4 ,scid_length_flag: 1 ,dcid_length_flag: 1
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*version = pntoh32((unsigned int *)&payload[offset]);
|
||||
|
||||
if (is_long_header) {
|
||||
@@ -697,16 +701,23 @@ static int quic_extract_header(const char *payload, unsigned char *long_packet_t
|
||||
// read DCID and SCID (both are prefixed by a length byte).
|
||||
unsigned char dcil = payload[offset];
|
||||
offset++;
|
||||
if(offset+dcil+1>=(int)payload_len) //scid_length_flag: +1
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dcil && dcil <= QUIC_MAX_CID_LENGTH) {
|
||||
memcpy(dcid->cid, &payload[offset], dcil);
|
||||
dcid->len = dcil;
|
||||
}
|
||||
offset += dcil;
|
||||
|
||||
|
||||
unsigned char scil = payload[offset];
|
||||
offset++;
|
||||
|
||||
if(offset+scil>=(int)payload_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (scil && scil <= QUIC_MAX_CID_LENGTH) {
|
||||
memcpy(scid->cid, &payload[offset], scil);
|
||||
scid->len = scil;
|
||||
@@ -719,6 +730,10 @@ static int quic_extract_header(const char *payload, unsigned char *long_packet_t
|
||||
// For short headers, the DCID length is unknown and could be 0 or
|
||||
// anything from 1 to 20 bytes. Copy the maximum possible and let the
|
||||
// consumer truncate it as necessary.
|
||||
if(offset+QUIC_MAX_CID_LENGTH>=(int)payload_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
memcpy(dcid->cid, &payload[offset], QUIC_MAX_CID_LENGTH);
|
||||
dcid->len = QUIC_MAX_CID_LENGTH;
|
||||
offset += QUIC_MAX_CID_LENGTH;
|
||||
@@ -727,6 +742,16 @@ static int quic_extract_header(const char *payload, unsigned char *long_packet_t
|
||||
return offset;
|
||||
}
|
||||
|
||||
static void free_quic_cipher(quic_ciphers *initial_ciphers)
|
||||
{
|
||||
if(initial_ciphers!=NULL)
|
||||
{
|
||||
quic_hp_cipher_reset(&(initial_ciphers->hp_cipher));
|
||||
quic_pp_cipher_reset(&(initial_ciphers->pp_cipher));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int dissect_quic(const char *payload, unsigned int length, unsigned char *out, unsigned int *out_length)
|
||||
{
|
||||
guint offset = 0;
|
||||
@@ -739,12 +764,12 @@ int dissect_quic(const char *payload, unsigned int length, unsigned char *out, u
|
||||
guint8 first_byte = 0;
|
||||
const gboolean from_server = FALSE;
|
||||
quic_ciphers *ciphers = NULL;
|
||||
int ret;
|
||||
int ret, out_len;
|
||||
|
||||
memset(&quic_packet, 0, sizeof(quic_packet_info_t));
|
||||
memset(&conn, 0, sizeof(quic_info_data_t));
|
||||
|
||||
ret = quic_extract_header(payload, &long_packet_type, &conn.version, &dcid, &scid);
|
||||
ret = quic_extract_header(payload, length, &long_packet_type, &conn.version, &dcid, &scid);
|
||||
if (ret < 0)
|
||||
{
|
||||
return -1;
|
||||
@@ -760,12 +785,23 @@ int dissect_quic(const char *payload, unsigned int length, unsigned char *out, u
|
||||
guint32 pkn32 = 0;
|
||||
// PKN is after type(1) + version(4) + DCIL+DCID + SCIL+SCID
|
||||
guint pn_offset = 1 + 4 + 1 + dcid.len + 1 + scid.len;
|
||||
if(pn_offset+8>=length) //tvb_get_varint max: 8
|
||||
{
|
||||
free_quic_cipher(&conn.client_initial_ciphers);
|
||||
free_quic_cipher(&conn.server_initial_ciphers);
|
||||
return 0;
|
||||
}
|
||||
pn_offset += tvb_get_varint(payload, pn_offset, 8, &token_length, ENC_VARINT_QUIC);
|
||||
pn_offset += (guint)token_length;
|
||||
// printf("%d\n", token_length);
|
||||
if(pn_offset+8>=length) //tvb_get_varint max: 8
|
||||
{
|
||||
free_quic_cipher(&conn.client_initial_ciphers);
|
||||
free_quic_cipher(&conn.server_initial_ciphers);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pn_offset += tvb_get_varint(payload, pn_offset, 8, &payload_length, ENC_VARINT_QUIC);
|
||||
if(payload_length==0 || payload_length >1500)
|
||||
if(payload_length==0 || payload_length >length || pn_offset>=length)
|
||||
{
|
||||
quic_packet.decryption.error = (const guchar*)"Payload length is too small or too long";
|
||||
}
|
||||
@@ -775,8 +811,12 @@ int dissect_quic(const char *payload, unsigned int length, unsigned char *out, u
|
||||
ciphers = &conn.client_initial_ciphers;
|
||||
error = "Header deprotection failed";
|
||||
if (quic_decrypt_header(payload, pn_offset, &ciphers->hp_cipher, GCRY_CIPHER_AES128, &first_byte, &pkn32))
|
||||
{
|
||||
error = NULL;
|
||||
if (!error) {
|
||||
}
|
||||
|
||||
if (!error)
|
||||
{
|
||||
quic_set_full_packet_number(&conn, &quic_packet, from_server, first_byte, pkn32);
|
||||
quic_packet.first_byte = first_byte;
|
||||
}
|
||||
@@ -791,8 +831,9 @@ int dissect_quic(const char *payload, unsigned int length, unsigned char *out, u
|
||||
// Out
|
||||
if (!quic_packet.decryption.error)
|
||||
{
|
||||
memcpy(out, quic_packet.decryption.data, quic_packet.decryption.data_len);
|
||||
*out_length = quic_packet.decryption.data_len;
|
||||
out_len=MIN(quic_packet.decryption.data_len, *out_length);
|
||||
memcpy(out, quic_packet.decryption.data, out_len);
|
||||
*out_length = out_len;
|
||||
|
||||
g_free((gpointer)quic_packet.decryption.data);
|
||||
quic_packet.decryption.data = NULL;
|
||||
@@ -804,10 +845,8 @@ int dissect_quic(const char *payload, unsigned int length, unsigned char *out, u
|
||||
ret=0;
|
||||
}
|
||||
|
||||
quic_hp_cipher_reset(&conn.client_initial_ciphers.hp_cipher);
|
||||
quic_pp_cipher_reset(&conn.client_initial_ciphers.pp_cipher);
|
||||
quic_hp_cipher_reset(&conn.server_initial_ciphers.hp_cipher);
|
||||
quic_pp_cipher_reset(&conn.server_initial_ciphers.pp_cipher);
|
||||
free_quic_cipher(&conn.client_initial_ciphers);
|
||||
free_quic_cipher(&conn.server_initial_ciphers);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user