aboutsummaryrefslogtreecommitdiff
path: root/src/lib/protocols
diff options
context:
space:
mode:
authorLuca <deri@ntop.org>2019-04-05 12:51:59 +0200
committerLuca <deri@ntop.org>2019-04-05 12:51:59 +0200
commit1290706fad6a8acac8d1bfe09cd8bb27805ecd15 (patch)
treeffba667879c0dbd95f3a269f35b01a18934e4d67 /src/lib/protocols
parent4e7fa82affc876245ab7f008271a49bde80bcf9f (diff)
parent796472cf846142d07b5d7300d3d70062d25fc0a2 (diff)
Tests result fix
Merge branch 'dev' of https://github.com/ntop/nDPI into dev
Diffstat (limited to 'src/lib/protocols')
-rw-r--r--src/lib/protocols/dns.c66
-rw-r--r--src/lib/protocols/http.c26
-rw-r--r--src/lib/protocols/quic.c4
-rw-r--r--src/lib/protocols/ssl.c158
-rw-r--r--src/lib/protocols/whatsapp.c34
5 files changed, 199 insertions, 89 deletions
diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c
index e282eb4d3..1c2593feb 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)
@@ -140,8 +153,10 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
|| ((dns_header.authority_rrs > 0) && (dns_header.authority_rrs <= NDPI_MAX_DNS_REQUESTS))
|| ((dns_header.additional_rrs > 0) && (dns_header.additional_rrs <= NDPI_MAX_DNS_REQUESTS)))
) {
- /* This is a good reply */
- if(ndpi_struct->dns_dont_dissect_response == 0) {
+ /* This is a good reply: we dissect it both for request and response */
+
+ /* Leave the statement below commented necessary in case of call to ndpi_get_partial_detection() */
+ /* if(ndpi_struct->dns_dont_dissect_response == 0) */ {
x++;
if(flow->packet.payload[x] != '\0') {
@@ -173,6 +188,22 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
rsp_type = get16(&x, flow->packet.payload);
flow->protos.dns.rsp_type = rsp_type;
+
+ /* here x points to the response "class" field */
+ if((x+12) < flow->packet.payload_packet_len) {
+ x += 6;
+ data_len = get16(&x, flow->packet.payload);
+
+ if(((x + data_len) < flow->packet.payload_packet_len)
+ && (((rsp_type == 0x1) && (data_len == 4)) /* A */
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ || ((rsp_type == 0x1c) && (data_len == 16)) /* AAAA */
+#endif
+ )) {
+ memcpy(&flow->protos.dns.rsp_addr, flow->packet.payload + x, data_len);
+ }
+ }
+
break;
}
}
@@ -187,28 +218,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/http.c b/src/lib/protocols/http.c
index 37f23e26a..33ef9e2ed 100644
--- a/src/lib/protocols/http.c
+++ b/src/lib/protocols/http.c
@@ -157,7 +157,9 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
}
#endif
- if(!ndpi_struct->http_dont_dissect_response) {
+ /* Leave the statement below commented necessary in case of call to ndpi_get_partial_detection() */
+
+ /* if(!ndpi_struct->http_dont_dissect_response) */ {
if((flow->http.url == NULL)
&& (packet->http_url_name.len > 0)
&& (packet->host_line.len > 0)) {
@@ -173,25 +175,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 +824,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/quic.c b/src/lib/protocols/quic.c
index 322eb9be7..d14538e0d 100644
--- a/src/lib/protocols/quic.c
+++ b/src/lib/protocols/quic.c
@@ -22,6 +22,10 @@
*
*/
+#if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
+#include <sys/endian.h>
+#endif
+
#include "ndpi_protocol_ids.h"
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_QUIC
diff --git a/src/lib/protocols/ssl.c b/src/lib/protocols/ssl.c
index ff6b47a0f..05988a8d4 100644
--- a/src/lib/protocols/ssl.c
+++ b/src/lib/protocols/ssl.c
@@ -27,7 +27,7 @@
#include "ndpi_api.h"
-//#define CERTIFICATE_DEBUG 1
+// #define CERTIFICATE_DEBUG 1
#define NDPI_MAX_SSL_REQUEST_SIZE 10000
@@ -152,8 +152,9 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
#ifdef CERTIFICATE_DEBUG
{
u_int16_t ssl_version = (packet->payload[1] << 8) + packet->payload[2];
-
- printf("SSL [version: %u]\n", ssl_version);
+ u_int16_t ssl_len = (packet->payload[3] << 8) + packet->payload[4];
+
+ printf("SSL Record [version: 0x%02X][len: %u]\n", ssl_version, ssl_len);
}
#endif
@@ -175,10 +176,18 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
if(total_len > 4) {
int i;
- if(handshake_protocol == 0x02 || handshake_protocol == 0xb /* Server Hello and Certificate message types are interesting for us */) {
+#ifdef CERTIFICATE_DEBUG
+ printf("SSL [len: %u][handshake_protocol: %02X]\n", packet->payload_packet_len, handshake_protocol);
+#endif
+
+ if((handshake_protocol == 0x02)
+ || (handshake_protocol == 0xb) /* Server Hello and Certificate message types are interesting for us */) {
u_int num_found = 0;
- flow->l4.tcp.ssl_seen_server_cert = 1;
+ if(handshake_protocol == 0x02)
+ flow->l4.tcp.ssl_seen_server_cert = 1;
+ else
+ flow->l4.tcp.ssl_seen_certificate = 1;
/* Check after handshake protocol header (5 bytes) and message header (4 bytes) */
for(i = 9; i < packet->payload_packet_len-3; i++) {
@@ -216,11 +225,11 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
break;
} else if(buffer[j] == '.') {
num_dots++;
- if(num_dots >=2) break;
+ if(num_dots >=1) break;
}
}
- if(num_dots >= 2) {
+ if(num_dots >= 1) {
if(!ndpi_struct->disable_metadata_export) {
stripCertificateTrailer(buffer, buffer_len);
snprintf(flow->protos.stun_ssl.ssl.server_certificate,
@@ -233,7 +242,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
}
} else if(handshake_protocol == 0x01 /* Client Hello */) {
u_int offset, base_offset = 43;
- if (base_offset + 2 <= packet->payload_packet_len) {
+ if(base_offset + 2 <= packet->payload_packet_len) {
u_int16_t session_id_len = packet->payload[base_offset];
if((session_id_len+base_offset+2) <= total_len) {
@@ -335,25 +344,94 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
return(0); /* Not found */
}
+void getSSLorganization(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ char *buffer, int buffer_len) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if(packet->payload[0] != 0x16 /* Handshake */)
+ return;
+
+ u_int16_t total_len = (packet->payload[3] << 8) + packet->payload[4] + 5 /* SSL Header */;
+ u_int8_t handshake_protocol = packet->payload[5]; /* handshake protocol a bit misleading, it is message type according TLS specs */
+
+ if(handshake_protocol != 0x02 && handshake_protocol != 0xb /* Server Hello and Certificate message types are interesting for us */)
+ return;
+
+ /* Truncate total len, search at least in incomplete packet */
+ if(total_len > packet->payload_packet_len)
+ total_len = packet->payload_packet_len;
+
+ memset(buffer, 0, buffer_len);
+
+ /* Check after handshake protocol header (5 bytes) and message header (4 bytes) */
+ u_int num_found = 0;
+ u_int i, j;
+ for(i = 9; i < packet->payload_packet_len-4; i++) {
+ /* Organization OID: 2.5.4.10 */
+ if((packet->payload[i] == 0x55) && (packet->payload[i+1] == 0x04) && (packet->payload[i+2] == 0x0a)) {
+ u_int8_t type_tag = packet->payload[i+3]; // 0x0c: utf8string / 0x13: printable_string
+ u_int8_t server_len = packet->payload[i+4];
+
+ num_found++;
+ /* what we want is subject certificate, so we bypass the issuer certificate */
+ if(num_found != 2) continue;
+
+ // packet is truncated... further inspection is not needed
+ if(i+4+server_len >= packet->payload_packet_len) {
+ break;
+ }
+
+ char *server_org = (char*)&packet->payload[i+5];
+
+ u_int len = (u_int)ndpi_min(server_len, buffer_len-1);
+ strncpy(buffer, server_org, len);
+ buffer[len] = '\0';
+
+ // check if organization string are all printable
+ u_int8_t is_printable = 1;
+ for (j = 0; j < len; j++) {
+ if(!ndpi_isprint(buffer[j])) {
+ is_printable = 0;
+ break;
+ }
+ }
+
+ if(is_printable == 1) {
+ snprintf(flow->protos.stun_ssl.ssl.server_organization,
+ sizeof(flow->protos.stun_ssl.ssl.server_organization), "%s", buffer);
+#ifdef CERTIFICATE_DEBUG
+ printf("Certificate origanization: %s\n", flow->protos.stun_ssl.ssl.server_organization);
+#endif
+ }
+ }
+ }
+}
+
int sslTryAndRetrieveServerCertificate(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &flow->packet;
/* consider only specific SSL packets (handshake) */
if((packet->payload_packet_len > 9) && (packet->payload[0] == 0x16)) {
char certificate[64];
+ char organization[64];
int rc;
certificate[0] = '\0';
rc = getSSLcertificate(ndpi_struct, flow, certificate, sizeof(certificate));
packet->ssl_certificate_num_checks++;
- if (rc > 0) {
+ if(rc > 0) {
+ // try fetch server organization once server certificate is found
+ organization[0] = '\0';
+ getSSLorganization(ndpi_struct, flow, organization, sizeof(organization));
+
packet->ssl_certificate_detected++;
- if ((flow->l4.tcp.ssl_seen_server_cert == 1) && (flow->protos.stun_ssl.ssl.server_certificate[0] != '\0'))
+ if((flow->l4.tcp.ssl_seen_server_cert == 1) && (flow->protos.stun_ssl.ssl.server_certificate[0] != '\0'))
/* 0 means we're done processing extra packets (since we found what we wanted) */
return 0;
}
/* Client hello, Server Hello, and certificate packets probably all checked in this case */
- if ((packet->ssl_certificate_num_checks >= 3)
+ if((packet->ssl_certificate_num_checks >= 3)
&& (flow->l4.tcp.seen_syn)
&& (flow->l4.tcp.seen_syn_ack)
&& (flow->l4.tcp.seen_ack) /* We have seen the 3-way handshake */)
@@ -369,7 +447,7 @@ int sslTryAndRetrieveServerCertificate(struct ndpi_detection_module_struct *ndpi
void sslInitExtraPacketProcessing(int caseNum, struct ndpi_flow_struct *flow) {
flow->check_extra_packets = 1;
/* 0 is the case for waiting for the server certificate */
- if (caseNum == 0) {
+ if(caseNum == 0) {
/* At most 7 packets should almost always be enough to find the server certificate if it's there */
flow->max_extra_packets_to_check = 7;
flow->extra_packets_func = sslTryAndRetrieveServerCertificate;
@@ -405,7 +483,8 @@ int sslDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_s
/* If we've detected the subprotocol from client certificate but haven't had a chance
* to see the server certificate yet, set up extra packet processing to wait
* a few more packets. */
- if(((flow->l4.tcp.ssl_seen_client_cert == 1) && (flow->protos.stun_ssl.ssl.client_certificate[0] != '\0')) && ((flow->l4.tcp.ssl_seen_server_cert != 1) && (flow->protos.stun_ssl.ssl.server_certificate[0] == '\0'))) {
+ if(((flow->l4.tcp.ssl_seen_client_cert == 1) && (flow->protos.stun_ssl.ssl.client_certificate[0] != '\0'))
+ && ((flow->l4.tcp.ssl_seen_server_cert != 1) && (flow->protos.stun_ssl.ssl.server_certificate[0] == '\0'))) {
sslInitExtraPacketProcessing(0, flow);
}
@@ -418,11 +497,13 @@ int sslDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_s
return(rc);
}
- if(((packet->ssl_certificate_num_checks >= 2)
+ if(((packet->ssl_certificate_num_checks >= 3)
&& flow->l4.tcp.seen_syn
&& flow->l4.tcp.seen_syn_ack
&& flow->l4.tcp.seen_ack /* We have seen the 3-way handshake */)
- || ((flow->l4.tcp.ssl_seen_server_cert == 1) && (flow->protos.stun_ssl.ssl.server_certificate[0] != '\0'))
+ || ((flow->l4.tcp.ssl_seen_certificate == 1)
+ && (flow->l4.tcp.ssl_seen_server_cert == 1)
+ && (flow->protos.stun_ssl.ssl.server_certificate[0] != '\0'))
/* || ((flow->l4.tcp.ssl_seen_client_cert == 1) && (flow->protos.stun_ssl.ssl.client_certificate[0] != '\0')) */
) {
ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL);
@@ -432,8 +513,7 @@ int sslDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_s
return(0);
}
-static void ssl_mark_and_payload_search_for_other_protocols(struct
- ndpi_detection_module_struct
+static void ssl_mark_and_payload_search_for_other_protocols(struct ndpi_detection_module_struct
*ndpi_struct, struct ndpi_flow_struct *flow)
{
struct ndpi_packet_struct *packet = &flow->packet;
@@ -510,16 +590,16 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct
/* SSL without certificate (Skype, Ultrasurf?) */
NDPI_LOG_INFO(ndpi_struct, "found ssl NO_CERT\n");
ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL_NO_CERT);
- } else
+ } else if(packet->ssl_certificate_num_checks >= 3) {
NDPI_LOG_INFO(ndpi_struct, "found ssl\n");
- ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL);
+ ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL);
+ }
}
}
static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow) {
-
struct ndpi_packet_struct *packet = &flow->packet;
if((packet->payload_packet_len >= 5)
@@ -647,27 +727,25 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc
NDPI_LOG_DBG(ndpi_struct, "search ssl\n");
- {
- /* Check if this is whatsapp first (this proto runs over port 443) */
- if((packet->payload_packet_len > 5)
- && ((packet->payload[0] == 'W')
- && (packet->payload[1] == 'A')
- && (packet->payload[4] == 0)
- && (packet->payload[2] <= 9)
- && (packet->payload[3] <= 9))) {
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_WHATSAPP, NDPI_PROTOCOL_UNKNOWN);
- return;
- } else if((packet->payload_packet_len == 4)
- && (packet->payload[0] == 'W')
- && (packet->payload[1] == 'A')) {
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_WHATSAPP, NDPI_PROTOCOL_UNKNOWN);
+ /* Check if this is whatsapp first (this proto runs over port 443) */
+ if((packet->payload_packet_len > 5)
+ && ((packet->payload[0] == 'W')
+ && (packet->payload[1] == 'A')
+ && (packet->payload[4] == 0)
+ && (packet->payload[2] <= 9)
+ && (packet->payload[3] <= 9))) {
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_WHATSAPP, NDPI_PROTOCOL_UNKNOWN);
+ return;
+ } else if((packet->payload_packet_len == 4)
+ && (packet->payload[0] == 'W')
+ && (packet->payload[1] == 'A')) {
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_WHATSAPP, NDPI_PROTOCOL_UNKNOWN);
+ return;
+ } else {
+ /* No whatsapp, let's try SSL */
+ if(sslDetectProtocolFromCertificate(ndpi_struct, flow) > 0)
return;
- } else {
- /* No whatsapp, let's try SSL */
- if(sslDetectProtocolFromCertificate(ndpi_struct, flow) > 0)
- return;
- }
- }
+ }
if(packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 0) {
NDPI_LOG_DBG2(ndpi_struct, "first ssl packet\n");
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);