diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/ndpi_main.h | 7 | ||||
-rw-r--r-- | src/include/ndpi_protocol_ids.h | 6 | ||||
-rw-r--r-- | src/include/ndpi_typedefs.h | 6 | ||||
-rw-r--r-- | src/lib/ndpi_content_match.c.inc | 3 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 78 | ||||
-rw-r--r-- | src/lib/ndpi_utils.c | 1 | ||||
-rw-r--r-- | src/lib/protocols/line.c | 32 | ||||
-rw-r--r-- | src/lib/protocols/stun.c | 172 | ||||
-rw-r--r-- | src/lib/protocols/tls.c | 63 |
9 files changed, 177 insertions, 191 deletions
diff --git a/src/include/ndpi_main.h b/src/include/ndpi_main.h index 5ec98f6d9..bcec38d17 100644 --- a/src/include/ndpi_main.h +++ b/src/include/ndpi_main.h @@ -112,10 +112,9 @@ extern "C" { extern void ndpi_packet_src_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_addr_t * ip); extern void ndpi_packet_dst_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_addr_t * ip); - extern char *ndpi_get_ip_string(struct ndpi_detection_module_struct *ndpi_struct, - const ndpi_ip_addr_t * ip); - extern char *ndpi_get_packet_src_ip_string(struct ndpi_detection_module_struct *ndpi_struct, - const struct ndpi_packet_struct *packet); + extern int ndpi_parse_ip_string(const char *ip_str, ndpi_ip_addr_t *parsed_ip); + extern char *ndpi_get_ip_string(const ndpi_ip_addr_t * ip, char *buf, u_int buf_len); + extern char* ndpi_get_proto_by_id(struct ndpi_detection_module_struct *ndpi_mod, u_int id); u_int16_t ndpi_get_proto_by_name(struct ndpi_detection_module_struct *ndpi_mod, const char *name); diff --git a/src/include/ndpi_protocol_ids.h b/src/include/ndpi_protocol_ids.h index ceb3cf2c9..b1be9fd69 100644 --- a/src/include/ndpi_protocol_ids.h +++ b/src/include/ndpi_protocol_ids.h @@ -79,7 +79,7 @@ typedef enum { NDPI_PROTOCOL_MINING = 42, /* Bitcoin, Ethereum, ZCash, Monero */ NDPI_PROTOCOL_NEST_LOG_SINK = 43, /* Nest Log Sink (Nest Protect) - Darryl Sokoloski <darryl@egloo.ca> */ NDPI_PROTOCOL_MODBUS = 44, /* Modbus */ - NDPI_PROTOCOL_WHATSAPP_VIDEO = 45, + NDPI_PROTOCOL_WHATSAPP_CALL = 45, /* WhatsApp video ad audio calls go here */ NDPI_PROTOCOL_DATASAVER = 46, /* Protocols used to save data on Internet communications */ NDPI_PROTOCOL_XBOX = 47, NDPI_PROTOCOL_QQ = 48, @@ -98,7 +98,7 @@ typedef enum { NDPI_PROTOCOL_QQLIVE = 61, NDPI_PROTOCOL_THUNDER = 62, NDPI_PROTOCOL_SOULSEEK = 63, - NDPI_FREE_64 = 64, + NDPI_PROTOCOL_FREE_64 = 64, NDPI_PROTOCOL_IRC = 65, NDPI_PROTOCOL_AYIYA = 66, NDPI_PROTOCOL_UNENCRYPTED_JABBER = 67, @@ -223,7 +223,7 @@ typedef enum { NDPI_PROTOCOL_VEVO = 186, NDPI_PROTOCOL_PANDORA = 187, NDPI_PROTOCOL_QUIC = 188, /* Andrea Buscarinu <andrea.buscarinu@gmail.com> - Michele Campus <michelecampus5@gmail.com> */ - NDPI_PROTOCOL_WHATSAPP_VOICE = 189, + NDPI_PROTOCOL_FREE_189 = 189, NDPI_PROTOCOL_EAQ = 190, NDPI_PROTOCOL_OOKLA = 191, NDPI_PROTOCOL_AMQP = 192, diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 4d322e5e1..35c7911b3 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -1078,10 +1078,6 @@ struct ndpi_detection_module_struct { u_int32_t zattoo_connection_timeout; u_int32_t jabber_stun_timeout; u_int32_t jabber_file_transfer_timeout; -#ifdef NDPI_ENABLE_DEBUG_MESSAGES -#define NDPI_IP_STRING_SIZE 40 - char ip_string[NDPI_IP_STRING_SIZE]; -#endif u_int8_t ip_version_limit; /* NDPI_PROTOCOL_BITTORRENT */ struct hash_ip4p_table *bt_ht; @@ -1200,7 +1196,7 @@ struct ndpi_flow_struct { } ssl; struct { - u_int8_t num_udp_pkts, num_processed_pkts, num_binding_requests, is_skype; + u_int8_t num_udp_pkts, num_processed_pkts, num_binding_requests; } stun; /* We can have STUN over SSL/TLS thus they need to live together */ diff --git a/src/lib/ndpi_content_match.c.inc b/src/lib/ndpi_content_match.c.inc index 81eebed72..67d2f5434 100644 --- a/src/lib/ndpi_content_match.c.inc +++ b/src/lib/ndpi_content_match.c.inc @@ -8217,6 +8217,9 @@ static ndpi_network host_protocol_list[] = { { 0xD040C900 /* 208.64.201.0/22 */, 22, NDPI_PROTOCOL_STEAM }, { 0xD04EA400 /* 208.78.164.0/22 */, 22, NDPI_PROTOCOL_STEAM }, + /* Line */ + { 0x7DD1FC00 /* 125.209.252.0/24 */, 24, NDPI_PROTOCOL_LINE }, + { 0x0, 0, 0 } }; diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index eee4dbb93..8bd7367f6 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -1006,9 +1006,9 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp no_master, "Modbus", NDPI_PROTOCOL_CATEGORY_NETWORK, /* Perhaps IoT in the future */ ndpi_build_default_ports(ports_a, 502, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); - ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHATSAPP_VIDEO, + ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHATSAPP_CALL, 0 /* can_have_a_subprotocol */, no_master, - no_master, "WhatsAppVideo", NDPI_PROTOCOL_CATEGORY_VOIP, + no_master, "WhatsAppCall", NDPI_PROTOCOL_CATEGORY_VOIP, ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DATASAVER, @@ -1122,7 +1122,7 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); - ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_FREE_64, + ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_FREE_64, 0 /* can_have_a_subprotocol */, no_master, no_master, "Free64", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT, ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, @@ -1249,9 +1249,9 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp no_master, "PcAnywhere", NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS, ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); - ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHATSAPP_VOICE, + ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_FREE_189, 0 /* can_have_a_subprotocol */, no_master, - no_master, "WhatsAppVoice", NDPI_PROTOCOL_CATEGORY_VOIP, + no_master, "Free189", NDPI_PROTOCOL_CATEGORY_VOIP, ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHATSAPP_FILES, @@ -4055,7 +4055,7 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st goto check_stun_export; else if((flow->guessed_protocol_id == NDPI_PROTOCOL_HANGOUT_DUO) || (flow->guessed_protocol_id == NDPI_PROTOCOL_MESSENGER) - || (flow->guessed_protocol_id == NDPI_PROTOCOL_WHATSAPP_VOICE)) + || (flow->guessed_protocol_id == NDPI_PROTOCOL_WHATSAPP_CALL)) ndpi_set_detected_protocol(ndpi_struct, flow, flow->guessed_protocol_id, NDPI_PROTOCOL_UNKNOWN); else if((flow->l4.tcp.tls_seen_client_cert == 1) && (flow->protos.stun_ssl.ssl.client_certificate[0] != '\0')) { @@ -4131,13 +4131,9 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st check_stun_export: if(flow->protos.stun_ssl.stun.num_processed_pkts || flow->protos.stun_ssl.stun.num_udp_pkts) { // if(/* (flow->protos.stun_ssl.stun.num_processed_pkts >= NDPI_MIN_NUM_STUN_DETECTION) */ - if(flow->protos.stun_ssl.stun.num_processed_pkts && flow->protos.stun_ssl.stun.is_skype) { - ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE_CALL, NDPI_PROTOCOL_SKYPE); - } else { - ndpi_set_detected_protocol(ndpi_struct, flow, - flow->guessed_host_protocol_id, - NDPI_PROTOCOL_STUN); - } + ndpi_set_detected_protocol(ndpi_struct, flow, + flow->guessed_host_protocol_id, + NDPI_PROTOCOL_STUN); } } @@ -5517,58 +5513,46 @@ void ndpi_packet_dst_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_add /* ********************************************************************************* */ -#ifdef NDPI_ENABLE_DEBUG_MESSAGES -/* get the string representation of ip - * returns a pointer to a static string - * only valid until the next call of this function */ -char *ndpi_get_ip_string(struct ndpi_detection_module_struct *ndpi_struct, - const ndpi_ip_addr_t * ip) -{ +char *ndpi_get_ip_string(const ndpi_ip_addr_t * ip, char *buf, u_int buf_len) { const u_int8_t *a = (const u_int8_t *) &ip->ipv4; #ifdef NDPI_DETECTION_SUPPORT_IPV6 - if(ip->ipv6.u6_addr.u6_addr32[0] != 0 || - ip->ipv6.u6_addr.u6_addr32[1] != 0 || + if(ip->ipv6.u6_addr.u6_addr32[1] != 0 || ip->ipv6.u6_addr.u6_addr32[2] != 0 || ip->ipv6.u6_addr.u6_addr32[3] != 0) { - const u_int16_t *b = ip->ipv6.u6_addr.u6_addr16; - snprintf(ndpi_struct->ip_string, 32, "%x:%x:%x:%x:%x:%x:%x:%x", - ntohs(b[0]), ntohs(b[1]), ntohs(b[2]), ntohs(b[3]), - ntohs(b[4]), ntohs(b[5]), ntohs(b[6]), ntohs(b[7])); + if(inet_ntop(AF_INET6, &ip->ipv6.u6_addr, buf, buf_len) == NULL) + buf[0] = '\0'; - return ndpi_struct->ip_string; + return buf; } #endif - snprintf(ndpi_struct->ip_string, 32, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]); + snprintf(buf, buf_len, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]); - return ndpi_struct->ip_string; + return buf; } -/* ********************************************************************************* */ +/* ****************************************************** */ -/* get the string representation of the source ip address from packet */ -char *ndpi_get_packet_src_ip_string(struct ndpi_detection_module_struct *ndpi_struct, - const struct ndpi_packet_struct *packet) -{ - ndpi_ip_addr_t ip; - ndpi_packet_src_ip_get(packet, &ip); - return ndpi_get_ip_string(ndpi_struct, &ip); -} +/* Returns -1 on failutre, otherwise fills parsed_ip and returns the IP version */ +int ndpi_parse_ip_string(const char *ip_str, ndpi_ip_addr_t *parsed_ip) { + int rv = -1; + memset(parsed_ip, 0, sizeof(*parsed_ip)); -/* ********************************************************************************* */ + if(strchr(ip_str, '.')) { + if(inet_pton(AF_INET, ip_str, &parsed_ip->ipv4) > 0) + rv = 4; +#ifdef NDPI_DETECTION_SUPPORT_IPV6 + } else { + if(inet_pton(AF_INET6, ip_str, &parsed_ip->ipv6) > 0) + rv = 6; +#endif + } -/* get the string representation of the destination ip address from packet */ -char *ndpi_get_packet_dst_ip_string(struct ndpi_detection_module_struct *ndpi_struct, - const struct ndpi_packet_struct *packet) -{ - ndpi_ip_addr_t ip; - ndpi_packet_dst_ip_get(packet, &ip); - return ndpi_get_ip_string(ndpi_struct, &ip); + return(rv); } -#endif /* NDPI_ENABLE_DEBUG_MESSAGES */ /* ****************************************************** */ diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c index c3e0bb542..b8ffe2e17 100644 --- a/src/lib/ndpi_utils.c +++ b/src/lib/ndpi_utils.c @@ -719,6 +719,7 @@ char* ndpi_ssl_version2str(u_int16_t version) { case 0x0302: return("TLSv1.1"); case 0x0303: return("TLSv1.2"); case 0x0304: return("TLSv1.3"); + case 0xfb1a: return("TLSv1.3 (Fizz)"); /* https://engineering.fb.com/security/fizz/ */ case 0xfeff: return("DTLSv1.0"); case 0xfefd: return("DTLSv1.2"); } diff --git a/src/lib/protocols/line.c b/src/lib/protocols/line.c index 0e624ab7d..b6e676c55 100644 --- a/src/lib/protocols/line.c +++ b/src/lib/protocols/line.c @@ -36,31 +36,35 @@ void ndpi_search_line(struct ndpi_detection_module_struct *ndpi_struct, struct n NDPI_LOG_DBG(ndpi_struct, "search line\n"); - if(packet->iph) { + if (packet->iph) { /* 125.209.252.xxx */ - if(((ntohl(packet->iph->saddr) & 0xFFFFFF00 /* 255.255.255.0 */) == 0x7DD1FC00) - || ((ntohl(packet->iph->daddr) & 0xFFFFFF00 /* 255.255.255.0 */) == 0x7DD1FC00)) { - if((packet->payload_packet_len == 110) - && (flow->packet.payload[0] == 0xB6) && (flow->packet.payload[1] == 0x18) - && (flow->packet.payload[2] == 0x00) && (flow->packet.payload[3] == 0x6A)) { - ndpi_line_report_protocol(ndpi_struct, flow); - return; + if (((ntohl(packet->iph->saddr) & 0xFFFFFF00 /* 255.255.255.0 */) == 0x7DD1FC00) || + ((ntohl(packet->iph->daddr) & 0xFFFFFF00 /* 255.255.255.0 */) == 0x7DD1FC00)) { + if ((packet->payload_packet_len == 110) && (flow->packet.payload[0] == 0xB6) && + (flow->packet.payload[1] == 0x18) && (flow->packet.payload[2] == 0x00) && + (flow->packet.payload[3] == 0x6A)) { + ndpi_line_report_protocol(ndpi_struct, flow); + return; } } } + if ((packet->payload_packet_len == 46 && ntohl(get_u_int32_t(packet->payload, 0)) == 0xb6130006) || + (packet->payload_packet_len == 8 && ntohl(get_u_int32_t(packet->payload, 0)) == 0xb6070004) || + (packet->payload_packet_len == 16 && ntohl(get_u_int32_t(packet->payload, 0)) == 0xb609000c)) { + ndpi_line_report_protocol(ndpi_struct, flow); + return; + } + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); } void init_line_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask) { - ndpi_set_bitmask_protocol_detection("Line", ndpi_struct, detection_bitmask, *id, - NDPI_PROTOCOL_LINE, - ndpi_search_line, - NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD, - SAVE_DETECTION_BITMASK_AS_UNKNOWN, - ADD_TO_DETECTION_BITMASK); + ndpi_set_bitmask_protocol_detection("Line", ndpi_struct, detection_bitmask, *id, NDPI_PROTOCOL_LINE, + ndpi_search_line, NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD, + SAVE_DETECTION_BITMASK_AS_UNKNOWN, ADD_TO_DETECTION_BITMASK); *id += 1; } diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c index 76a75fb8d..77ddf6ca0 100644 --- a/src/lib/protocols/stun.c +++ b/src/lib/protocols/stun.c @@ -41,6 +41,23 @@ struct stun_packet_header { /* ************************************************************ */ +static u_int8_t is_stun_based_proto(u_int16_t proto) { + + switch(proto) { + case NDPI_PROTOCOL_WHATSAPP_CALL: + case NDPI_PROTOCOL_MESSENGER: + case NDPI_PROTOCOL_HANGOUT_DUO: + case NDPI_PROTOCOL_SKYPE_CALL: + case NDPI_PROTOCOL_SIGNAL: + case NDPI_PROTOCOL_STUN: + return(1); + } + + return(0); +} + +/* ************************************************************ */ + u_int32_t get_stun_lru_key(struct ndpi_flow_struct *flow, u_int8_t rev) { if(rev) return(flow->packet.iph->daddr + flow->packet.udp->dest); @@ -52,7 +69,7 @@ u_int32_t get_stun_lru_key(struct ndpi_flow_struct *flow, u_int8_t rev) { void ndpi_int_stun_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, - u_int app_proto, u_int proto) { + u_int proto, u_int app_proto) { if(ndpi_struct->stun_cache == NULL) ndpi_struct->stun_cache = ndpi_lru_cache_init(1024); @@ -71,24 +88,25 @@ void ndpi_int_stun_add_connection(struct ndpi_detection_module_struct *ndpi_stru #endif app_proto = cached_proto, proto = NDPI_PROTOCOL_STUN; } else { - u_int32_t key1 = get_stun_lru_key(flow, 1); + u_int32_t key_rev = get_stun_lru_key(flow, 1); - if(ndpi_lru_find_cache(ndpi_struct->stun_cache, key1, + if(ndpi_lru_find_cache(ndpi_struct->stun_cache, key_rev, &cached_proto, 0 /* Don't remove it as it can be used for other connections */)) { #ifdef DEBUG_LRU - printf("[LRU] FOUND %u / %u: no need to cache %u.%u\n", key1, cached_proto, proto, app_proto); + printf("[LRU] FOUND %u / %u: no need to cache %u.%u\n", key_rev, cached_proto, proto, app_proto); #endif app_proto = cached_proto, proto = NDPI_PROTOCOL_STUN; } else { if(app_proto != NDPI_PROTOCOL_STUN) { /* No sense to ass STUN, but only subprotocols */ - + #ifdef DEBUG_LRU printf("[LRU] ADDING %u / %u.%u [%u -> %u]\n", key, proto, app_proto, ntohs(flow->packet.udp->source), ntohs(flow->packet.udp->dest)); #endif - + ndpi_lru_add_to_cache(ndpi_struct->stun_cache, key, app_proto); + ndpi_lru_add_to_cache(ndpi_struct->stun_cache, key_rev, app_proto); } } } @@ -140,11 +158,7 @@ static int is_messenger_ip_address(u_int32_t host) { static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, const u_int8_t * payload, - const u_int16_t payload_length, - u_int8_t *is_whatsapp, - u_int8_t *is_messenger, - u_int8_t *is_duo - ) { + const u_int16_t payload_length) { u_int16_t msg_type, msg_len; struct stun_packet_header *h = (struct stun_packet_header*)payload; u_int8_t can_this_be_whatsapp_voice = 1; @@ -152,15 +166,13 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * /* STUN over TCP does not look good */ if(flow->packet.tcp) return(NDPI_IS_NOT_STUN); - *is_whatsapp = 0, *is_messenger = 0, *is_duo = 0; - if(payload_length >= 512) { return(NDPI_IS_NOT_STUN); } else if(payload_length < sizeof(struct stun_packet_header)) { /* This looks like an invalid packet */ if(flow->protos.stun_ssl.stun.num_udp_pkts > 0) { - *is_whatsapp = 1; + flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL; return(NDPI_IS_STUN); /* This is WhatsApp Voice */ } else return(NDPI_IS_NOT_STUN); @@ -179,6 +191,19 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * #ifdef DEBUG_STUN printf("[STUN] msg_type = %04X\n", msg_type); #endif + + if(is_stun_based_proto(flow->guessed_host_protocol_id)) { + /* + In this case we have the detected the typical STUN pattern + of modern protocols where the flow starts as STUN and becomes + something else that has nothing to do with STUN anymore + */ + ndpi_int_stun_add_connection(ndpi_struct, flow, + flow->guessed_protocol_id, + flow->guessed_host_protocol_id); + return(NDPI_IS_STUN); + } + return(NDPI_IS_NOT_STUN); } @@ -214,21 +239,6 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * flow->guessed_host_protocol_id = proto, flow->guessed_protocol_id = NDPI_PROTOCOL_STUN; - switch(proto) { - case NDPI_PROTOCOL_WHATSAPP: - *is_whatsapp = 1; - break; - case NDPI_PROTOCOL_MESSENGER: - *is_messenger = 1; - break; - case NDPI_PROTOCOL_HANGOUT_DUO: - *is_duo = 1; - break; - case NDPI_PROTOCOL_SKYPE_CALL: - flow->protos.stun_ssl.stun.is_skype = 1; - break; - } - return(NDPI_IS_STUN); } else { #ifdef DEBUG_LRU @@ -247,10 +257,10 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * if((msg_len == 0) && (flow->guessed_host_protocol_id == NDPI_PROTOCOL_GOOGLE)) flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO; else - flow->guessed_host_protocol_id = NDPI_PROTOCOL_STUN; + flow->guessed_protocol_id = NDPI_PROTOCOL_STUN; if(msg_len == 0) { - flow->protos.stun_ssl.stun.num_udp_pkts++; + /* flow->protos.stun_ssl.stun.num_udp_pkts++; */ return(NDPI_IS_NOT_STUN); /* This to keep analyzing STUN instead of giving up */ } } @@ -270,12 +280,12 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * if(((payload[0] == 0x80) && (payload_length < 512) && ((msg_len+20) <= payload_length)) /* WhatsApp Voice */) { - *is_whatsapp = 1; + flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL; return(NDPI_IS_STUN); /* This is WhatsApp Voice */ } else if((payload[0] == 0x90) && (((msg_len+11) == payload_length) /* WhatsApp Video */ || (flow->protos.stun_ssl.stun.num_binding_requests >= 4))) { - *is_whatsapp = 2; + flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL; return(NDPI_IS_STUN); /* This is WhatsApp Video */ } @@ -285,7 +295,7 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * switch(flow->guessed_protocol_id) { case NDPI_PROTOCOL_HANGOUT_DUO: case NDPI_PROTOCOL_MESSENGER: - case NDPI_PROTOCOL_WHATSAPP_VOICE: + case NDPI_PROTOCOL_WHATSAPP_CALL: /* Don't overwrite the protocol with sub-STUN protocols */ break; @@ -323,8 +333,8 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * #endif switch(attribute) { - case 0x0008: /* Message Integrity */ - case 0x0020: /* XOR-MAPPED-ADDRESSES */ + // case 0x0008: /* Message Integrity */ + // case 0x0020: /* XOR-MAPPED-ADDRESSES */ case 0x4000: case 0x4001: case 0x4002: @@ -349,7 +359,6 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * #endif if(strstr((char*)flow->host_server_name, "google.com") != NULL) { - *is_duo = 1; flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO, flow->guessed_protocol_id = NDPI_PROTOCOL_STUN; return(NDPI_IS_STUN); } else if(strstr((char*)flow->host_server_name, "whispersystems.org") != NULL) { @@ -363,12 +372,10 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * case 0xC057: /* Messeger */ if(msg_type == 0x0001) { if((msg_len == 100) || (msg_len == 104)) { - *is_messenger = 1; + flow->guessed_host_protocol_id = NDPI_PROTOCOL_MESSENGER, flow->guessed_protocol_id = NDPI_PROTOCOL_STUN; return(NDPI_IS_STUN); } else if(msg_len == 76) { #if 0 - *is_duo = 1; - if(1) { flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO, flow->guessed_protocol_id = NDPI_PROTOCOL_STUN; return(NDPI_IS_NOT_STUN); /* This case is found also with signal traffic */ @@ -390,7 +397,6 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * printf("==> Skype found\n"); #endif flow->guessed_protocol_id = NDPI_PROTOCOL_SKYPE_CALL; - flow->protos.stun_ssl.stun.is_skype = 1; return(NDPI_IS_STUN); } break; @@ -411,7 +417,6 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * #endif flow->guessed_protocol_id = NDPI_PROTOCOL_SKYPE_CALL; - flow->protos.stun_ssl.stun.is_skype = 1; return(NDPI_IS_STUN); break; @@ -424,7 +429,6 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * && ((payload[offset+7] == 0x02) || (payload[offset+7] == 0x03)) ) { flow->guessed_protocol_id = NDPI_PROTOCOL_SKYPE_CALL; - flow->protos.stun_ssl.stun.is_skype = 1; #ifdef DEBUG_STUN printf("==> Skype (3) found\n"); #endif @@ -451,13 +455,13 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * } goto udp_stun_found; } else if(msg_type == 0x0800) { - *is_whatsapp = 1; + flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL; return(NDPI_IS_STUN); /* This is WhatsApp */ } } if((flow->protos.stun_ssl.stun.num_udp_pkts > 0) && (msg_type <= 0x00FF)) { - *is_whatsapp = 1; + flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL; return(NDPI_IS_STUN); /* This is WhatsApp Voice */ } else return(NDPI_IS_NOT_STUN); @@ -466,23 +470,25 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * if(can_this_be_whatsapp_voice) { struct ndpi_packet_struct *packet = &flow->packet; int rc; - + flow->protos.stun_ssl.stun.num_processed_pkts++; #ifdef DEBUG_STUN - printf("==>> NDPI_PROTOCOL_WHATSAPP_VOICE\n"); + printf("==>> NDPI_PROTOCOL_WHATSAPP_CALL\n"); #endif if((ntohs(packet->udp->source) == 3478) || (ntohs(packet->udp->dest) == 3478)) { flow->guessed_host_protocol_id = (is_messenger_ip_address(ntohl(packet->iph->saddr)) || is_messenger_ip_address(ntohl(packet->iph->daddr))) ? - NDPI_PROTOCOL_MESSENGER : NDPI_PROTOCOL_WHATSAPP_VOICE; + NDPI_PROTOCOL_MESSENGER : NDPI_PROTOCOL_WHATSAPP_CALL; } else flow->guessed_host_protocol_id = (is_google_ip_address(ntohl(packet->iph->saddr)) || is_google_ip_address(ntohl(packet->iph->daddr))) - ? NDPI_PROTOCOL_HANGOUT_DUO : NDPI_PROTOCOL_WHATSAPP_VOICE; + ? NDPI_PROTOCOL_HANGOUT_DUO : NDPI_PROTOCOL_WHATSAPP_CALL; rc = (flow->protos.stun_ssl.stun.num_udp_pkts < MAX_NUM_STUN_PKTS) ? NDPI_IS_NOT_STUN : NDPI_IS_STUN; if(rc == NDPI_IS_STUN) - ndpi_int_stun_add_connection(ndpi_struct, flow, flow->guessed_host_protocol_id, NDPI_IS_STUN); + ndpi_int_stun_add_connection(ndpi_struct, flow, + NDPI_IS_STUN, + flow->guessed_host_protocol_id); return(rc); } else { @@ -498,7 +504,6 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * void ndpi_search_stun(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; - u_int8_t is_whatsapp = 0, is_messenger = 0, is_duo = 0; NDPI_LOG_DBG(ndpi_struct, "search stun\n"); @@ -517,64 +522,27 @@ void ndpi_search_stun(struct ndpi_detection_module_struct *ndpi_struct, struct n * improved by checking only the STUN packet of given length */ if(ndpi_int_check_stun(ndpi_struct, flow, packet->payload + 2, - packet->payload_packet_len - 2, - &is_whatsapp, &is_messenger, &is_duo) == NDPI_IS_STUN) { - if(flow->guessed_protocol_id == NDPI_PROTOCOL_UNKNOWN) flow->guessed_protocol_id = NDPI_PROTOCOL_STUN; - - if(is_messenger) { - ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MESSENGER, NDPI_PROTOCOL_STUN); - return; - } else if(is_duo) { - ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HANGOUT_DUO, NDPI_PROTOCOL_STUN); - return; - } else if(flow->guessed_host_protocol_id == NDPI_PROTOCOL_SIGNAL) { - ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SIGNAL, NDPI_PROTOCOL_STUN); - return; - } else if(flow->protos.stun_ssl.stun.is_skype || (flow->guessed_host_protocol_id = NDPI_PROTOCOL_SKYPE_CALL)) { - NDPI_LOG_INFO(ndpi_struct, "found Skype\n"); - - // if((flow->protos.stun_ssl.stun.num_processed_pkts >= 8) || (flow->protos.stun_ssl.stun.num_binding_requests >= 4)) - ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE_CALL, NDPI_PROTOCOL_SKYPE); - } else { - NDPI_LOG_INFO(ndpi_struct, "found UDP stun\n"); /* Ummmmm we're in the TCP branch. This code looks bad */ - ndpi_int_stun_add_connection(ndpi_struct, flow, - is_whatsapp ? (is_whatsapp == 1 ? NDPI_PROTOCOL_WHATSAPP_VOICE : NDPI_PROTOCOL_WHATSAPP_VIDEO) : NDPI_PROTOCOL_STUN, - NDPI_PROTOCOL_UNKNOWN); - } - - return; + packet->payload_packet_len - 2) == NDPI_IS_STUN) { + goto udp_stun_match; } } } /* UDP */ if(ndpi_int_check_stun(ndpi_struct, flow, packet->payload, - packet->payload_packet_len, - &is_whatsapp, &is_messenger, &is_duo) == NDPI_IS_STUN) { - if(flow->guessed_protocol_id == NDPI_PROTOCOL_UNKNOWN) flow->guessed_protocol_id = NDPI_PROTOCOL_STUN; - - if(is_messenger) { - ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MESSENGER, NDPI_PROTOCOL_STUN); - return; - } else if(is_duo) { - ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HANGOUT_DUO, NDPI_PROTOCOL_STUN); - return; - } else if(flow->guessed_host_protocol_id == NDPI_PROTOCOL_SIGNAL) { - ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SIGNAL, NDPI_PROTOCOL_STUN); - return; - } else if(flow->protos.stun_ssl.stun.is_skype) { - NDPI_LOG_INFO(ndpi_struct, "Found Skype\n"); - - /* flow->protos.stun_ssl.stun.num_binding_requests < 4) ? NDPI_PROTOCOL_SKYPE_CALL_IN : NDPI_PROTOCOL_SKYPE_CALL_OUT */ - // if((flow->protos.stun_ssl.stun.num_udp_pkts >= 6) || (flow->protos.stun_ssl.stun.num_binding_requests >= 3)) - ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE_CALL, NDPI_PROTOCOL_SKYPE); - } else { - NDPI_LOG_INFO(ndpi_struct, "found UDP stun\n"); - ndpi_int_stun_add_connection(ndpi_struct, flow, - is_whatsapp ? (is_whatsapp == 1 ? NDPI_PROTOCOL_WHATSAPP_VOICE : NDPI_PROTOCOL_WHATSAPP_VIDEO) - : NDPI_PROTOCOL_STUN, NDPI_PROTOCOL_UNKNOWN); - } + packet->payload_packet_len) == NDPI_IS_STUN) { + udp_stun_match: + if(flow->guessed_protocol_id == NDPI_PROTOCOL_UNKNOWN) + flow->guessed_protocol_id = NDPI_PROTOCOL_STUN; + if(flow->guessed_host_protocol_id == NDPI_PROTOCOL_UNKNOWN) { + flow->guessed_host_protocol_id = flow->guessed_protocol_id; + flow->guessed_protocol_id = NDPI_PROTOCOL_STUN; + } + + ndpi_int_stun_add_connection(ndpi_struct, flow, + flow->guessed_protocol_id, + flow->guessed_host_protocol_id); return; } diff --git a/src/lib/protocols/tls.c b/src/lib/protocols/tls.c index 8a4d0c3ac..f63da2067 100644 --- a/src/lib/protocols/tls.c +++ b/src/lib/protocols/tls.c @@ -31,7 +31,7 @@ extern char *strptime(const char *s, const char *format, struct tm *tm); -// #define DEBUG_TLS 1 +/* #define DEBUG_TLS 1 */ #define DEBUG_FINGERPRINT 1 @@ -176,7 +176,7 @@ static void stripCertificateTrailer(char *buffer, int buffer_len) { #define MAX_NUM_JA3 128 struct ja3_info { - u_int16_t tls_version; + u_int16_t tls_handshake_version; u_int16_t num_cipher, cipher[MAX_NUM_JA3]; u_int16_t num_tls_extension, tls_extension[MAX_NUM_JA3]; u_int16_t num_elliptic_curve, elliptic_curve[MAX_NUM_JA3]; @@ -263,7 +263,7 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct, else tls_version = ntohs(*((u_int16_t*)&packet->payload[header_len+12])); - ja3.tls_version = tls_version; + ja3.tls_handshake_version = tls_version; if(handshake_protocol == 0x02) { u_int16_t offset = base_offset, extension_len, j; @@ -291,36 +291,49 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct, flow->protos.stun_ssl.ssl.server_cipher = ja3.cipher[0]; #ifdef DEBUG_TLS - printf("SSL [server][session_id_len: %u][cipher: %04X]\n", session_id_len, ja3.cipher[0]); + printf("TLS [server][session_id_len: %u][cipher: %04X]\n", session_id_len, ja3.cipher[0]); #endif offset += 2 + 1; extension_len = ntohs(*((u_int16_t*)&packet->payload[offset])); #ifdef DEBUG_TLS - printf("SSL [server][extension_len: %u]\n", extension_len); + printf("TLS [server][extension_len: %u]\n", extension_len); #endif offset += 2; for(i=0; i<extension_len; ) { - u_int16_t id, len; + u_int16_t extension_id, extension_len; if(offset >= (packet->payload_packet_len+4)) break; - id = ntohs(*((u_int16_t*)&packet->payload[offset])); - len = ntohs(*((u_int16_t*)&packet->payload[offset+2])); + extension_id = ntohs(*((u_int16_t*)&packet->payload[offset])); + extension_len = ntohs(*((u_int16_t*)&packet->payload[offset+2])); if(ja3.num_tls_extension < MAX_NUM_JA3) - ja3.tls_extension[ja3.num_tls_extension++] = id; + ja3.tls_extension[ja3.num_tls_extension++] = extension_id; #ifdef DEBUG_TLS - printf("SSL [server][extension_id: %u/0x%04X]\n", id, id); + printf("TLS [server][extension_id: %u/0x%04X][len: %u]\n", + extension_id, extension_id, extension_len); #endif - i += 4 + len, offset += 4 + len; + if(extension_id == 43 /* supported versions */) { + if(extension_len >= 2) { + u_int16_t tls_version = ntohs(*((u_int16_t*)&packet->payload[offset+4])); + +#ifdef DEBUG_TLS + printf("TLS [server] [TLS version: 0x%04X]\n", tls_version); +#endif + + flow->protos.stun_ssl.ssl.ssl_version = tls_version; + } + } + + i += 4 + extension_len, offset += 4 + extension_len; } - ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.tls_version); + ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.tls_handshake_version); for(i=0; i<ja3.num_cipher; i++) ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", (i > 0) ? "-" : "", ja3.cipher[i]); @@ -333,7 +346,7 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct, ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", (i > 0) ? "-" : "", ja3.tls_extension[i]); #ifdef DEBUG_TLS - printf("SSL [server] %s\n", ja3_str); + printf("TLS [server] %s\n", ja3_str); #endif #ifdef DEBUG_TLS @@ -426,7 +439,7 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct, session_id_len = packet->payload[base_offset]; - ja3.tls_version = tls_version; + ja3.tls_handshake_version = tls_version; if((session_id_len+base_offset+2) <= total_len) { u_int16_t cipher_len, cipher_offset; @@ -533,7 +546,7 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct, #endif } } - + if(extension_id == 0 /* server name */) { u_int16_t len; @@ -611,6 +624,20 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct, printf("Client SSL Invalid len %u vs %u\n", s_offset+extension_len, total_len); #endif } + } else if(extension_id == 43 /* supported versions */) { + u_int8_t version_len = packet->payload[offset+4]; + + if(version_len == (extension_len-1)) { +#ifdef DEBUG_TLS + u_int8_t j; + + for(j=0; j<version_len; j += 2) { + u_int16_t tls_version = ntohs(*((u_int16_t*)&packet->payload[offset+5+j])); + + printf("Client SSL [TLS version: 0x%04X]\n", tls_version); + } +#endif + } } extension_offset += extension_len; @@ -621,7 +648,8 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct, } /* while */ if(!invalid_ja3) { - ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.tls_version); + compute_ja3c: + ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.tls_handshake_version); for(i=0; i<ja3.num_cipher; i++) { ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", @@ -670,6 +698,9 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct, return(2 /* Client Certificate */); } + } else if(offset == total_len) { + /* SSL does not have extensions etc */ + goto compute_ja3c; } } } |