/* * gquic_process.c * * Created on: 2019年4月2日 * Author: root */ #include "gquic_process.h" #include "quic_analysis.h" #include "quic_callback.h" #include #include #include #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, int thread_seq, char * payload, uint32_t payload_len, struct quic_stream* a_quic_stream){ 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, int thread_seq, char * payload, uint32_t payload_len, struct quic_stream* a_quic_stream){ 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 协商 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); } }