diff options
-rw-r--r-- | example/ndpiReader.c | 21 | ||||
-rw-r--r-- | src/include/ndpi_api.h | 1 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 112 | ||||
-rw-r--r-- | src/lib/ndpi_utils.c | 28 | ||||
-rw-r--r-- | src/lib/protocols/quic.c | 4 | ||||
-rw-r--r-- | src/lib/protocols/ssl.c | 78 | ||||
-rw-r--r-- | src/lib/protocols/stun.c | 4 |
7 files changed, 155 insertions, 93 deletions
diff --git a/example/ndpiReader.c b/example/ndpiReader.c index 75f3c4f6d..73dfdf051 100644 --- a/example/ndpiReader.c +++ b/example/ndpiReader.c @@ -764,23 +764,6 @@ static char* print_cipher(ndpi_cipher_weakness c) { /* ********************************** */ -static char* ssl_version2str(u_int16_t version) { - static char v[8]; - - switch(version) { - case 0x300: return("SSLv3"); - case 0x301: return("TLSv1"); - case 0x302: return("TLSv1.1"); - case 0x303: return("TLSv1.2"); - case 0x304: return("TLSv1.3"); - } - - snprintf(v, sizeof(v), "%04X", version); - return(v); -} - -/* ********************************** */ - /** * @brief Print the flow */ @@ -835,7 +818,7 @@ static void printFlow(u_int16_t id, struct ndpi_flow_info *flow, u_int16_t threa if(flow->info[0] != '\0') fprintf(out, "[%s]", flow->info); - if(flow->ssh_ssl.ssl_version != 0) fprintf(out, "[%s]", ssl_version2str(flow->ssh_ssl.ssl_version)); + if(flow->ssh_ssl.ssl_version != 0) fprintf(out, "[%s]", ndpi_ssl_version2str(flow->ssh_ssl.ssl_version)); if(flow->ssh_ssl.ja3_client[0] != '\0') fprintf(out, "[JA3C: %s%s]", flow->ssh_ssl.ja3_client, print_cipher(flow->ssh_ssl.client_unsafe_cipher)); if(flow->ssh_ssl.server_info[0] != '\0') fprintf(out, "[server: %s]", flow->ssh_ssl.server_info); @@ -2742,6 +2725,8 @@ void test_lib() { } } +/* *********************************************** */ + void automataUnitTest() { void *automa; diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h index 7297f0038..466d51b48 100644 --- a/src/include/ndpi_api.h +++ b/src/include/ndpi_api.h @@ -813,6 +813,7 @@ extern "C" { struct ndpi_flow_struct *flow); int ndpi_has_human_readeable_string(struct ndpi_detection_module_struct *ndpi_struct, char *buffer, u_int buffer_size); + char* ndpi_ssl_version2str(u_int16_t version); #ifdef __cplusplus } #endif diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index 85366358b..325123476 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -53,7 +53,7 @@ static int _ndpi_debug_callbacks = 0; -// #define MATCH_DEBUG 1 +/* #define MATCH_DEBUG 1 */ /* ****************************************** */ @@ -1750,7 +1750,7 @@ static int ac_match_handler(AC_MATCH_t *m, AC_TEXT_t *txt, AC_REP_t *match) { has to match */ if(whatfound && (whatfound != buf) - && (m->patterns->astring[0] != '.') /* The searched patter does not start with . */ + && (m->patterns->astring[0] != '.') /* The searched pattern does not start with . */ && strchr(m->patterns->astring, '.') /* The matched pattern has a . (e.g. numeric or sym IPs) */ && (whatfound[-1] != '.') ) @@ -1768,12 +1768,18 @@ static int ac_match_handler(AC_MATCH_t *m, AC_TEXT_t *txt, AC_REP_t *match) { || (strncmp(buf, m->patterns->astring, min_len) == 0) /* begins with */ ) { #ifdef MATCH_DEBUG - printf("Found match [%s][%s] [len: %u][proto_id: %u]\n", - buf, m->patterns->astring, min_len , *matching_protocol_id); + printf("Found match [%s][%s] [len: %u]" + // "[proto_id: %u]" + "\n", + buf, m->patterns->astring, min_len /* , *matching_protocol_id */); #endif return(1); /* If the pattern found matches the string at the beginning we stop here */ - } else + } else { +#ifdef MATCH_DEBUG + printf("NO match found: continue\n"); +#endif return 0; /* 0 to continue searching, !0 to stop */ + } } /* ******************************************************************** */ @@ -2155,6 +2161,7 @@ int ndpi_match_string(void *_automa, char *string_to_match) { AC_REP_t match = { NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED, NDPI_PROTOCOL_UNRATED }; AC_TEXT_t ac_input_text; AC_AUTOMATA_t *automa = (AC_AUTOMATA_t*)_automa; + int rc; if((automa == NULL) || (string_to_match == NULL) @@ -2162,10 +2169,10 @@ int ndpi_match_string(void *_automa, char *string_to_match) { return(-2); ac_input_text.astring = string_to_match, ac_input_text.length = strlen(string_to_match); - ac_automata_search(automa, &ac_input_text, &match); + rc = ac_automata_search(automa, &ac_input_text, &match); ac_automata_reset(automa); - return(match.number > 0 ? 0 : -1); + return(rc ? match.number : 0); } /* ****************************************************** */ @@ -2174,6 +2181,7 @@ int ndpi_match_string_id(void *_automa, char *string_to_match, unsigned long *id AC_TEXT_t ac_input_text; AC_AUTOMATA_t *automa = (AC_AUTOMATA_t*)_automa; AC_REP_t match = { NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED, NDPI_PROTOCOL_UNRATED }; + int rc; *id = -1; if((automa == NULL) @@ -2182,10 +2190,10 @@ int ndpi_match_string_id(void *_automa, char *string_to_match, unsigned long *id return(-2); ac_input_text.astring = string_to_match, ac_input_text.length = strlen(string_to_match); - ac_automata_search(automa, &ac_input_text, &match); + rc = ac_automata_search(automa, &ac_input_text, &match); ac_automata_reset(automa); - *id = match.number; + *id = rc ? match.number : NDPI_PROTOCOL_UNKNOWN; return(*id != NDPI_PROTOCOL_UNKNOWN ? 0 : -1); } @@ -4491,7 +4499,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct else sport = dport = 0; /* guess protocol */ - flow->guessed_protocol_id = (int16_t) ndpi_guess_protocol_id(ndpi_struct, flow, protocol, sport, dport, &user_defined_proto); + flow->guessed_protocol_id = (int16_t)ndpi_guess_protocol_id(ndpi_struct, flow, protocol, sport, dport, &user_defined_proto); flow->guessed_host_protocol_id = ndpi_guess_host_protocol_id(ndpi_struct, flow); if(ndpi_struct->custom_categories.categories_loaded && flow->packet.iph) { @@ -4534,15 +4542,24 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct /* This is a custom protocol and it has priority over everything else */ ret.master_protocol = NDPI_PROTOCOL_UNKNOWN, ret.app_protocol = flow->guessed_host_protocol_id; - if(flow->packet.tcp) { + if(flow->packet.tcp && (ret.master_protocol == NDPI_PROTOCOL_UNKNOWN)) { /* Minimal guess for HTTP/SSL-based protocols */ - switch(ntohs(flow->packet.tcp->dest)) { - case 80: - ret.master_protocol = NDPI_PROTOCOL_HTTP; - break; - case 443: - ret.master_protocol = NDPI_PROTOCOL_SSL; /* QUIC could also match */ - break; + int i; + + for(i=0; i<2; i++) { + u_int16_t port = (i == 0) ? ntohs(flow->packet.tcp->dest) : ntohs(flow->packet.tcp->source); + + switch(port) { + case 80: + ret.master_protocol = NDPI_PROTOCOL_HTTP; + break; + case 443: + ret.master_protocol = NDPI_PROTOCOL_SSL; /* QUIC could also match */ + break; + } + + if(ret.master_protocol != NDPI_PROTOCOL_UNKNOWN) + break; } } @@ -5498,7 +5515,7 @@ ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct u_int8_t user_defined_proto; if((proto == IPPROTO_TCP) || (proto == IPPROTO_UDP)) { - rc = ndpi_search_tcp_or_udp_raw(ndpi_struct, NULL, proto, shost, dhost, sport, dport); + rc = ndpi_search_tcp_or_udp_raw(ndpi_struct, flow, proto, shost, dhost, sport, dport); if(rc != NDPI_PROTOCOL_UNKNOWN) { if(flow && (proto == IPPROTO_UDP) @@ -5507,7 +5524,7 @@ ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct ; else { ret.app_protocol = rc, - ret.master_protocol = ndpi_guess_protocol_id(ndpi_struct, NULL, proto, sport, + ret.master_protocol = ndpi_guess_protocol_id(ndpi_struct, flow, proto, sport, dport, &user_defined_proto); if(ret.app_protocol == ret.master_protocol) @@ -5518,7 +5535,7 @@ ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct } } - rc = ndpi_guess_protocol_id(ndpi_struct, NULL, proto, sport, dport, &user_defined_proto); + rc = ndpi_guess_protocol_id(ndpi_struct, flow, proto, sport, dport, &user_defined_proto); if(rc != NDPI_PROTOCOL_UNKNOWN) { if(flow && (proto == IPPROTO_UDP) && NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, rc) @@ -5546,7 +5563,7 @@ ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct ret.app_protocol = NDPI_PROTOCOL_SKYPE; } } else - ret.app_protocol = ndpi_guess_protocol_id(ndpi_struct, NULL, proto, sport, + ret.app_protocol = ndpi_guess_protocol_id(ndpi_struct, flow, proto, sport, dport, &user_defined_proto); ret.category = ndpi_get_proto_category(ndpi_struct, ret); @@ -5645,8 +5662,15 @@ void ndpi_category_set_name(struct ndpi_detection_module_struct *ndpi_mod, 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)) - return(NULL); + if((!ndpi_mod) || (category >= NDPI_PROTOCOL_NUM_CATEGORIES)) { + static char b[24]; + + if(!ndpi_mod) + snprintf(b, sizeof(b), "NULL nDPI"); + else + snprintf(b, sizeof(b), "Invalid category %d", (int)category); + return(b); + } if((category >= NDPI_PROTOCOL_CATEGORY_CUSTOM_1) && (category <= NDPI_PROTOCOL_CATEGORY_CUSTOM_5)) { switch(category) { @@ -5687,7 +5711,7 @@ ndpi_protocol_category_t ndpi_get_proto_category(struct ndpi_detection_module_st char* ndpi_get_proto_name(struct ndpi_detection_module_struct *ndpi_mod, u_int16_t proto_id) { if((proto_id >= ndpi_mod->ndpi_num_supported_protocols) - || (proto_id < (NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) + || (proto_id >= (NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) || (ndpi_mod->proto_defaults[proto_id].protoName == NULL)) proto_id = NDPI_PROTOCOL_UNKNOWN; @@ -5699,7 +5723,7 @@ char* ndpi_get_proto_name(struct ndpi_detection_module_struct *ndpi_mod, u_int16 ndpi_protocol_breed_t ndpi_get_proto_breed(struct ndpi_detection_module_struct *ndpi_mod, u_int16_t proto_id) { if((proto_id >= ndpi_mod->ndpi_num_supported_protocols) - || (proto_id < (NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) + || (proto_id >= (NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) || (ndpi_mod->proto_defaults[proto_id].protoName == NULL)) proto_id = NDPI_PROTOCOL_UNKNOWN; @@ -5822,8 +5846,7 @@ char* ndpi_strncasestr(const char *s, const char *find, size_t slen) { /* ****************************************************** */ int ndpi_match_prefix(const u_int8_t *payload, size_t payload_len, - const char *str, size_t str_len) -{ + const char *str, size_t str_len) { int rc = str_len <= payload_len ? memcmp(payload, str, str_len) == 0 : 0; return rc; @@ -5836,9 +5859,9 @@ int ndpi_match_string_subprotocol(struct ndpi_detection_module_struct *ndpi_stru ndpi_protocol_match_result *ret_match, u_int8_t is_host_match) { AC_TEXT_t ac_input_text; - ndpi_automa *automa = is_host_match ? &ndpi_struct->host_automa : - &ndpi_struct->content_automa; + ndpi_automa *automa = is_host_match ? &ndpi_struct->host_automa : &ndpi_struct->content_automa; AC_REP_t match = { NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED, NDPI_PROTOCOL_UNRATED }; + int rc; if((automa->ac_automa == NULL) || (string_to_match_len == 0)) return(NDPI_PROTOCOL_UNKNOWN); @@ -5849,14 +5872,22 @@ int ndpi_match_string_subprotocol(struct ndpi_detection_module_struct *ndpi_stru } ac_input_text.astring = string_to_match, ac_input_text.length = string_to_match_len; - ac_automata_search(((AC_AUTOMATA_t*)automa->ac_automa), &ac_input_text, &match); + rc = ac_automata_search(((AC_AUTOMATA_t*)automa->ac_automa), &ac_input_text, &match); ac_automata_reset(((AC_AUTOMATA_t*)automa->ac_automa)); - ret_match->protocol_id = match.number, - ret_match->protocol_category = match.category, - ret_match->protocol_breed = match.breed; - - return(match.number); + /* We need to take into account also rc==0 that is used for partial matches */ +#if 0 + if(rc) { +#endif + ret_match->protocol_id = match.number, + ret_match->protocol_category = match.category, + ret_match->protocol_breed = match.breed; + + return(match.number); +#if 0 + } else + return(NDPI_PROTOCOL_UNKNOWN); +#endif } #ifdef HAVE_HYPERSCAN @@ -5950,6 +5981,10 @@ static int ndpi_automa_match_string_subprotocol(struct ndpi_detection_module_str NDPI_LOG_DBG2(ndpi_struct, "[NTOP] Unable to find a match for '%s'\n", string_to_match); #endif + ret_match->protocol_id = NDPI_PROTOCOL_UNKNOWN, + ret_match->protocol_category = NDPI_PROTOCOL_CATEGORY_UNSPECIFIED, + ret_match->protocol_breed = NDPI_PROTOCOL_UNRATED; + return(NDPI_PROTOCOL_UNKNOWN); } @@ -5983,6 +6018,7 @@ int ndpi_match_bigram(struct ndpi_detection_module_struct *ndpi_struct, ndpi_automa *automa, char *bigram_to_match) { AC_TEXT_t ac_input_text; AC_REP_t match = { NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED, NDPI_PROTOCOL_UNRATED }; + int rc; if((automa->ac_automa == NULL) || (bigram_to_match == NULL)) return(-1); @@ -5993,10 +6029,10 @@ int ndpi_match_bigram(struct ndpi_detection_module_struct *ndpi_struct, } ac_input_text.astring = bigram_to_match, ac_input_text.length = 2; - ac_automata_search(((AC_AUTOMATA_t*)automa->ac_automa), &ac_input_text, &match); + rc = ac_automata_search(((AC_AUTOMATA_t*)automa->ac_automa), &ac_input_text, &match); ac_automata_reset(((AC_AUTOMATA_t*)automa->ac_automa)); - return(match.number); + return(rc ? match.number : 0); } /* ****************************************************** */ diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c index 480f4ff18..933d5634c 100644 --- a/src/lib/ndpi_utils.c +++ b/src/lib/ndpi_utils.c @@ -590,7 +590,12 @@ const char* ndpi_cipher2str(u_int32_t cipher) { case 0x060040: return("SSL2_DES_64_CBC_WITH_MD5"); case 0x0700c0: return("SSL2_DES_192_EDE3_CBC_WITH_MD5"); case 0x080080: return("SSL2_RC4_64_WITH_MD5"); - case 0x001301: return("TLS_AES_128_GMC_SHA256"); + case 0x001301: return("TLS_AES_128_GCM_SHA256"); + case 0x001302: return("TLS_AES_256_GCM_SHA384"); + case 0x001303: return("TLS_CHACHA20_POLY1305_SHA256"); + case 0x001304: return("TLS_AES_128_CCM_SHA256"); + case 0x001305: return("TLS_AES_128_CCM_8_SHA256"); + default: { static char buf[8]; @@ -682,3 +687,24 @@ int ndpi_has_human_readeable_string(struct ndpi_detection_module_struct *ndpi_st return(ret); } + +/* ********************************** */ + +char* ndpi_ssl_version2str(u_int16_t version) { + static char v[8]; + + switch(version) { + case 0x300: return("SSLv3"); + case 0x301: return("TLSv1"); + case 0x302: return("TLSv1.1"); + case 0x303: return("TLSv1.2"); + case 0x304: return("TLSv1.3"); + } + + if((version >= 0x7f00) && (version <= 0x7fff)) + return("TLSv1.3 (draft)"); + + snprintf(v, sizeof(v), "%04X", version); + return(v); +} + diff --git a/src/lib/protocols/quic.c b/src/lib/protocols/quic.c index d67414fdf..9bf382217 100644 --- a/src/lib/protocols/quic.c +++ b/src/lib/protocols/quic.c @@ -100,8 +100,8 @@ void ndpi_search_quic(struct ndpi_detection_module_struct *ndpi_struct, && (packet->payload[i+1] == 'N') && (packet->payload[i+2] == 'I') && (packet->payload[i+3] == 0)) { - u_int32_t offset = ntohl(*((u_int32_t*)&packet->payload[i+4])); - u_int32_t prev_offset = ntohl(*((u_int32_t*)&packet->payload[i-4])); + u_int32_t offset = (*((u_int32_t*)&packet->payload[i+4])); + u_int32_t prev_offset = (*((u_int32_t*)&packet->payload[i-4])); int len = offset-prev_offset; int sni_offset = i+prev_offset+1; diff --git a/src/lib/protocols/ssl.c b/src/lib/protocols/ssl.c index f7009a788..29b22ac11 100644 --- a/src/lib/protocols/ssl.c +++ b/src/lib/protocols/ssl.c @@ -238,9 +238,10 @@ static u_int32_t ndpi_ssl_refine_master_protocol(struct ndpi_detection_module_st { struct ndpi_packet_struct *packet = &flow->packet; - 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')) - || (flow->host_server_name[0] != '\0')) + if(((flow->l4.tcp.ssl_seen_client_cert == 1) && (flow->protos.stun_ssl.ssl.ja3_client[0] != '\0')) + || ((flow->l4.tcp.ssl_seen_server_cert == 1) && (flow->protos.stun_ssl.ssl.ja3_server[0] != '\0')) + // || (flow->host_server_name[0] != '\0') + ) protocol = NDPI_PROTOCOL_SSL; else protocol = NDPI_PROTOCOL_SSL_NO_CERT; @@ -373,7 +374,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, u_char md5_hash[16]; flow->protos.stun_ssl.ssl.ssl_version = ssl_version; - + memset(&ja3, 0, sizeof(ja3)); #ifdef CERTIFICATE_DEBUG @@ -409,7 +410,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, if((handshake_protocol == 0x02) || (handshake_protocol == 0xb) /* Server Hello and Certificate message types are interesting for us */) { u_int num_found = 0; - u_int16_t ssl_version = ntohs(*((u_int16_t*)&packet->payload[9])); + u_int16_t ssl_version = ntohs(*((u_int16_t*)&packet->payload[9])); ja3.ssl_version = ssl_version; @@ -417,12 +418,23 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, u_int16_t offset = 43, extension_len, j; u_int8_t session_id_len = packet->payload[43]; - offset += session_id_len+1; +#ifdef CERTIFICATE_DEBUG + printf("SSL Server Hello [version: 0x%04X]\n", ssl_version); +#endif + + /* + The server hello decides about the SSL version of this flow + https://networkengineering.stackexchange.com/questions/55752/why-does-wireshark-show-version-tls-1-2-here-instead-of-tls-1-3 + */ + flow->protos.stun_ssl.ssl.ssl_version = ssl_version; + + if(ssl_version < 0x7F15 /* TLS 1.3 lacks of session id */) + offset += session_id_len+1; ja3.num_cipher = 1, ja3.cipher[0] = ntohs(*((u_int16_t*)&packet->payload[offset])); flow->protos.stun_ssl.ssl.server_unsafe_cipher = ndpi_is_safe_ssl_cipher(ja3.cipher[0]); flow->protos.stun_ssl.ssl.server_cipher = ja3.cipher[0]; - + #ifdef CERTIFICATE_DEBUG printf("SSL [server][session_id_len: %u][cipher: %04X]\n", session_id_len, ja3.cipher[0]); #endif @@ -468,23 +480,23 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, #ifdef CERTIFICATE_DEBUG printf("SSL [server] %s\n", ja3_str); #endif - + #ifdef CERTIFICATE_DEBUG printf("[JA3] Server: %s \n", ja3_str); #endif - + MD5Init(&ctx); MD5Update(&ctx, (const unsigned char *)ja3_str, strlen(ja3_str)); MD5Final(md5_hash, &ctx); - + for(i=0, j=0; i<16; i++) j += snprintf(&flow->protos.stun_ssl.ssl.ja3_server[j], sizeof(flow->protos.stun_ssl.ssl.ja3_server)-j, "%02x", md5_hash[i]); - + #ifdef CERTIFICATE_DEBUG printf("[JA3] Server: %s \n", flow->protos.stun_ssl.ssl.ja3_server); #endif - + flow->l4.tcp.ssl_seen_server_cert = 1; } else flow->l4.tcp.ssl_seen_certificate = 1; @@ -561,7 +573,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, if((cipher_offset+cipher_len) <= total_len) { for(i=0; i<cipher_len;) { u_int16_t *id = (u_int16_t*)&packet->payload[cipher_offset+i]; - + #ifdef CERTIFICATE_DEBUG printf("Client SSL [cipher suite: %u] [%u/%u]\n", ntohs(*id), i, cipher_len); #endif @@ -570,7 +582,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, Skip GREASE [https://tools.ietf.org/id/draft-ietf-tls-grease-01.html] https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967 */ - + if(ja3.num_cipher < MAX_NUM_JA3) ja3.cipher[ja3.num_cipher++] = ntohs(*id); else { @@ -580,16 +592,16 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, #endif } } - + i += 2; } } else { invalid_ja3 = 1; #ifdef CERTIFICATE_DEBUG printf("Client SSL Invalid len %u vs %u\n", (cipher_offset+cipher_len), total_len); -#endif +#endif } - + offset = base_offset + session_id_len + cipher_len + 2; flow->l4.tcp.ssl_seen_client_cert = 1; @@ -673,7 +685,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, if((s_offset+extension_len-2) <= total_len) { for(i=0; i<extension_len-2;) { u_int16_t s_group = ntohs(*((u_int16_t*)&packet->payload[s_offset+i])); - + #ifdef CERTIFICATE_DEBUG printf("Client SSL [EllipticCurve: %u]\n", s_group); #endif @@ -681,7 +693,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, /* Skip GREASE */ if(ja3.num_elliptic_curve < MAX_NUM_JA3) ja3.elliptic_curve[ja3.num_elliptic_curve++] = s_group; - else { + else { invalid_ja3 = 1; #ifdef CERTIFICATE_DEBUG printf("Client SSL Invalid num elliptic %u\n", ja3.num_elliptic_curve); @@ -696,7 +708,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, #ifdef CERTIFICATE_DEBUG printf("Client SSL Invalid len %u vs %u\n", (s_offset+extension_len-1), total_len); #endif - } + } } else if(extension_id == 11 /* ec_point_formats groups */) { u_int16_t i, s_offset = offset+extension_offset + 1; @@ -706,11 +718,11 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, if((s_offset+extension_len) < total_len) { for(i=0; i<extension_len-1;i++) { u_int8_t s_group = packet->payload[s_offset+i]; - + #ifdef CERTIFICATE_DEBUG printf("Client SSL [EllipticCurveFormat: %u]\n", s_group); #endif - + if(ja3.num_elliptic_curve_point_format < MAX_NUM_JA3) ja3.elliptic_curve_point_format[ja3.num_elliptic_curve_point_format++] = s_group; else { @@ -727,7 +739,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, #endif } } - + extension_offset += extension_len; #ifdef CERTIFICATE_DEBUG @@ -737,30 +749,30 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, if(!invalid_ja3) { ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.ssl_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]); } - + ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ","); - + /* ********** */ - + for(i=0; i<ja3.num_ssl_extension; i++) ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", (i > 0) ? "-" : "", ja3.ssl_extension[i]); - + ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ","); - + /* ********** */ - + for(i=0; i<ja3.num_elliptic_curve; i++) ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", (i > 0) ? "-" : "", ja3.elliptic_curve[i]); - + ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ","); - + for(i=0; i<ja3.num_elliptic_curve_point_format; i++) ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", (i > 0) ? "-" : "", ja3.elliptic_curve_point_format[i]); @@ -781,7 +793,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, printf("[JA3] Client: %s \n", flow->protos.stun_ssl.ssl.ja3_client); #endif } - + return(2 /* Client Certificate */); } } diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c index cf03ddaec..3e2e037f2 100644 --- a/src/lib/protocols/stun.c +++ b/src/lib/protocols/stun.c @@ -81,7 +81,9 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * msg_type, payload_length, flow->protos.stun_ssl.stun.num_binding_requests); */ - if(((payload[0] == 0x80) && ((msg_len+20) <= payload_length)) /* WhatsApp Voice */) { + if(((payload[0] == 0x80) + && (payload_length < 512) + && ((msg_len+20) <= payload_length)) /* WhatsApp Voice */) { *is_whatsapp = 1; return NDPI_IS_STUN; /* This is WhatsApp Voice */ } else if((payload[0] == 0x90) |