This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
mesa-platform-quic/src/gquic_process.c

1083 lines
34 KiB
C
Raw Normal View History

2020-05-12 12:18:02 +08:00
/*
* gquic_process.c
*
* Created on: 2019<EFBFBD><EFBFBD>4<EFBFBD><EFBFBD>2<EFBFBD><EFBFBD>
* Author: root
*/
#include "gquic_process.h"
#include "quic_analysis.h"
#include "quic_callback.h"
#include <stdbool.h>
#include <stdio.h>
#include<assert.h>
#define C2S 0x01
#define S2C 0x02
#define GQUIC_HANDSHAKE_LEN 12+1+1+4+4
#define DIVERSIFICATION_NONCE_LEN 32
enum gquic_type {
GQUIC=1, UNKNOWN_QUIC_TYPE
};
enum gquic_handshake_type {
QUIC_Crypto=1, UNKNOWN_HANDSHAKE_TYPE
};
//QUIC_DATA:is quic data pcap;QUIC_TRUE:is handshake pcap;QUIC_RETURN_DROPME:not quic protocol;
UCHAR is_handshake_pkt(struct quic_stream* a_quic_stream,uint32_t pkt_num_len,
char * quic_data, UINT32 quic_data_len, UINT32 offset){
UINT8 frame_type = 0, num_timestamp, num_ranges, num_revived, num_blocks;
UINT32 len_stream = 0, len_offset = 0, len_data = 0, len_largest_observed = 0, len_missing_packet = 0;
if(!a_canRead(GQUIC_HANDSHAKE_LEN, quic_data_len, offset)){
return QUIC_FALSE;
}
//message authentication hash
if(!a_canRead(MSG_AUTH_HASH_LEN, quic_data_len, offset)){
return QUIC_FALSE;
}
offset += MSG_AUTH_HASH_LEN;
//private flags
if(a_quic_stream->version > 0 && a_quic_stream->version < 34){
offset += 1;
}
while(offset < quic_data_len){
frame_type = quic_data[offset];
//offset+=1;
if(!(frame_type & FRAM_SPECIAL)){
offset += 1;
UINT16 len_reason;
switch(frame_type){
case PADDING:
return QUIC_FALSE;
break;
case RST_STREAM:
//stream id
offset += 4;
//Byte Offset
offset += 8;
//Error Code
offset += 4;
break;
case CONNECTION_CLOSE:
len_reason = 0;
//Error Code
offset += 4;
//Reason Phrase Length
if (get_remaining_len(quic_data_len, offset) <= 2){
return QUIC_FALSE;
}
len_reason = a_pntoh16(quic_data, offset);
offset += 2;
//Reason Phrase,If length remaining == len_reason, it is Connection Close
if (get_remaining_len(quic_data_len, offset) == len_reason){
return QUIC_DATA;
}
break;
case GOAWAY:{
len_reason = 0;
//Error Code
offset += 4;
//Last Good Stream ID
offset += 4;
//Reason Phrase Length
if (get_remaining_len(quic_data_len, offset) <= 2){
return QUIC_FALSE;
}
len_reason = a_pntoh16(quic_data, offset);
offset += 2;
//Reason Phrase
offset += len_reason;
}
break;
case WINDOW_UPDATE:
//Stream ID
offset += 4;
//Byte Offset
offset += 8;
break;
case BLOCKED:
//Stream ID
offset += 4;
break;
case STOP_WAITING:
//No longer Entropy after Q034
if(a_quic_stream->version > 0 && a_quic_stream->version < 34){
// Send Entropy
offset += 1;
}
//Least Unacked Delta
offset += pkt_num_len;
break;
case PING: //No Payload
default:
return QUIC_FALSE;
break;
}
}else{
if(frame_type & STREAM){
if(frame_type & STREAM_D){
len_data = 2;
}
len_offset = read_offset_len(frame_type);
len_stream = read_stream_len(frame_type);
offset+=1;
offset+=len_stream;
offset+=len_offset;
offset+=len_data;
if (get_remaining_len(quic_data_len, offset) <= 4){
return QUIC_FALSE;
}
UINT32 message_tag;
strncpy((char*)&message_tag, quic_data+offset, 4);
if(ntohl(message_tag) == CHLO || ntohl(message_tag) == SHLO || ntohl(message_tag) == REJ){
return QUIC_TRUE;
}
}else if(frame_type & ACK){
offset+=1;
len_largest_observed = read_largest_observed_len(frame_type);
len_missing_packet = read_missing_packet_len(frame_type);
//No longer Entropy after Q034
if(a_quic_stream->version < 34 && a_quic_stream->version > 0){
//Send Entropy
offset += 1;
offset += len_largest_observed;
offset += 2; //ack delay time
if(get_remaining_len(quic_data_len, offset) <= 1){
return QUIC_FALSE;
}
strncpy((char*)&num_timestamp, quic_data+offset,1);
offset += 1;
if(num_timestamp > 0){
offset += 1;
offset += 4; //first timestamp
offset += (num_timestamp - 1)*(1+2);
}
if(frame_type & ACK_N){
//Num Ranges
if (get_remaining_len(quic_data_len, offset) <= 1){
return QUIC_FALSE;
}
strncpy((char*)&num_ranges, quic_data+offset,1);
offset += 1;
//Num Range x (Missing Packet + Range Length)
offset += num_ranges*(len_missing_packet+1);
//Num Revived
if (get_remaining_len(quic_data_len, offset) <= 1){
return QUIC_FALSE;
}
strncpy((char*)&num_revived, quic_data+offset,1);
offset += 1;
//Num Revived x Length Largest Observed
offset += num_revived*len_largest_observed;
}
}else{
//Largest Acked
offset += len_largest_observed;
//Largest Acked Delta Time
offset += 2;
//Ack Block
if(frame_type & ACK_N){
if (get_remaining_len(quic_data_len, offset) <= 1){
return QUIC_FALSE;
}
strncpy((char*)&num_blocks, quic_data+offset,1);
offset += 1;
}
//First Ack Block Length
offset += len_missing_packet;
if(num_blocks){
//Gap to next block
offset += 1;
num_blocks -= 1;
offset += (num_blocks - 1)*len_missing_packet;
}
//Timestamp
if (get_remaining_len(quic_data_len, offset) <= 1){
return QUIC_FALSE;
}
strncpy((char*)&num_timestamp, quic_data+offset,1);
offset += 1;
if(num_timestamp > 0){
//Delta Largest Acked
offset += 1;
//Time Since Largest Acked
offset += 4;
//Num Timestamp x (Delta Largest Acked + Time Since Previous Timestamp)
offset += (num_timestamp - 1)*(1+2);
}
}
}else{
offset +=1;
return QUIC_FALSE;
}
}
}
return QUIC_FALSE;
}
void gquic_proc_tag(struct streaminfo *pstream, struct quic_stream *a_quic_stream, UINT16 tag_num, UINT8 direction,
unsigned long long region_flag, int thread_seq, void* a_packet, char * quic_data, UINT32 quic_data_len, UINT32 g_pos_t){
UINT32 total_tag_len = 0, tag_len = 0;
UINT32 tag_value_start = tag_num * 4 * 2 + g_pos_t;
UINT32 tag_offset_end = 0, pre_tag_offset_end = 0;
UCHAR return_val;
int tag_type_len = 4, tag_offset_len = 4, num = 0;
while(tag_num > 0 && a_canRead(tag_type_len + tag_offset_len, quic_data_len, g_pos_t)){
UINT32 tag_type;
if(!a_canRead(tag_type_len, quic_data_len, g_pos_t)){
return;
}
tag_type = a_pntoh32(quic_data, g_pos_t);
g_pos_t += 4;
if(!a_canRead(tag_type_len, quic_data_len, g_pos_t)){
return;
}
tag_offset_end = a_pletoh32(quic_data, g_pos_t);
if(tag_offset_end < pre_tag_offset_end){
return;
}
if(tag_offset_end >= quic_data_len) {
return ;
}
g_pos_t += 4;
tag_len = tag_offset_end - pre_tag_offset_end;
if(!a_canRead(tag_len, quic_data_len, tag_value_start)){
return ;
}
total_tag_len += tag_len;
if(tag_len == 0){
tag_num--;
tag_value_start += tag_len;
pre_tag_offset_end = tag_offset_end;
continue;
}
if(tag_type == TAG_PAD){
tag_num--;
tag_value_start += tag_len;
pre_tag_offset_end = tag_offset_end;
continue;
}
//common_cert
if(tag_type == TAG_CCS){
if(a_quic_stream->common_cert.ptr_value == NULL){
a_quic_stream->common_cert.ptr_value = (char *)dictator_malloc(thread_seq, sizeof(char)*tag_len);
memset(a_quic_stream->common_cert.ptr_value, 0, tag_len);
a_quic_stream->common_cert.length = tag_len;
memcpy(a_quic_stream->common_cert.ptr_value, quic_data + tag_value_start, tag_len);
if(a_quic_stream->common_cert.ptr_value != NULL){
return_val = quic_proc_interest_region(QUIC_COMM_CERT_MASK, &a_quic_stream, pstream, region_flag, thread_seq, a_packet);
}
}
tag_num--;
tag_value_start += tag_len;
pre_tag_offset_end = tag_offset_end;
continue;
}
//cached_cert
if(tag_type == TAG_CCRT){
if(a_quic_stream->cached_cert.ptr_value == NULL){
a_quic_stream->cached_cert.ptr_value = (char *)dictator_malloc(thread_seq, sizeof(char)*tag_len);
memset(a_quic_stream->cached_cert.ptr_value, 0, tag_len);
a_quic_stream->cached_cert.length = tag_len;
memcpy(a_quic_stream->cached_cert.ptr_value, quic_data + tag_value_start, tag_len);
if(a_quic_stream->cached_cert.ptr_value != NULL){
return_val = quic_proc_interest_region(QUIC_CACHED_CERT_MASK, &a_quic_stream, pstream, region_flag, thread_seq, a_packet);
}
}
tag_num--;
tag_value_start += tag_len;
pre_tag_offset_end = tag_offset_end;
continue;
}
//cert_chain?????length need change
if(tag_type == TAG_CRT){
if(a_quic_stream->cert_chain.length == 0 && a_quic_stream->cert_chain.ptr_value == NULL){
a_quic_stream->cert_chain.length = tag_len > (quic_data_len-tag_value_start+1) ? (quic_data_len-tag_value_start+1) : tag_len;
a_quic_stream->cert_chain.ptr_value = (char *)dictator_malloc(thread_seq, a_quic_stream->cert_chain.length);
memset(a_quic_stream->cert_chain.ptr_value, 0, a_quic_stream->cert_chain.length);
memcpy(a_quic_stream->cert_chain.ptr_value, quic_data + tag_value_start, a_quic_stream->cert_chain.length);
tag_num--;
tag_value_start += a_quic_stream->cert_chain.length;
pre_tag_offset_end = tag_offset_end;
if(a_quic_stream->cert_chain.ptr_value != NULL){
return_val = quic_proc_interest_region(QUIC_CERT_CHAIN_MASK, &a_quic_stream, pstream, region_flag, thread_seq, a_packet);
}
}else{
tag_num--;
tag_value_start += tag_len;
pre_tag_offset_end = tag_offset_end;
}
continue;
}
if(tag_type == TAG_SNI){
if(a_quic_stream->st_client_hello.server_name_len ==0){
assert(tag_len < SERVER_NAME_LEN);
a_quic_stream->st_client_hello.server_name_len = tag_len > SERVER_NAME_LEN ? SERVER_NAME_LEN : tag_len;
strncpy(a_quic_stream->st_client_hello.server_name, quic_data + tag_value_start, tag_len);
a_quic_stream->st_client_hello.server_name_len = tag_len;
// printf("SNI:%s\n",a_quic_stream->st_client_hello.server_name);
}
tag_num--;
tag_value_start += tag_len;
pre_tag_offset_end = tag_offset_end;
continue;
}
if(tag_type == TAG_UAID){
assert(tag_len < USER_AGENT_LEN);
if(a_quic_stream->st_client_hello.user_agent_len==0){
a_quic_stream->st_client_hello.user_agent_len = tag_len > USER_AGENT_LEN ? USER_AGENT_LEN : tag_len;
strncpy(a_quic_stream->st_client_hello.user_agent, quic_data + tag_value_start, a_quic_stream->st_client_hello.user_agent_len);
// printf("UA:%s\n",a_quic_stream->st_client_hello.user_agent);
}
tag_num--;
tag_value_start += tag_len;
pre_tag_offset_end = tag_offset_end;
continue;
}
if(direction == 0x01 && num < a_quic_stream->st_client_hello.ext_tag_num){
a_quic_stream->st_client_hello.ext_tags[num]->type = tag_type;
a_quic_stream->st_client_hello.ext_tags[num]->length = tag_len > MAX_TAG_VALUE_LEN-1 ? tag_len > MAX_TAG_VALUE_LEN-1 : tag_len;
memcpy(a_quic_stream->st_client_hello.ext_tags[num]->ptr_value, quic_data+tag_value_start, a_quic_stream->st_client_hello.ext_tags[num]->length);
// a_readBytes(a_quic_stream->st_client_hello.ext_tags[num]->ptr_value,
// a_quic_stream->st_client_hello.ext_tags[num]->length, quic_data, quic_data_len, &tag_value_start);
((unsigned char*)(a_quic_stream->st_client_hello.ext_tags[num]->ptr_value))[MAX_TAG_VALUE_LEN-1] = '\0';
}else if(num < a_quic_stream->st_server_hello.ext_tag_num){
a_quic_stream->st_server_hello.ext_tags[num]->type = tag_type;
a_quic_stream->st_server_hello.ext_tags[num]->length = tag_len > MAX_TAG_VALUE_LEN-1 ? tag_len > MAX_TAG_VALUE_LEN-1 : tag_len;
memcpy(a_quic_stream->st_server_hello.ext_tags[num]->ptr_value, quic_data+tag_value_start, a_quic_stream->st_server_hello.ext_tags[num]->length);
// a_readBytes(a_quic_stream->st_server_hello.ext_tags[num]->ptr_value,
// a_quic_stream->st_server_hello.ext_tags[num]->length, quic_data, quic_data_len, &tag_value_start);
((unsigned char*)(a_quic_stream->st_server_hello.ext_tags[num]->ptr_value))[MAX_TAG_VALUE_LEN-1] = '\0';
}
num++;
tag_num--;
tag_value_start += tag_len;
pre_tag_offset_end = tag_offset_end;
}
g_pos_t = tag_value_start;
return;
}
//frame type->stream->offset->data length
void gquic_proc_unencrypt(struct streaminfo *pstream, struct quic_stream* a_quic_stream, uint32_t pkt_num_len,
unsigned long long region_flag, int thread_seq, void* a_packet, char * quic_data, UINT32 quic_data_len, UINT32 g_pos_t){
UINT8 frame_type, num_timestamp, num_ranges, num_revived, num_blocks;
UINT32 len_largest_observed = 0, len_missing_packet = 0;
g_pos_t += MSG_AUTH_HASH_LEN;
//private flags
if(a_quic_stream->version <34){
g_pos_t += 1;
}
while(g_pos_t < quic_data_len){
a_readUInt8(&frame_type, quic_data, quic_data_len, &g_pos_t);
if(!(frame_type & FRAM_SPECIAL)){
g_pos_t += 1;
UINT16 len_reason;
switch(frame_type){
case PADDING:
return;
break;
case RST_STREAM:
//stream id
g_pos_t += 4;
//Byte Offset
g_pos_t += 8;
//Error Code
g_pos_t += 4;
a_quic_stream->fin_flag = QUIC_TRUE;
break;
case CONNECTION_CLOSE:
len_reason = 0;
//Error Code
g_pos_t += 4;
//Reason Phrase Length
len_reason = a_pntoh16(quic_data, g_pos_t);
g_pos_t += 2;
//Reason Phrase,If length remaining == len_reason, it is Connection Close
if (get_remaining_len(quic_data_len, g_pos_t) == len_reason){
return;
}
if(a_quic_stream->fin_flag == QUIC_FALSE){
a_quic_stream->fin_flag = QUIC_HALF_CLOSE;
}else{
a_quic_stream->fin_flag = QUIC_TRUE;
}
break;
case GOAWAY:{
len_reason = 0;
//Error Code
g_pos_t += 4;
//Last Good Stream ID
g_pos_t += 4;
//Reason Phrase Length
len_reason = a_pntoh16(quic_data, g_pos_t);
g_pos_t += 2;
//Reason Phrase
g_pos_t += len_reason;
}
break;
case WINDOW_UPDATE:
//Stream ID
g_pos_t += 4;
//Byte Offset
g_pos_t += 8;
break;
case BLOCKED:
//Stream ID
g_pos_t += 4;
break;
case STOP_WAITING:
//No longer Entropy after Q034
if(a_quic_stream->version < 34){
// Send Entropy
g_pos_t += 1;
}
//Least Unacked Delta
g_pos_t += pkt_num_len;
break;
case PING: //No Payload
default:
return;
break;
}
}else{
//special packet
if(frame_type & STREAM){
UINT8 len_data = 0, len_stream = 0, len_offset = 0, return_val;
UINT16 tag_num = 0;
UINT32 stream_id, message_tag;
if(frame_type & STREAM_F){
a_quic_stream->fin_flag = QUIC_TRUE;
}
if(frame_type & STREAM_D){
len_data = 2;
}
len_stream = read_stream_len(frame_type);
stream_id = get_stream_id(quic_data, g_pos_t, len_stream);
g_pos_t += len_stream;
len_offset = read_offset_len(frame_type);
g_pos_t += len_offset;
g_pos_t += len_data;
//handshake
if(stream_id == 1){
message_tag = a_pntoh32((void *)quic_data, g_pos_t);
g_pos_t += 4;
tag_num = a_pletoh16(quic_data, g_pos_t);
g_pos_t += 2; //tag_num
g_pos_t += 2; //padding
switch(message_tag){
case CHLO:
//MTAG_CHLO;
if(a_quic_stream->st_client_hello.ext_tags == NULL){
// a_quic_stream->st_client_hello = (struct quic_client_hello*)dictator_malloc(thread_seq,sizeof(struct quic_client_hello));
// memset(a_quic_stream->st_client_hello, 0, sizeof(struct quic_client_hello));
quic_init_clientHello(&a_quic_stream->st_client_hello, tag_num, thread_seq);
}else if(a_quic_stream->st_server_hello.ext_tag_num){
if(tag_num > a_quic_stream->st_client_hello.ext_tag_num){
// a_quic_stream->is_0rtt = QUIC_TRUE;
quic_release_clientHello(thread_seq, &a_quic_stream->st_client_hello);
quic_init_clientHello(&a_quic_stream->st_client_hello, tag_num, thread_seq);
}else{
return;
}
}else{
return;
}
gquic_proc_tag(pstream, a_quic_stream, tag_num, C2S, region_flag, thread_seq, a_packet, quic_data, quic_data_len, g_pos_t);
if(a_quic_stream->st_client_hello.server_name_len > 0 || a_quic_stream->st_client_hello.user_agent_len > 0){
quic_proc_interest_region(QUIC_CLIENT_HELLO_MASK, &a_quic_stream, pstream, region_flag, thread_seq, a_packet);
}
// if(return_val != QUIC_RETURN_NORM){
// return return_val;
// }
break;
case SHLO:
//MTAG_SHLO;
if(a_quic_stream->st_server_hello.ext_tags == NULL){
// a_quic_stream->st_server_hello = (struct quic_server_hello*)dictator_malloc(thread_seq,sizeof(struct quic_server_hello));
// memset(a_quic_stream->st_server_hello, 0, sizeof(struct quic_server_hello));
quic_init_serverHello(&a_quic_stream->st_server_hello, tag_num, thread_seq);
}else{
return;
}
gquic_proc_tag(pstream, a_quic_stream, tag_num, S2C, region_flag, thread_seq, a_packet, quic_data, quic_data_len, g_pos_t);
if(a_quic_stream->st_server_hello.ext_tags != NULL){
quic_proc_interest_region(QUIC_SERVER_HELLO_MASK, &a_quic_stream, pstream, region_flag, thread_seq, a_packet);
}
// if(return_val != QUIC_RETURN_NORM){
// return return_val;
// }
break;
case REJ:
//MTAG_REJ;
if(a_quic_stream->st_server_hello.ext_tags == NULL){
// a_quic_stream->st_server_hello = (struct quic_server_hello*)dictator_malloc(thread_seq,sizeof(struct quic_server_hello));
// memset(a_quic_stream->st_server_hello, 0, sizeof(struct quic_server_hello));
quic_init_serverHello(&a_quic_stream->st_server_hello, tag_num, thread_seq);
}else{
return;
}
gquic_proc_tag(pstream, a_quic_stream, tag_num, S2C, region_flag, thread_seq, a_packet, quic_data, quic_data_len, g_pos_t);
if(a_quic_stream->st_server_hello.ext_tags != NULL){
quic_proc_interest_region(QUIC_SERVER_HELLO_MASK, &a_quic_stream, pstream, region_flag, thread_seq, a_packet);
}
// if(return_val != QUIC_RETURN_NORM){
// return return_val;
// }
break;
default:
break;
}
}
}else if(frame_type & ACK){
g_pos_t+=1;
len_largest_observed = read_largest_observed_len(frame_type);
len_missing_packet = read_missing_packet_len(frame_type);
//No longer Entropy after Q034
if(a_quic_stream->version < 34){
//Send Entropy
g_pos_t += 1;
g_pos_t += len_largest_observed;
g_pos_t += 2; //ack delay time
strncpy((char*)&num_timestamp, quic_data+g_pos_t,1);
g_pos_t += 1;
if(num_timestamp > 0){
g_pos_t += 1;
g_pos_t += 4;
g_pos_t += (num_timestamp - 1)*(1+2);
}
if(frame_type & ACK_N){
strncpy((char*)&num_ranges, quic_data+g_pos_t,1);
g_pos_t += 1;
g_pos_t += num_ranges*(len_missing_packet+1);
strncpy((char*)&num_revived, quic_data+g_pos_t,1);
g_pos_t += 1;
//Num Revived x Length Largest Observed
g_pos_t += num_revived*len_largest_observed;
}
}else{
//Largest Acked
g_pos_t += len_largest_observed;
//Largest Acked Delta Time
g_pos_t += 2;
//Ack Block
if(frame_type & ACK_N){
strncpy((char*)&num_blocks, quic_data+g_pos_t,1);
g_pos_t += 1;
}
//First Ack Block Length
g_pos_t += len_missing_packet;
if(num_blocks){
//Gap to next block
g_pos_t += 1;
num_blocks -= 1;
g_pos_t += (num_blocks - 1)*len_missing_packet;
}
//Timestamp
strncpy((char*)&num_timestamp, quic_data+g_pos_t,1);
g_pos_t += 1;
if(num_timestamp > 0){
//Delta Largest Acked
g_pos_t += 1;
//Time Since Largest Acked
g_pos_t += 4;
//Num Timestamp x (Delta Largest Acked + Time Since Previous Timestamp)
g_pos_t += (num_timestamp - 1)*(1+2);
}
}
}else{
g_pos_t +=1;
return;
}
}
}
return;
}
UINT8 parse_gquic_Q046(struct streaminfo *pstream, unsigned long long region_flag, void* a_packet,
2020-05-20 14:52:44 +08:00
int thread_seq, char * payload, uint32_t payload_len, struct quic_stream* a_quic_stream){
2020-05-12 12:18:02 +08:00
uint32_t g_pos_t = 0;
if (!a_canRead(5, payload_len, g_pos_t)) {
return QUIC_RETURN_DROPME;
}
uint32_t version;
g_pos_t += 1;
strncpy((char*)&version, payload+g_pos_t, 4);
if(ntohl(version) != VER_Q046){
return QUIC_RETURN_DROPME;
}
g_pos_t += 2;
a_quic_stream->version = (payload[g_pos_t] & 0x0f) * 10 + (payload[g_pos_t+1] & 0x0f);
a_quic_stream->is_quic_stream = QUIC_TRUE;
quic_proc_interest_region(QUIC_VERSION_MASK, &a_quic_stream, pstream, region_flag, thread_seq, a_packet);
g_pos_t += 2;
if (!a_canRead(25, payload_len, g_pos_t)) {
return QUIC_RETURN_DROPME;
}
g_pos_t += 25;
uint8_t frame_type;
while(g_pos_t < payload_len){
a_readUInt8(&frame_type, payload, payload_len, &g_pos_t);
if(frame_type & STREAM){
uint8_t len_data = 0, len_stream = 0, len_offset = 0;
uint16_t tag_num = 0;
uint32_t stream_id, message_tag;
if(frame_type & STREAM_D){
len_data = 2;
}
len_stream = read_stream_len(frame_type);
stream_id = get_stream_id(payload, g_pos_t, len_stream);
g_pos_t += len_stream;
len_offset = read_offset_len(frame_type);
g_pos_t += len_offset;
g_pos_t += len_data;
if(stream_id == 1){
message_tag = a_pntoh32((void *)payload, g_pos_t);
g_pos_t += 4;
tag_num = a_pletoh16(payload, g_pos_t);
g_pos_t += 2; //tag_num
g_pos_t += 2; //padding
char sni[1024];
uint32_t sni_len = 0;
char uaid[1024];
uint32_t uaid_len = 0;
switch(message_tag){
case CHLO:
//MTAG_CHLO;
if(a_quic_stream->st_client_hello.ext_tags == NULL){
quic_init_clientHello(&a_quic_stream->st_client_hello, tag_num, thread_seq);
}
gquic_proc_tag(pstream, a_quic_stream, tag_num, C2S, region_flag, thread_seq, a_packet, payload, payload_len, g_pos_t);
if(a_quic_stream->st_client_hello.server_name_len > 0 || a_quic_stream->st_client_hello.user_agent_len > 0){
quic_proc_interest_region(QUIC_CLIENT_HELLO_MASK, &a_quic_stream, pstream, region_flag, thread_seq, a_packet);
}
// *chello = (struct quic_pme *)malloc(sizeof(struct quic_pme) + sni_len + uaid_len + 2);
// memset(*chello, 0, sizeof(struct quic_pme) + sni_len + uaid_len + 2);
// *chello = (struct quic_pme *)malloc(sizeof(struct quic_pme));
// memset(*chello, 0, sizeof(struct quic_pme));
// if(sni_len > 128){
// sni_len = GQUIC_SNI_LEN;
// }
// a_quic_stream->st_client_hello->server_name_len = sni_len;
// memcpy((chello)->sni, sni, sni_len);
// (chello)->sni[127] = '\0';
// if(uaid_len > 512){
// uaid_len = GQUIC_UAID_LEN;
// }
// (chello)->user_agent_len = uaid_len;
// memcpy((chello)->user_agent, uaid, uaid_len);
// (chello)->user_agent[511] = '\0';
// char * p, *q;
// p = (char*)(*chello) + sizeof(struct quic_pme);
// q = (char*)(*chello) + sizeof(struct quic_pme) + sni_len + 1;
// memcpy(p, sni, sni_len);
// memset(p+sni_len, '\0', 1);
// (*chello)->sni = p;
// memcpy(q, uaid, uaid_len);
// memset(q+uaid_len, '\0', 1);
// (*chello)->user_agent = q;
// printf("46 chello_sni_len:%d, chello_sni:%s\n",(*chello)->sni_len, (*chello)->sni);
// printf("46 chello_uaid_len:%d, chello_uaid:%s\n",(*chello)->user_agent_len, (*chello)->user_agent);
break;
default:
break;
}
}
}
}
return QUIC_RETURN_NORM;
}
UINT8 parse_gquic(struct streaminfo *pstream, unsigned long long region_flag, void* a_packet,
2020-05-20 14:52:44 +08:00
int thread_seq, char * payload, uint32_t payload_len, struct quic_stream* a_quic_stream){
2020-05-12 12:18:02 +08:00
uint8_t pub_flags = 0;
uint8_t nonce_flag = 0;
uint8_t reset_flag = 0;
uint8_t version_flag = 0;
int ret = QUIC_RETURN_DROPME;
uint32_t g_pos_t = 0;
uint64_t connection_id = 0;
int connection_id_len = 0;
uint32_t pkt_num = 0;
uint32_t pkt_num_len = 0;
uint32_t version;
strncpy((char *)&pub_flags, payload + g_pos_t, 1);
g_pos_t += 1;
if (pub_flags > PACKET_PUBLIC_FLAGS_MAX) {
return QUIC_RETURN_DROPME;
}
nonce_flag = (pub_flags & PUBLIC_FLAG_NONCE) != 0;
reset_flag = (pub_flags & PUBLIC_FLAG_RST) != 0;
version_flag = (pub_flags & PUBLIC_FLAG_VER) != 0;
if (reset_flag && version_flag) {
return QUIC_RETURN_DROPME;
}
if(reset_flag){
return QUIC_RETURN_DROPME;
}
connection_id_len = read_conn_id_len(pub_flags);
if(connection_id_len == -1){
return QUIC_RETURN_DROPME;
}else if(connection_id_len == 0){
connection_id = 0;
}else{
if (!a_canRead(connection_id_len, payload_len, g_pos_t)) {
return QUIC_RETURN_DROPME;
}
connection_id = a_pntoh64((void *)payload, g_pos_t);
g_pos_t += connection_id_len;
}
pkt_num_len = read_seq_num_len(pub_flags);
if (!a_canRead(VERSION_LEN, payload_len, g_pos_t)) {
return QUIC_RETURN_DROPME;
}
if(payload[g_pos_t] != PUBLIC_FLAG_VER_FST_BYTE){
return QUIC_RETURN_DROPME;
}
g_pos_t += 2;
version = (payload[g_pos_t] & 0x0f) * 10 + (payload[g_pos_t+1] & 0x0f);
a_quic_stream->version = version;
quic_proc_interest_region(QUIC_VERSION_MASK, &a_quic_stream, pstream, region_flag, thread_seq, a_packet);
g_pos_t += 2;
if (!a_canRead(pkt_num_len, payload_len, g_pos_t)) {
return QUIC_RETURN_DROPME;
}
pkt_num = get_pkn(payload, g_pos_t, pkt_num_len);
g_pos_t += pkt_num_len;
//version Э<><D0AD>
if(!version_flag && a_quic_stream->version && !a_quic_stream->version_cfm){
a_quic_stream->version_cfm = QUIC_TRUE;
quic_proc_interest_region(QUIC_VERSION_MASK, &a_quic_stream, pstream, region_flag, thread_seq, a_packet);
}
ret = is_handshake_pkt(a_quic_stream, pkt_num_len, payload, payload_len, g_pos_t);
if(ret == QUIC_TRUE){
//handshake
if(!a_quic_stream->is_quic_stream){
a_quic_stream->is_quic_stream = QUIC_TRUE;
}
gquic_proc_unencrypt(pstream, a_quic_stream, pkt_num_len, region_flag, thread_seq, a_packet, payload, payload_len, g_pos_t);
ret = QUIC_RETURN_NORM;
}else if(ret == QUIC_DATA){
//ack or special stream
a_quic_stream->is_quic_stream = QUIC_TRUE;
ret = QUIC_RETURN_NORM;
}else{
//gquic data or not gquic packet
if(a_quic_stream->is_quic_stream){
quic_proc_interest_region(QUIC_APPLICATION_DATA_MASK, &a_quic_stream, pstream, region_flag, thread_seq, a_packet);
ret = QUIC_RETURN_NORM;
}else{
ret = QUIC_RETURN_DROPME;
}
}
return ret;
}
//cid->version->nounce->pkt num->ahn hash(12)
UINT8 gquic_process(struct streaminfo *pstream, struct quic_stream* a_quic_stream,
unsigned long long region_flag, int thread_seq, void* a_packet, char* quic_data, UINT32 quic_data_len) {
int ret = parse_gquic(pstream, region_flag, a_packet, thread_seq, quic_data, quic_data_len, a_quic_stream);
if(ret == QUIC_RETURN_DROPME){
ret = parse_gquic_Q046(pstream, region_flag, a_packet, thread_seq, quic_data, quic_data_len, a_quic_stream);
}
return ret;
/*
UINT8 pub_flags;
UCHAR return_val = QUIC_RETURN_NORM;
UINT32 g_pos_t = 0;
strncpy((char *)&pub_flags, quic_data + g_pos_t, 1);
g_pos_t += 1;
if (pub_flags > PACKET_PUBLIC_FLAGS_MAX) {
return QUIC_RETURN_DROPME;
}
struct gquic_pkt_hdr gquic_hdr = {};
memset(&gquic_hdr, 0, sizeof(struct gquic_pkt_hdr));
gquic_hdr.nonce_flag = (pub_flags & PUBLIC_FLAG_NONCE) != 0;
gquic_hdr.reset_flag = (pub_flags & PUBLIC_FLAG_RST) != 0;
gquic_hdr.version_flag = (pub_flags & PUBLIC_FLAG_VER) != 0;
if (gquic_hdr.reset_flag && gquic_hdr.version_flag) {
return QUIC_RETURN_DROPME;
}
if(gquic_hdr.reset_flag){
return QUIC_RETURN_DROPME;
}
gquic_hdr.connection_id_len = read_conn_id_len(pub_flags);
if(gquic_hdr.connection_id_len == -1){
return QUIC_RETURN_DROPME;
}else if(gquic_hdr.connection_id_len == 0){
gquic_hdr.connection_id = 0;
}else{
if (!a_canRead(gquic_hdr.connection_id_len, quic_data_len, g_pos_t)) {
return QUIC_RETURN_DROPME;
}
if(a_quic_stream->gquic_cID == 0){
gquic_hdr.connection_id = a_pntoh64((void *)quic_data, g_pos_t);
a_quic_stream->gquic_cID = gquic_hdr.connection_id;
}
g_pos_t+=gquic_hdr.connection_id_len;
}
if(gquic_hdr.nonce_flag && pstream->curdir == 0x02){
g_pos_t+=DIVERSIFICATION_NONCE_LEN;
}
gquic_hdr.packet_number_len = read_seq_num_len(pub_flags);
if (gquic_hdr.version_flag) {
//c2s
if(pstream->curdir == 0x01){
if (!a_canRead(4, quic_data_len, g_pos_t)) {
return QUIC_RETURN_DROPME;
}
if(quic_data[g_pos_t] != PUBLIC_FLAG_VER_FST_BYTE){
return QUIC_RETURN_DROPME;
}
g_pos_t += 2;
a_quic_stream->version_flag = QUIC_TRUE;
gquic_hdr.version = (quic_data[g_pos_t] & 0x0f) * 10 + (quic_data[g_pos_t+1] & 0x0f);
g_pos_t += 2;
a_quic_stream->version = gquic_hdr.version;
printf("VERSION:%d\n",a_quic_stream->version);
}
}
if(!gquic_hdr.version_flag && pstream->curdir == 0x02 && a_quic_stream->version_flag == QUIC_TRUE){
a_quic_stream->version_flag = QUIC_FALSE;
return_val = quic_proc_interest_region(QUIC_VERSION_MASK, &a_quic_stream, pstream, region_flag, thread_seq, a_packet);
// if(return_val != QUIC_RETURN_NORM){
// char info[256];
// sprintf(info, "VERSION CALLBACK ERROR\t%s_%s_%d\t", __FILE__, __FUNCTION__, __LINE__);
// printf("%s\n", info);
// return return_val;
// }
}
if(!a_canRead(gquic_hdr.packet_number_len, quic_data_len, g_pos_t)){
return QUIC_RETURN_DROPME;
}
UINT32 pkt_num = get_pkn(quic_data, g_pos_t, gquic_hdr.packet_number_len);
gquic_hdr.packet_number = pkt_num;
g_pos_t += gquic_hdr.packet_number_len;
char sip[32],dip[32];
memset(sip, 0, sizeof(sip));
memset(dip, 0, sizeof(dip));
a_ntoa(pstream->addr.tuple4_v4->saddr, sip);
a_ntoa(pstream->addr.tuple4_v4->daddr, dip);
return_val = is_handshake_pkt(a_quic_stream, &gquic_hdr, quic_data, quic_data_len, g_pos_t);
if(return_val == QUIC_TRUE){
//handshake
if(!a_quic_stream->is_quic_stream){
a_quic_stream->is_quic_stream = QUIC_TRUE;
}
gquic_proc_unencrypt(pstream, &gquic_hdr, a_quic_stream, region_flag, thread_seq, a_packet, quic_data, quic_data_len, g_pos_t);
return_val = QUIC_RETURN_NORM;
}else if(return_val == QUIC_DATA){
//ack or special stream
if(!a_quic_stream->is_quic_stream){
a_quic_stream->is_quic_stream = QUIC_TRUE;
}
}else{
//gquic data or not gquic packet
if(a_quic_stream->is_quic_stream){
return_val = quic_proc_interest_region(QUIC_APPLICATION_DATA_MASK, &a_quic_stream, pstream, region_flag, thread_seq, a_packet);
}else{
return_val = QUIC_RETURN_DROPME;
}
}
// if(a_quic_stream->type == GQUIC){
// if(pstream->curdir == 0x01){
// printf("QUIC\tC2S\tSIP=%s\tDIP=%s\tPKN=%d\tVERSION=%d\tthread_seq=%d\n",sip,dip,pkt_num,gquic_hdr.version,thread_seq);
// }else{
// printf("QUIC\tS2C\tSIP=%s\tDIP=%s\tPKN=%d\tVERSION=%d\tthread_seq=%d\n",sip,dip,pkt_num,gquic_hdr.version,thread_seq);
// }
// }
// else{
// if(pstream->curdir == 0x01){
// printf("UNKN\tC2S\tSIP=%s\tDIP=%s\tPKN=%d\tVERSION=%d\tthread_seq=%d\n",sip,dip,pkt_num,gquic_hdr.version,thread_seq);
// }else{
// printf("UNKN\tS2C\tSIP=%s\tDIP=%s\tPKN=%d\tVERSION=%d\tthread_seq=%d\n",sip,dip,pkt_num,gquic_hdr.version,thread_seq);
// }
// }
return return_val;
*/
}
UINT32 read_offset_len(UINT8 frame_type){
switch((frame_type & STREAM_OOO) >> 2){
case 0:
return 0;
break;
case 1:
return 2;
break;
case 2:
return 3;
break;
case 3:
return 4;
break;
case 4:
return 5;
break;
case 5:
return 6;
break;
case 6:
return 7;
break;
case 7:
return 8;
break;
default:
break;
}
return 0;
}
UINT32 read_stream_len(UINT8 frame_type){
UINT32 stream_len = 0;
switch(frame_type & STREAM_SS){
case STREAM_ID_1BYTE:
stream_len = 1;
break;
case STREAM_ID_2BYTE:
stream_len = 2;
break;
case STREAM_ID_3BYTE:
stream_len = 3;
break;
case STREAM_ID_4BYTE:
stream_len = 4;
break;
default:
break;
}
return stream_len;
}
int read_conn_id_len(UINT8 flags) {
switch (flags & BYTE_CNTID_8) {
case BYTE_CNTID_8:
return 8;
case BYTE_CNTID_0:
return 0;
default:
return -1;
}
}
UINT32 read_seq_num_len(UINT8 flags) {
switch (flags & PKT_NUM_6) {
case PKT_NUM_6:
return 6;
case PKT_NUM_4:
return 4;
case PKT_NUM_2:
return 2;
case PKT_NUM_1:
return 1;
default:
break;
}
return 1;
}
UINT32 read_largest_observed_len(UINT8 frame_type){
switch((frame_type & ACK_LL) >> 2){
case 0:
return 1;
break;
case 1:
return 2;
break;
case 2:
return 4;
break;
case 3:
return 6;
break;
default:
break;
}
return 1;
}
UINT32 read_missing_packet_len(UINT8 frame_type){
switch(frame_type & ACK_MM){
case 0:
return 1;
break;
case 1:
return 2;
break;
case 2:
return 4;
break;
case 3:
return 6;
break;
default:
break;
}
return 1;
}
UINT32 get_stream_id(char* g_data_t, UINT32 offset, UINT8 stream_id_len){
if(stream_id_len == 1){
return g_data_t[offset];
}else if(stream_id_len == 2){
return a_pletoh16((void *)g_data_t, offset);
}else if(stream_id_len == 3){
return a_pletoh24((void *)g_data_t, offset);
}else{
return a_pletoh32((void *)g_data_t, offset);
}
}
UINT32 get_pkn(char* g_data_t, UINT32 offset, UINT8 pkn_len){
if(pkn_len == 1){
return g_data_t[offset];
}else if(pkn_len == 2){
return a_pletoh16((void *)g_data_t, offset);
}else if(pkn_len == 4){
return a_pletoh32((void *)g_data_t, offset);
}else{//6
return a_pletoh48((void *)g_data_t, offset);
}
}