diff options
Diffstat (limited to 'src/lib/protocols/quic.c')
-rw-r--r-- | src/lib/protocols/quic.c | 74 |
1 files changed, 63 insertions, 11 deletions
diff --git a/src/lib/protocols/quic.c b/src/lib/protocols/quic.c index 84ad23799..2a4c7294b 100644 --- a/src/lib/protocols/quic.c +++ b/src/lib/protocols/quic.c @@ -43,7 +43,10 @@ */ extern int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct, - struct ndpi_flow_struct *flow, int is_quic); + struct ndpi_flow_struct *flow, uint32_t quic_version); +extern int http_process_user_agent(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_flow_struct *flow, + const u_int8_t *ua_ptr, u_int16_t ua_ptr_len); /* Versions */ #define V_Q024 0x51303234 @@ -141,9 +144,13 @@ static int is_version_with_tls(uint32_t version) return is_version_quic(version) || ((version & 0xFFFFFF00) == 0x54303500) /* T05X */; } +int is_version_with_var_int_transport_params(uint32_t version) +{ + return (is_version_quic(version) && is_quic_ver_greater_than(version, 27)) || + (version == V_T051); +} - -static int quic_len(const uint8_t *buf, uint64_t *value) +int quic_len(const uint8_t *buf, uint64_t *value) { *value = buf[0]; switch((*value) >> 6) { @@ -163,6 +170,22 @@ static int quic_len(const uint8_t *buf, uint64_t *value) return 0; } } +int quic_len_buffer_still_required(uint8_t value) +{ + switch(value >> 6) { + case 0: + return 0; + case 1: + return 1; + case 2: + return 3; + case 3: + return 7; + default: /* No Possible */ + return 0; + } +} + static uint16_t gquic_get_u16(const uint8_t *buf, uint32_t version) { @@ -903,7 +926,9 @@ static const uint8_t *get_crypto_data(struct ndpi_detection_module_struct *ndpi_ if(counter + 2 + offset_len + 2 /*gquic_get_u16 reads 2 bytes */ > clear_payload_len) return NULL; if(clear_payload[counter + 1] != 0x01) { +#ifdef QUIC_DEBUG NDPI_LOG_ERR(ndpi_struct, "Unexpected stream ID version 0x%x\n", version); +#endif return NULL; } counter += 2 + offset_len; @@ -936,7 +961,9 @@ static const uint8_t *get_crypto_data(struct ndpi_detection_module_struct *ndpi_ if(first_nonzero_payload_byte != 0x06) { if(first_nonzero_payload_byte != 0x02 && first_nonzero_payload_byte != 0x1C) { +#ifdef QUIC_DEBUG NDPI_LOG_ERR(ndpi_struct, "Unexpected frame 0x%x\n", first_nonzero_payload_byte); +#endif } else { NDPI_LOG_DBG(ndpi_struct, "Unexpected ACK/CC frame\n"); } @@ -945,8 +972,10 @@ static const uint8_t *get_crypto_data(struct ndpi_detection_module_struct *ndpi_ if(counter + 2 + 8 >= clear_payload_len) /* quic_len reads 8 bytes, at most */ return NULL; if(clear_payload[counter + 1] != 0x00) { +#ifdef QUIC_DEBUG NDPI_LOG_ERR(ndpi_struct, "Unexpected crypto stream offset 0x%x\n", clear_payload[counter + 1]); +#endif return NULL; } counter += 2; @@ -955,8 +984,10 @@ static const uint8_t *get_crypto_data(struct ndpi_detection_module_struct *ndpi_ } if(*crypto_data_len + counter > clear_payload_len) { +#ifdef QUIC_DEBUG NDPI_LOG_ERR(ndpi_struct, "Invalid length %lu + %d > %d version 0x%x\n", (unsigned long)*crypto_data_len, counter, clear_payload_len, version); +#endif return NULL; } return crypto_data; @@ -1015,7 +1046,8 @@ static uint8_t *get_clear_payload(struct ndpi_detection_module_struct *ndpi_stru } static void process_tls(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, - const u_int8_t *crypto_data, uint32_t crypto_data_len) + const u_int8_t *crypto_data, uint32_t crypto_data_len, + uint32_t version) { struct ndpi_packet_struct *packet = &flow->packet; @@ -1027,7 +1059,7 @@ static void process_tls(struct ndpi_detection_module_struct *ndpi_struct, packet->payload = crypto_data; packet->payload_packet_len = crypto_data_len; - processClientServerHello(ndpi_struct, flow, 1); + processClientServerHello(ndpi_struct, flow, version); /* Restore */ packet->payload = p; @@ -1049,11 +1081,14 @@ static void process_chlo(struct ndpi_detection_module_struct *ndpi_struct, uint32_t prev_offset; uint32_t tag_offset_start, offset, len, sni_len; ndpi_protocol_match_result ret_match; + int sni_found = 0, ua_found = 0; if(crypto_data_len < 6) return; if(memcmp(crypto_data, "CHLO", 4) != 0) { +#ifdef QUIC_DEBUG NDPI_LOG_ERR(ndpi_struct, "Unexpected handshake message"); +#endif return; } num_tags = (*(uint16_t *)&crypto_data[4]); @@ -1086,7 +1121,19 @@ static void process_chlo(struct ndpi_detection_module_struct *ndpi_struct, (char *)flow->host_server_name, strlen((const char*)flow->host_server_name), &ret_match, NDPI_PROTOCOL_QUIC); - return; + sni_found = 1; + if (ua_found) + return; + } + if((memcmp(tag, "UAID", 4) == 0) && + (tag_offset_start + prev_offset + len < crypto_data_len)) { + NDPI_LOG_DBG2(ndpi_struct, "UA: [%.*s]\n", len, &crypto_data[tag_offset_start + prev_offset]); + + http_process_user_agent(ndpi_struct, flow, + &crypto_data[tag_offset_start + prev_offset], len); + ua_found = 1; + if (sni_found) + return; } prev_offset = offset; @@ -1137,13 +1184,16 @@ static int may_be_initial_pkt(struct ndpi_detection_module_struct *ndpi_struct, if(is_gquic_ver_less_than(*version, 43) && (!pub_bit5 || pub_bit3 != 0 || pub_bit4 != 0)) { - NDPI_LOG_ERR(ndpi_struct, "Version 0x%x invalid flags 0x%x\n", - *version, first_byte); +#ifdef QUIC_DEBUG + NDPI_LOG_ERR(ndpi_struct, "Version 0x%x invalid flags 0x%x\n", *version, first_byte); +#endif return 0; } if((*version == V_Q046) && (pub_bit7 != 1 || pub_bit8 != 1)) { +#ifdef QUIC_DEBUG NDPI_LOG_ERR(ndpi_struct, "Q46 invalid flag 0x%x\n", first_byte); +#endif return 0; } if((is_version_quic(*version) || (*version == V_Q046) || (*version == V_Q050)) && @@ -1201,8 +1251,10 @@ void ndpi_search_quic(struct ndpi_detection_module_struct *ndpi_struct, */ if(!is_version_supported(version)) { - NDPI_LOG_ERR(ndpi_struct, "Unsupported version 0x%x\n", version) - NDPI_EXCLUDE_PROTO(ndpi_struct, flow); +#ifdef QUIC_DEBUG + NDPI_LOG_ERR(ndpi_struct, "Unsupported version 0x%x\n", version); +#endif + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); return; } @@ -1235,7 +1287,7 @@ void ndpi_search_quic(struct ndpi_detection_module_struct *ndpi_struct, if(!is_version_with_tls(version)) { process_chlo(ndpi_struct, flow, crypto_data, crypto_data_len); } else { - process_tls(ndpi_struct, flow, crypto_data, crypto_data_len); + process_tls(ndpi_struct, flow, crypto_data, crypto_data_len, version); } if(is_version_with_encrypted_header(version)) { ndpi_free(clear_payload); |