diff options
-rw-r--r-- | example/reader_util.c | 4 | ||||
-rw-r--r-- | src/include/ndpi_main.h | 5 | ||||
-rw-r--r-- | src/include/ndpi_typedefs.h | 2 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 17 | ||||
-rw-r--r-- | src/lib/ndpi_utils.c | 93 | ||||
-rw-r--r-- | src/lib/protocols/tls.c | 51 |
6 files changed, 108 insertions, 64 deletions
diff --git a/example/reader_util.c b/example/reader_util.c index f4f35da1a..bc7444f31 100644 --- a/example/reader_util.c +++ b/example/reader_util.c @@ -1472,8 +1472,8 @@ static struct ndpi_proto packet_processing(struct ndpi_workflow * workflow, /* Copy packets entropy if num packets count == 10 */ ndpi_clear_entropy_stats(flow); - - if(!flow->has_human_readeable_strings) { + + if((human_readeable_string_len != 0) && (!flow->has_human_readeable_strings)) { u_int8_t skip = 0; if((proto == IPPROTO_TCP) diff --git a/src/include/ndpi_main.h b/src/include/ndpi_main.h index 3369e979a..0cd41d2b8 100644 --- a/src/include/ndpi_main.h +++ b/src/include/ndpi_main.h @@ -131,7 +131,7 @@ extern "C" { extern u_int8_t ndpi_is_proto(ndpi_protocol proto, u_int16_t p); extern u_int16_t ndpi_get_lower_proto(ndpi_protocol p); - + #ifdef NDPI_ENABLE_DEBUG_MESSAGES void ndpi_debug_get_last_log_function_line(struct ndpi_detection_module_struct *ndpi_struct, const char **file, const char **func, u_int32_t * line); @@ -155,6 +155,9 @@ extern "C" { struct ndpi_flow_struct *flow, ndpi_risk_enum r); int ndpi_is_printable_string(char const * const str, size_t len); float ndpi_calculate_entropy(u_int8_t const * const buf, size_t len); + void load_common_alpns(struct ndpi_detection_module_struct *ndpi_str); + u_int8_t is_a_common_alpn(struct ndpi_detection_module_struct *ndpi_str, + const char *alpn_to_check, u_int alpn_to_check_len); #ifdef __cplusplus } #endif diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 486af76ed..68745a69a 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -1161,7 +1161,7 @@ struct ndpi_detection_module_struct { subprotocol_automa, /* Used for HTTP subprotocol_detection */ risky_domain_automa, tls_cert_subject_automa, malicious_ja3_automa, malicious_sha1_automa, - host_risk_mask_automa; + host_risk_mask_automa, common_alpns_automa; /* IMPORTANT: please update ndpi_finalize_initialization() whenever you add a new automa */ void *ip_risk_mask_ptree; diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index d202b05e9..aa3934a0f 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -2345,6 +2345,8 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs ndpi_str->host_automa.ac_automa = ac_automata_init(ac_domain_match_handler); ndpi_str->content_automa.ac_automa = ac_automata_init(ac_domain_match_handler); ndpi_str->host_risk_mask_automa.ac_automa = ac_automata_init(ac_domain_match_handler); + ndpi_str->common_alpns_automa.ac_automa = ac_automata_init(ac_domain_match_handler); + load_common_alpns(ndpi_str); ndpi_str->tls_cert_subject_automa.ac_automa = ac_automata_init(NULL); ndpi_str->malicious_ja3_automa.ac_automa = NULL; /* Initialized on demand */ ndpi_str->malicious_sha1_automa.ac_automa = NULL; /* Initialized on demand */ @@ -2380,6 +2382,9 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs if(ndpi_str->host_risk_mask_automa.ac_automa) ac_automata_feature(ndpi_str->host_risk_mask_automa.ac_automa,AC_FEATURE_LC); + if(ndpi_str->common_alpns_automa.ac_automa) + ac_automata_feature(ndpi_str->common_alpns_automa.ac_automa,AC_FEATURE_LC); + /* ahocorasick debug */ /* Needed ac_automata_enable_debug(1) for show debug */ if(ndpi_str->host_automa.ac_automa) @@ -2400,6 +2405,9 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs if(ndpi_str->host_risk_mask_automa.ac_automa) ac_automata_name(ndpi_str->host_risk_mask_automa.ac_automa,"content",AC_FEATURE_DEBUG); + if(ndpi_str->common_alpns_automa.ac_automa) + ac_automata_name(ndpi_str->common_alpns_automa.ac_automa,"content",AC_FEATURE_DEBUG); + if((ndpi_str->custom_categories.ipAddresses == NULL) || (ndpi_str->custom_categories.ipAddresses_shadow == NULL)) { NDPI_LOG_ERR(ndpi_str, "[NDPI] Error allocating Patricia trees\n"); return(NULL); @@ -2449,6 +2457,10 @@ void ndpi_finalize_initialization(struct ndpi_detection_module_struct *ndpi_str) automa = &ndpi_str->host_risk_mask_automa; break; + case 6: + automa = &ndpi_str->common_alpns_automa; + break; + default: ndpi_str->ac_automa_finalized = 1; return; @@ -2728,6 +2740,10 @@ void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_str) { ac_automata_release((AC_AUTOMATA_t *) ndpi_str->host_risk_mask_automa.ac_automa, 1 /* free patterns strings memory */); + if(ndpi_str->common_alpns_automa.ac_automa != NULL) + ac_automata_release((AC_AUTOMATA_t *) ndpi_str->common_alpns_automa.ac_automa, + 1 /* free patterns strings memory */); + #ifdef CUSTOM_NDPI_PROTOCOLS #include "../../../nDPI-custom/ndpi_exit_detection_module.c" #endif @@ -2928,7 +2944,6 @@ int ndpi_add_ip_risk_mask(struct ndpi_detection_module_struct *ndpi_str, int ndpi_add_host_risk_mask(struct ndpi_detection_module_struct *ndpi_str, char *host, ndpi_risk mask) { - /* host_risk_mask_automa */ AC_PATTERN_t ac_pattern; AC_ERROR_t rc; u_int len; diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c index 80342b32d..3ed2592b2 100644 --- a/src/lib/ndpi_utils.c +++ b/src/lib/ndpi_utils.c @@ -1767,7 +1767,7 @@ const char* ndpi_risk2str(ndpi_risk_enum risk) { case NDPI_TLS_UNCOMMON_ALPN: return("Uncommon TLS ALPN"); - + case NDPI_TLS_CERT_VALIDITY_TOO_LONG: return("TLS certificate validity longer than 13 months"); @@ -1787,7 +1787,7 @@ const char* ndpi_severity2str(ndpi_risk_severity s) { case NDPI_RISK_LOW: return("Low"); break; - + case NDPI_RISK_MEDIUM: return("Medium"); break; @@ -1813,16 +1813,16 @@ u_int16_t ndpi_risk2score(ndpi_risk risk, u_int32_t i; *client_score = *server_score = 0; /* Reset values */ - + if(risk == 0) return(0); - + for(i = 0; i < NDPI_MAX_RISK; i++) { ndpi_risk_enum r = (ndpi_risk_enum)i; if(NDPI_ISSET_BIT(risk, r)) { ndpi_risk_info *info = ndpi_risk2severity(r); u_int16_t val = 0, client_score_val; - + switch(info->severity) { case NDPI_RISK_LOW: val = NDPI_SCORE_RISK_LOW; @@ -2016,7 +2016,7 @@ int ndpi_hash_add_entry(ndpi_str_hash *h, char *key, u_int8_t key_len, u_int8_t if(e == NULL) return(-2); - + if((e->key = (char*)ndpi_malloc(key_len)) == NULL) return(-3); @@ -2043,7 +2043,7 @@ static u_int64_t ndpi_host_ip_risk_ptree_match(struct ndpi_detection_module_stru if(node) return(node->value.u.uv64); - else + else return((u_int64_t)-1); } @@ -2052,7 +2052,7 @@ static u_int64_t ndpi_host_ip_risk_ptree_match(struct ndpi_detection_module_stru static void ndpi_handle_risk_exceptions(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow) { char *host; - + if(flow->risk == 0) return; /* Nothing to do */ host = ndpi_get_flow_name(flow); @@ -2061,14 +2061,14 @@ static void ndpi_handle_risk_exceptions(struct ndpi_detection_module_struct *ndp if(host && (host[0] != '\0')) { /* Check host exception */ ndpi_automa *automa = &ndpi_str->host_risk_mask_automa; - + if(automa->ac_automa) { AC_TEXT_t ac_input_text; AC_REP_t match; - + ac_input_text.astring = host, ac_input_text.length = strlen(host); ac_input_text.option = 0; - + if(ac_automata_search(automa->ac_automa, &ac_input_text, &match) > 0) flow->risk &= match.number64; } @@ -2081,11 +2081,11 @@ static void ndpi_handle_risk_exceptions(struct ndpi_detection_module_struct *ndp /* TODO: add IPv6 support */ if(!flow->ip_risk_mask_evaluated) { flow->host_risk_mask = (u_int64_t)-1; /* No mask */ - + if(flow->packet.iph) { struct ndpi_packet_struct *packet = &flow->packet; struct in_addr pin; - + pin.s_addr = packet->iph->saddr; flow->host_risk_mask &= ndpi_host_ip_risk_ptree_match(ndpi_str, &pin); @@ -2161,13 +2161,74 @@ float ndpi_calculate_entropy(u_int8_t const * const buf, size_t len) char* ndpi_get_flow_name(struct ndpi_flow_struct *flow) { if(!flow) goto no_flow_info; - + if(flow->host_server_name[0] != '\0') return((char*)flow->host_server_name); - + if(flow->protos.tls_quic_stun.tls_quic.client_requested_server_name[0] != '\0') return(flow->protos.tls_quic_stun.tls_quic.client_requested_server_name); - + no_flow_info: return((char*)""); } + +/* ******************************************* */ + +void load_common_alpns(struct ndpi_detection_module_struct *ndpi_str) { + /* see: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml */ + const char* const common_alpns[] = { + "http/0.9", "http/1.0", "http/1.1", + "spdy/1", "spdy/2", "spdy/3", "spdy/3.1", + "stun.turn", "stun.nat-discovery", + "h2", "h2c", "h2-16", "h2-15", "h2-14", "h2-fb", + "webrtc", "c-webrtc", + "ftp", "imap", "pop3", "managesieve", "coap", + "xmpp-client", "xmpp-server", + "acme-tls/1", + "mqtt", "dot", "ntske/1", "sunrpc", + "h3", + "smb", + "irc", + + /* QUIC ALPNs */ + "h3-T051", "h3-T050", + "h3-32", "h3-30", "h3-29", "h3-28", "h3-27", "h3-24", "h3-22", + "hq-30", "hq-29", "hq-28", "hq-27", + "h3-fb-05", "h1q-fb", + "doq-i00", + + NULL /* end */ + }; + u_int i; + + for(i=0; common_alpns[i] != NULL; i++) { + AC_PATTERN_t ac_pattern; + + memset(&ac_pattern, 0, sizeof(ac_pattern)); + ac_pattern.astring = ndpi_strdup((char*)common_alpns[i]); + ac_pattern.length = strlen(common_alpns[i]); + + if(ac_automata_add(ndpi_str->common_alpns_automa.ac_automa, &ac_pattern) != ACERR_SUCCESS) + printf("%s(): unable to add %s\n", __FUNCTION__, common_alpns[i]); + } +} + +/* ******************************************* */ + +u_int8_t is_a_common_alpn(struct ndpi_detection_module_struct *ndpi_str, + const char *alpn_to_check, u_int alpn_to_check_len) { + ndpi_automa *automa = &ndpi_str->common_alpns_automa; + + if(automa->ac_automa) { + AC_TEXT_t ac_input_text; + AC_REP_t match; + + ac_input_text.astring = (char*)alpn_to_check, ac_input_text.length = alpn_to_check_len; + ac_input_text.option = 0; + + if(ac_automata_search(automa->ac_automa, &ac_input_text, &match) > 0) + return(1); + } + + return(0); +} diff --git a/src/lib/protocols/tls.c b/src/lib/protocols/tls.c index cec43c890..38f1ffbca 100644 --- a/src/lib/protocols/tls.c +++ b/src/lib/protocols/tls.c @@ -464,7 +464,7 @@ static void processCertificateElements(struct ndpi_detection_module_struct *ndpi if (flow->protos.tls_quic_stun.tls_quic.notBefore > TLS_LIMIT_DATE) if((flow->protos.tls_quic_stun.tls_quic.notAfter-flow->protos.tls_quic_stun.tls_quic.notBefore) > TLS_THRESHOLD) ndpi_set_risk(ndpi_struct, flow, NDPI_TLS_CERT_VALIDITY_TOO_LONG); /* Certificate validity longer than 13 months*/ - + if((time_sec < flow->protos.tls_quic_stun.tls_quic.notBefore) || (time_sec > flow->protos.tls_quic_stun.tls_quic.notAfter)) ndpi_set_risk(ndpi_struct, flow, NDPI_TLS_CERTIFICATE_EXPIRED); /* Certificate expired */ @@ -1064,54 +1064,19 @@ static void tlsInitExtraPacketProcessing(struct ndpi_detection_module_struct *nd static void tlsCheckUncommonALPN(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { - /* TODO: make search more efficient instead of a linear scan */ - /* see: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml */ - static char const * const common_alpns[] = { - "http/0.9", "http/1.0", "http/1.1", - "spdy/1", "spdy/2", "spdy/3", "spdy/3.1", - "stun.turn", "stun.nat-discovery", - "h2", "h2c", "h2-16", "h2-15", "h2-14", "h2-fb", - "webrtc", "c-webrtc", - "ftp", "imap", "pop3", "managesieve", "coap", - "xmpp-client", "xmpp-server", - "acme-tls/1", - "mqtt", "dot", "ntske/1", "sunrpc", - "h3", - "smb", - "irc", - - /* QUIC ALPNs */ - "h3-T051", "h3-T050", - "h3-32", "h3-30", "h3-29", "h3-28", "h3-27", "h3-24", "h3-22", - "hq-30", "hq-29", "hq-28", "hq-27", - "h3-fb-05", "h1q-fb", - "doq-i00" - }; - char * alpn_start = flow->protos.tls_quic_stun.tls_quic.alpn; char * comma_or_nul = alpn_start; do { + int alpn_len; + comma_or_nul = strchr(comma_or_nul, ','); - if (comma_or_nul == NULL) - { - comma_or_nul = alpn_start + strlen(alpn_start); - } - int alpn_found = 0; - int alpn_len = comma_or_nul - alpn_start; - char const * const alpn = alpn_start; - for (size_t i = 0; i < sizeof(common_alpns)/sizeof(common_alpns[0]); ++i) - { - if (strlen(common_alpns[i]) == alpn_len && - strncmp(alpn, common_alpns[i], alpn_len) == 0) - { - alpn_found = 1; - break; - } - } + if(comma_or_nul == NULL) + comma_or_nul = alpn_start + strlen(alpn_start); - if (alpn_found == 0) - { + alpn_len = comma_or_nul - alpn_start; + + if(!is_a_common_alpn(ndpi_struct, alpn_start, alpn_len)) { #ifdef DEBUG_TLS printf("TLS uncommon ALPN found: %.*s\n", alpn_len, alpn); #endif |