diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/ndpi_typedefs.h | 18 | ||||
-rw-r--r-- | src/lib/ndpi_content_match.c.inc | 4 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 225 | ||||
-rw-r--r-- | src/lib/protocols/dns.c | 44 | ||||
-rw-r--r-- | src/lib/protocols/ftp_data.c | 50 | ||||
-rw-r--r-- | src/lib/protocols/http.c | 22 | ||||
-rw-r--r-- | src/lib/protocols/whatsapp.c | 34 |
7 files changed, 216 insertions, 181 deletions
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 39995d662..298306657 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -356,15 +356,15 @@ PACK_ON struct tinc_cache_entry { } PACK_OFF; typedef enum { - HTTP_METHOD_UNKNOWN = 0, - HTTP_METHOD_OPTIONS, - HTTP_METHOD_GET, - HTTP_METHOD_HEAD, - HTTP_METHOD_POST, - HTTP_METHOD_PUT, - HTTP_METHOD_DELETE, - HTTP_METHOD_TRACE, - HTTP_METHOD_CONNECT + NDPI_HTTP_METHOD_UNKNOWN = 0, + NDPI_HTTP_METHOD_OPTIONS, + NDPI_HTTP_METHOD_GET, + NDPI_HTTP_METHOD_HEAD, + NDPI_HTTP_METHOD_POST, + NDPI_HTTP_METHOD_PUT, + NDPI_HTTP_METHOD_DELETE, + NDPI_HTTP_METHOD_TRACE, + NDPI_HTTP_METHOD_CONNECT } ndpi_http_method; struct ndpi_lru_cache { diff --git a/src/lib/ndpi_content_match.c.inc b/src/lib/ndpi_content_match.c.inc index 3261618b9..3a8a9664f 100644 --- a/src/lib/ndpi_content_match.c.inc +++ b/src/lib/ndpi_content_match.c.inc @@ -8246,6 +8246,10 @@ ndpi_protocol_match host_match[] = { { "feelinsonice.com", NULL, "\\.feelsonice" TLD, "Snapchat", NDPI_PROTOCOL_SNAPCHAT, NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK, NDPI_PROTOCOL_FUN }, { ".snapchat.", NULL, "\\.snapchat" TLD, "Snapchat", NDPI_PROTOCOL_SNAPCHAT, NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK, NDPI_PROTOCOL_FUN }, { ".snapads.", NULL, "\\.snapads" TLD, "Snapchat", NDPI_PROTOCOL_SNAPCHAT, NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK, NDPI_PROTOCOL_FUN }, + { ".sc-cdn.net", NULL, "\\.sc-cdn\\.net" TLD, "Snapchat", NDPI_PROTOCOL_SNAPCHAT, NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK, NDPI_PROTOCOL_FUN }, + { ".sc-prod.net", NULL, "\\.sc-prod\\.net" TLD, "Snapchat", NDPI_PROTOCOL_SNAPCHAT, NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK, NDPI_PROTOCOL_FUN }, + { ".sc-jpl.com", NULL, "\\.sc-jpl\\.com" TLD, "Snapchat", NDPI_PROTOCOL_SNAPCHAT, NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK, NDPI_PROTOCOL_FUN }, + { "sc-analytics.appspot.com", NULL, "sc-analytics\\.appspot\\.com", "Snapchat", NDPI_PROTOCOL_SNAPCHAT, NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK, NDPI_PROTOCOL_FUN }, { ".waze.com", NULL, "\\.waze" TLD, "Waze", NDPI_PROTOCOL_WAZE, NDPI_PROTOCOL_CATEGORY_WEB, NDPI_PROTOCOL_ACCEPTABLE }, diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index 4e9f37248..047167ac3 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -318,6 +318,116 @@ int strncasecmp(s1, s2, n) /* ****************************************** */ +/* Keep it in order and in sync with ndpi_protocol_category_t in ndpi_typedefs.h */ +static const char* categories[] = { + "Unspecified", + "Media", + "VPN", + "Email", + "DataTransfer", + "Web", + "SocialNetwork", + "Download-FileTransfer-FileSharing", + "Game", + "Chat", + "VoIP", + "Database", + "RemoteAccess", + "Cloud", + "Network", + "Collaborative", + "RPC", + "Streaming", + "System", + "SoftwareUpdate", + "", + "", + "", + "", + "", + "Music", + "Video", + "Shopping", + "Productivity", + "FileSharing", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Mining", /* 99 */ + "Malware", + "Advertisement", + "Banned_Site", + "Site_Unavailable" +}; + +/* ****************************************** */ + /* Forward */ static void addDefaultPort(struct ndpi_detection_module_struct *ndpi_mod, ndpi_port_range *range, @@ -1725,7 +1835,7 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp ndpi_build_default_ports(ports_b, 17500, 0, 0, 0, 0) /* UDP */); ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SPOTIFY, 0 /* can_have_a_subprotocol */, no_master, - no_master, "Spotify", NDPI_PROTOCOL_CATEGORY_STREAMING, + no_master, "Spotify", NDPI_PROTOCOL_CATEGORY_MUSIC, 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_LISP, @@ -2243,6 +2353,12 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(void) { ndpi_str->bigrams_automa.ac_automa = ac_automata_init(ac_match_handler); ndpi_str->impossible_bigrams_automa.ac_automa = ac_automata_init(ac_match_handler); + if((sizeof(categories)/sizeof(char*)) != NDPI_PROTOCOL_NUM_CATEGORIES) { + NDPI_LOG_ERR(ndpi_str, "[NDPI] invalid categories length: expected %u, got %u\n", + NDPI_PROTOCOL_NUM_CATEGORIES, (unsigned int)(sizeof(categories)/sizeof(char*))); + return(NULL); + } + #ifdef HAVE_HYPERSCAN ndpi_str->custom_categories.num_to_load = 0, ndpi_str->custom_categories.to_load = NULL; ndpi_str->custom_categories.hostnames = NULL; @@ -5675,113 +5791,6 @@ void ndpi_category_set_name(struct ndpi_detection_module_struct *ndpi_mod, /* ****************************************************** */ -/* Keep it in order and in sync with ndpi_protocol_category_t in ndpi_typedefs.h */ -static const char* categories[] = { - "Unspecified", - "Media", - "VPN", - "Email", - "DataTransfer", - "Web", - "SocialNetwork", - "Download-FileTransfer-FileSharing", - "Game", - "Chat", - "VoIP", - "Database", - "RemoteAccess", - "Cloud", - "Network", - "Collaborative", - "RPC", - "Streaming", - "System", - "SoftwareUpdate", - "", - "", - "", - "", - "", - "Music", - "Video", - "Shopping", - "Productivity", - "FileSharing", - "", - "", - "", - - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - - "", - "", - "", - "", - "", - "", - "", - "", - - "Mining", /* 99 */ - "Malware", - "Advertisement", - "Banned_Site", - "Site_Unavailable" -}; - const char* ndpi_category_get_name(struct ndpi_detection_module_struct *ndpi_mod, ndpi_protocol_category_t category) { if((!ndpi_mod) || (category >= NDPI_PROTOCOL_NUM_CATEGORIES)) diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c index e282eb4d3..d17acd2bd 100644 --- a/src/lib/protocols/dns.c +++ b/src/lib/protocols/dns.c @@ -59,7 +59,19 @@ static u_int getNameLength(u_int i, const u_int8_t *payload, u_int payloadLen) { return(off + getNameLength(i+off, payload, payloadLen)); } } +/* + allowed chars for dns names A-Z 0-9 _ - + Perl script for generation map: + my @M; + for(my $ch=0; $ch < 256; $ch++) { + $M[$ch >> 5] |= 1 << ($ch & 0x1f) if chr($ch) =~ /[a-z0-9_-]/i; + } + print join(',', map { sprintf "0x%08x",$_ } @M),"\n"; + */ +static uint32_t dns_validchar[8] = { + 0x00000000,0x03ff2000,0x87fffffe,0x07fffffe,0,0,0,0 +}; /* *********************************************** */ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { @@ -108,6 +120,7 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd invalid = 1; if(!invalid) { + int j = 0, max_len, off; if(is_query) { /* DNS Request */ if((dns_header.num_queries > 0) && (dns_header.num_queries <= NDPI_MAX_DNS_REQUESTS) @@ -187,28 +200,31 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd } /* extract host name server */ - int j = 0, max_len = sizeof(flow->host_server_name)-1, off = sizeof(struct ndpi_dns_packet_header) + 1 + payload_offset; - while(off < flow->packet.payload_packet_len && flow->packet.payload[off] != '\0') { - flow->host_server_name[j] = flow->packet.payload[off]; - if(j < max_len) { - if(flow->host_server_name[j] < ' ') - flow->host_server_name[j] = '.'; - j++; - } else - break; - - off++; + max_len = sizeof(flow->host_server_name)-1; + off = sizeof(struct ndpi_dns_packet_header) + payload_offset; + + while(j < max_len && off < flow->packet.payload_packet_len && flow->packet.payload[off] != '\0') { + uint8_t c,cl = flow->packet.payload[off++]; + if( (cl & 0xc0) != 0 || // we not support compressed names in query + off + cl >= flow->packet.payload_packet_len) { + j = 0; break; + } + if(j && j < max_len) flow->host_server_name[j++] = '.'; + while(j < max_len && cl != 0) { + c = flow->packet.payload[off++]; + flow->host_server_name[j++] = dns_validchar[c >> 5] & (1 << (c & 0x1f)) ? c:'_'; + cl--; + } } + flow->host_server_name[j] = '\0'; if(is_query && (ndpi_struct->dns_dont_dissect_response == 0)) { // dpi_set_detected_protocol(ndpi_struct, flow, (d_port == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS, NDPI_PROTOCOL_UNKNOWN); return; /* The response will set the verdict */ } - - flow->host_server_name[j] = '\0'; flow->protos.dns.num_queries = (u_int8_t)dns_header.num_queries, - flow->protos.dns.num_answers = (u_int8_t) (dns_header.num_answers + dns_header.authority_rrs + dns_header.additional_rrs); + flow->protos.dns.num_answers = (u_int8_t) (dns_header.num_answers + dns_header.authority_rrs + dns_header.additional_rrs); if(j > 0) { ndpi_protocol_match_result ret_match; diff --git a/src/lib/protocols/ftp_data.c b/src/lib/protocols/ftp_data.c index 8d3e6fa8c..7c646c363 100644 --- a/src/lib/protocols/ftp_data.c +++ b/src/lib/protocols/ftp_data.c @@ -49,16 +49,22 @@ static int ndpi_match_ftp_data_directory(struct ndpi_detection_module_struct *nd struct ndpi_packet_struct *packet = &flow->packet; u_int32_t payload_len = packet->payload_packet_len; - if((payload_len >= 4) - && ((packet->payload[0] == '-') || (packet->payload[0] == 'd')) - && ((packet->payload[1] == '-') || (packet->payload[1] == 'r')) - && ((packet->payload[2] == '-') || (packet->payload[2] == 'w')) - && ((packet->payload[3] == '-') || (packet->payload[3] == 'x'))) { - - return 1; + if(payload_len > 10) { + int i; + + if(!((packet->payload[0] == '-') || (packet->payload[0] == 'd'))) + return(0); + + for(i=0; i<9; i += 3) + if(((packet->payload[1+i] == '-') || (packet->payload[1+i] == 'r')) + && ((packet->payload[2+i] == '-') || (packet->payload[2+i] == 'w')) + && ((packet->payload[3+i] == '-') || (packet->payload[3+i] == 'x'))) { + ; + } else + return 0; } - return 0; + return 1; } static int ndpi_match_file_header(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { @@ -220,16 +226,24 @@ static int ndpi_match_file_header(struct ndpi_detection_module_struct *ndpi_stru static void ndpi_check_ftp_data(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; - if((packet->payload_packet_len > 0) - && (ndpi_match_file_header(ndpi_struct, flow) - || ndpi_match_ftp_data_directory(ndpi_struct, flow) - || ndpi_match_ftp_data_port(ndpi_struct, flow) - ) - ) { - NDPI_LOG_INFO(ndpi_struct, "found FTP_DATA request\n"); - ndpi_int_ftp_data_add_connection(ndpi_struct, flow); - } else - NDPI_EXCLUDE_PROTO(ndpi_struct, flow); + /* + Make sure we see the beginning of the connection as otherwise we might have + false positive results + */ + if(flow->l4.tcp.seen_syn) { + if((packet->payload_packet_len > 0) + && (ndpi_match_file_header(ndpi_struct, flow) + || ndpi_match_ftp_data_directory(ndpi_struct, flow) + || ndpi_match_ftp_data_port(ndpi_struct, flow) + ) + ) { + NDPI_LOG_INFO(ndpi_struct, "found FTP_DATA request\n"); + ndpi_int_ftp_data_add_connection(ndpi_struct, flow); + return; + } + } + + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); } void ndpi_search_ftp_data(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { diff --git a/src/lib/protocols/http.c b/src/lib/protocols/http.c index 37f23e26a..fc392c2b7 100644 --- a/src/lib/protocols/http.c +++ b/src/lib/protocols/http.c @@ -173,25 +173,25 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_ } if(flow->packet.http_method.len < 3) - flow->http.method = HTTP_METHOD_UNKNOWN; + flow->http.method = NDPI_HTTP_METHOD_UNKNOWN; else { switch(flow->packet.http_method.ptr[0]) { - case 'O': flow->http.method = HTTP_METHOD_OPTIONS; break; - case 'G': flow->http.method = HTTP_METHOD_GET; break; - case 'H': flow->http.method = HTTP_METHOD_HEAD; break; + case 'O': flow->http.method = NDPI_HTTP_METHOD_OPTIONS; break; + case 'G': flow->http.method = NDPI_HTTP_METHOD_GET; break; + case 'H': flow->http.method = NDPI_HTTP_METHOD_HEAD; break; case 'P': switch(flow->packet.http_method.ptr[1]) { - case 'O': flow->http.method = HTTP_METHOD_POST; break; - case 'U': flow->http.method = HTTP_METHOD_PUT; break; + case 'O': flow->http.method = NDPI_HTTP_METHOD_POST; break; + case 'U': flow->http.method = NDPI_HTTP_METHOD_PUT; break; } break; - case 'D': flow->http.method = HTTP_METHOD_DELETE; break; - case 'T': flow->http.method = HTTP_METHOD_TRACE; break; - case 'C': flow->http.method = HTTP_METHOD_CONNECT; break; + case 'D': flow->http.method = NDPI_HTTP_METHOD_DELETE; break; + case 'T': flow->http.method = NDPI_HTTP_METHOD_TRACE; break; + case 'C': flow->http.method = NDPI_HTTP_METHOD_CONNECT; break; default: - flow->http.method = HTTP_METHOD_UNKNOWN; + flow->http.method = NDPI_HTTP_METHOD_UNKNOWN; break; } } @@ -822,7 +822,7 @@ void ndpi_search_http_tcp(struct ndpi_detection_module_struct *ndpi_struct, ndpi_http_method ndpi_get_http_method(struct ndpi_detection_module_struct *ndpi_mod, struct ndpi_flow_struct *flow) { if(!flow) - return(HTTP_METHOD_UNKNOWN); + return(NDPI_HTTP_METHOD_UNKNOWN); else return(flow->http.method); } diff --git a/src/lib/protocols/whatsapp.c b/src/lib/protocols/whatsapp.c index 6964a8e0e..608e6576e 100644 --- a/src/lib/protocols/whatsapp.c +++ b/src/lib/protocols/whatsapp.c @@ -26,34 +26,26 @@ void ndpi_search_whatsapp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; - u_int8_t whatsapp_sequence[] = { + static u_int8_t whatsapp_sequence[] = { 0x45, 0x44, 0x0, 0x01, 0x0, 0x0, 0x02, 0x08, 0x0, 0x57, 0x41, 0x02, 0x0, 0x0, 0x0 }; NDPI_LOG_DBG(ndpi_struct, "search WhatsApp\n"); - if(flow->l4.tcp.wa_matched_so_far == 0) { - if(memcmp(packet->payload, whatsapp_sequence, packet->payload_packet_len)) { - NDPI_EXCLUDE_PROTO(ndpi_struct, flow); - } else - flow->l4.tcp.wa_matched_so_far = packet->payload_packet_len; + if(flow->l4.tcp.wa_matched_so_far < sizeof(whatsapp_sequence)) { + size_t match_len = sizeof(whatsapp_sequence) - flow->l4.tcp.wa_matched_so_far; + if(packet->payload_packet_len < match_len) + match_len = packet->payload_packet_len; - return; - } else { - if(memcmp(packet->payload, &whatsapp_sequence[flow->l4.tcp.wa_matched_so_far], - sizeof(whatsapp_sequence)-flow->l4.tcp.wa_matched_so_far)) - NDPI_EXCLUDE_PROTO(ndpi_struct, flow); - else - ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_WHATSAPP, NDPI_PROTOCOL_UNKNOWN); - - return; - } - - if((packet->payload_packet_len > 240) - && (memcmp(packet->payload, whatsapp_sequence, sizeof(whatsapp_sequence)) == 0)) { - NDPI_LOG_INFO(ndpi_struct, "found WhatsApp\n"); - ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_WHATSAPP, NDPI_PROTOCOL_UNKNOWN); + if(!memcmp(packet->payload, &whatsapp_sequence[flow->l4.tcp.wa_matched_so_far], match_len)) { + flow->l4.tcp.wa_matched_so_far += match_len; + if(flow->l4.tcp.wa_matched_so_far == sizeof(whatsapp_sequence)) { + NDPI_LOG_INFO(ndpi_struct, "found WhatsApp\n"); + ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_WHATSAPP, NDPI_PROTOCOL_UNKNOWN); + } + return; + } } NDPI_EXCLUDE_PROTO(ndpi_struct, flow); |