aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/ndpi_typedefs.h18
-rw-r--r--src/lib/ndpi_content_match.c.inc4
-rw-r--r--src/lib/ndpi_main.c225
-rw-r--r--src/lib/protocols/dns.c44
-rw-r--r--src/lib/protocols/ftp_data.c50
-rw-r--r--src/lib/protocols/http.c22
-rw-r--r--src/lib/protocols/whatsapp.c34
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);