diff options
Diffstat (limited to 'src/lib/ndpi_main.c')
-rw-r--r-- | src/lib/ndpi_main.c | 179 |
1 files changed, 136 insertions, 43 deletions
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index ca557ea31..fed3c9831 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -1626,7 +1626,7 @@ u_int16_t ndpi_network_port_ptree_match(struct ndpi_detection_module_struct *ndp || (node->value.uv.additional_user_value == port)) return(node->value.uv.user_value); } - + return(NDPI_PROTOCOL_UNKNOWN); } @@ -2198,10 +2198,10 @@ int ndpi_match_custom_category(struct ndpi_detection_module_struct *ndpi_str, char *name, u_int name_len, ndpi_protocol_category_t *category) { ndpi_protocol_breed_t breed; - u_int16_t id; + u_int16_t id; int rc = ndpi_match_string_protocol_id(ndpi_str->custom_categories.hostnames.ac_automa, name, name_len, &id, category, &breed); - + return(rc); } @@ -2277,6 +2277,9 @@ void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_str) { if(ndpi_str->stun_cache) ndpi_lru_free_cache(ndpi_str->stun_cache); + if(ndpi_str->msteams_cache) + ndpi_lru_free_cache(ndpi_str->msteams_cache); + if(ndpi_str->protocols_ptree) ndpi_Destroy_Patricia((patricia_tree_t *) ndpi_str->protocols_ptree, free_ptree_data); @@ -2315,7 +2318,7 @@ void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_str) { #ifdef CUSTOM_NDPI_PROTOCOLS #include "../../../nDPI-custom/ndpi_exit_detection_module.c" #endif - + ndpi_free(ndpi_str); } } @@ -3491,12 +3494,17 @@ static u_int8_t ndpi_detection_get_l4_internal(struct ndpi_detection_module_stru return(0); } +/* ************************************************ */ + void ndpi_apply_flow_protocol_to_packet(struct ndpi_flow_struct *flow, struct ndpi_packet_struct *packet) { memcpy(&packet->detected_protocol_stack, &flow->detected_protocol_stack, sizeof(packet->detected_protocol_stack)); memcpy(&packet->protocol_stack_info, &flow->protocol_stack_info, sizeof(packet->protocol_stack_info)); } -static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, +/* ************************************************ */ + +static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, unsigned short packetlen) { const struct ndpi_iphdr *decaps_iph = NULL; u_int16_t l3len; @@ -3634,7 +3642,10 @@ static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str return(0); } -void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow) { +/* ************************************************ */ + +void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow) { if(!flow) { return; } else { @@ -3756,10 +3767,12 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, str } } +/* ************************************************ */ + void check_ndpi_other_flow_func(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) { if(!flow) - return; + return; void *func = NULL; u_int32_t a; @@ -3797,6 +3810,8 @@ void check_ndpi_other_flow_func(struct ndpi_detection_module_struct *ndpi_str, s } } +/* ************************************************ */ + void check_ndpi_udp_flow_func(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) { void *func = NULL; @@ -3838,7 +3853,10 @@ void check_ndpi_udp_flow_func(struct ndpi_detection_module_struct *ndpi_str, str } } -void check_ndpi_tcp_flow_func(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, +/* ************************************************ */ + +void check_ndpi_tcp_flow_func(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) { void *func = NULL; u_int32_t a; @@ -3931,16 +3949,16 @@ u_int16_t ndpi_guess_host_protocol_id(struct ndpi_detection_module_struct *ndpi_ if(flow->packet.iph) { struct in_addr addr; u_int16_t sport, dport; - + addr.s_addr = flow->packet.iph->saddr; - + if((flow->l4_proto == IPPROTO_TCP) && flow->packet.tcp) sport = flow->packet.tcp->source, dport = flow->packet.tcp->dest; else if((flow->l4_proto == IPPROTO_UDP) && flow->packet.udp) sport = flow->packet.udp->source, dport = flow->packet.udp->dest; else sport = dport = 0; - + /* guess host protocol */ ret = ndpi_network_port_ptree_match(ndpi_str, &addr, sport); @@ -4342,11 +4360,79 @@ static void ndpi_reset_packet_line_info(struct ndpi_packet_struct *packet) { /* ********************************************************************************* */ -#if 0 -static u_int16_t ndpi_checK_flow_port(, u_int16_t sport, u_int16_t dport) { +static int ndpi_check_protocol_port_mismatch_exceptions(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, + ndpi_default_ports_tree_node_t *expected_proto, + ndpi_protocol *returned_proto) { + /* + For TLS (and other protocols) it is not simple to guess the exact protocol so before + triggering an alert we need to make sure what we have exhausted all the possible + options available + */ + if(returned_proto->master_protocol == NDPI_PROTOCOL_TLS) { + switch(expected_proto->proto->protoId) { + case NDPI_PROTOCOL_MAIL_IMAPS: + case NDPI_PROTOCOL_MAIL_POPS: + case NDPI_PROTOCOL_MAIL_SMTPS: + return(1); /* This is a reasonable exception */ + break; + } + } + + return(0); +} + +/* ********************************************************************************* */ + +static void ndpi_reconcile_protocols(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, + ndpi_protocol *ret) { + /* + Skype for a host doing MS Teams means MS Teams + (MS Teams uses Skype as transport protocol for voice/video) + */ + + switch(ret->app_protocol) { + case NDPI_PROTOCOL_MSTEAMS: + if(flow->packet.iph && flow->packet.tcp) { + // printf("====>> NDPI_PROTOCOL_MSTEAMS\n"); + + if(ndpi_str->msteams_cache == NULL) + ndpi_str->msteams_cache = ndpi_lru_cache_init(1024); + + if(ndpi_str->msteams_cache) + ndpi_lru_add_to_cache(ndpi_str->msteams_cache, + flow->packet.iph->saddr, + flow->packet.tick_timestamp & 0xFFFF /* 16 bit */); + } + break; + + case NDPI_PROTOCOL_SKYPE: + case NDPI_PROTOCOL_SKYPE_CALL: + if(flow->packet.iph + && flow->packet.udp + && ndpi_str->msteams_cache) { + u_int16_t when; + + if(ndpi_lru_find_cache(ndpi_str->msteams_cache, flow->packet.iph->saddr, + &when, 0 /* Don't remove it as it can be used for other connections */)) { + u_int16_t tdiff = (flow->packet.tick_timestamp & 0xFFFF) - when; + + if(tdiff < 60 /* sec */) { + // printf("====>> NDPI_PROTOCOL_SKYPE(_CALL) -> NDPI_PROTOCOL_MSTEAMS [%u]\n", tdiff); + ret->app_protocol = NDPI_PROTOCOL_MSTEAMS; + + /* Refresh cache */ + ndpi_lru_add_to_cache(ndpi_str->msteams_cache, + flow->packet.iph->saddr, + flow->packet.tick_timestamp & 0xFFFF /* 16 bit */); + } + } + } + break; + } /* switch */ } -#endif /* ********************************************************************************* */ @@ -4586,7 +4672,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct if((!flow->risk_checked) && (ret.master_protocol != NDPI_PROTOCOL_UNKNOWN)) { ndpi_default_ports_tree_node_t *found; u_int16_t *default_ports, sport, dport; - + if(flow->packet.udp) found = ndpi_get_guessed_protocol_id(ndpi_str, IPPROTO_UDP, sport = ntohs(flow->packet.udp->source), @@ -4596,7 +4682,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct found = ndpi_get_guessed_protocol_id(ndpi_str, IPPROTO_TCP, sport = ntohs(flow->packet.tcp->source), dport = ntohs(flow->packet.tcp->dest)), - default_ports = ndpi_str->proto_defaults[ret.master_protocol].tcp_default_ports; + default_ports = ndpi_str->proto_defaults[ret.master_protocol].tcp_default_ports; else found = NULL, default_ports = NULL; @@ -4604,10 +4690,12 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct && (found->proto->protoId != NDPI_PROTOCOL_UNKNOWN) && (found->proto->protoId != ret.master_protocol)) { // printf("******** %u / %u\n", found->proto->protoId, ret.master_protocol); - NDPI_SET_BIT(flow->risk, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT); + + if(!ndpi_check_protocol_port_mismatch_exceptions(ndpi_str, flow, found, &ret)) + NDPI_SET_BIT(flow->risk, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT); } else if(default_ports && (default_ports[0] != 0)) { u_int8_t found = 0, i; - + for(i=0; (i<MAX_DEFAULT_PORTS) && (default_ports[i] != 0); i++) { if((default_ports[i] == sport) || (default_ports[i] == dport)) { found = 1; @@ -4620,10 +4708,11 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct NDPI_SET_BIT(flow->risk, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT); } } - + flow->risk_checked = 1; } - + + ndpi_reconcile_protocols(ndpi_str, flow, &ret); invalidate_ptr: /* @@ -4749,29 +4838,34 @@ u_int32_t ndpi_bytestream_to_ipv4(const u_int8_t *str, u_int16_t max_chars_to_re u_int16_t read = 0; u_int16_t oldread; u_int32_t c; + /* ip address must be X.X.X.X with each X between 0 and 255 */ oldread = read; c = ndpi_bytestream_to_number(str, max_chars_to_read, &read); if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.') return(0); + read++; val = c << 24; oldread = read; c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read); if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.') return(0); + read++; val = val + (c << 16); oldread = read; c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read); if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.') return(0); + read++; val = val + (c << 8); oldread = read; c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read); if(c > 255 || oldread == read || max_chars_to_read == read) return(0); + val = val + c; *bytes_read = *bytes_read + read; @@ -4805,14 +4899,16 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_str, if(get_u_int16_t(packet->payload, a) == ntohs(0x0d0a)) { /* If end of line char sequence CR+NL "\r\n", process line */ - if(get_u_int16_t(packet->payload, a+2) == ntohs(0x0d0a)) { + if(((a + 3) <= packet->payload_packet_len) + && (get_u_int16_t(packet->payload, a+2) == ntohs(0x0d0a))) { /* \r\n\r\n */ int diff; /* No unsigned ! */ u_int32_t a1 = a + 4; - diff = ndpi_min(packet->payload_packet_len-a1, sizeof(flow->initial_binary_bytes)); - + diff = packet->payload_packet_len - a1; + if(diff > 0) { + diff = ndpi_min(diff, sizeof(flow->initial_binary_bytes)); memcpy(&flow->initial_binary_bytes, &packet->payload[a1], diff); flow->initial_binary_bytes_len = diff; } @@ -5814,27 +5910,21 @@ char *ndpi_strnstr(const char *s, const char *find, size_t slen) { /* * Same as ndpi_strnstr but case-insensitive */ -char *ndpi_strncasestr(const char *s, const char *find, size_t slen) { - char c; - size_t len; - - if((c = *find++) != '\0') { - len = strlen(find); - do { - char sc; - - do { - if(slen-- < 1 || (sc = *s++) == '\0') - return(NULL); - } while (sc != c); - - if(len > slen) - return(NULL); - } while (strncasecmp(s, find, len) != 0); - - s--; +const char * ndpi_strncasestr(const char *str1, const char *str2, size_t len) { + size_t str1_len = strnlen(str1, len); + size_t str2_len = strlen(str2); + size_t i; + + for(i = 0; i < (str1_len - str2_len + 1); i++){ + if(str1[0] == '\0') + return NULL; + else if(strncasecmp(str1, str2, str2_len) == 0) + return(str1); + + str1++; } - return((char *) s); + + return NULL; } /* ****************************************************** */ @@ -6065,6 +6155,9 @@ void ndpi_free_flow(struct ndpi_flow_struct *flow) { if(flow->l4.tcp.tls.srv_cert_fingerprint_ctx) ndpi_free(flow->l4.tcp.tls.srv_cert_fingerprint_ctx); + + if(flow->protos.stun_ssl.ssl.encrypted_sni.esni) + ndpi_free(flow->protos.stun_ssl.ssl.encrypted_sni.esni); } if(flow->l4_proto == IPPROTO_TCP) { |