aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorLuca Deri <deri@ntop.org>2022-01-13 19:03:17 +0100
committerLuca Deri <deri@ntop.org>2022-01-13 19:06:21 +0100
commit406ac7e8c825ba05bc6371ed3088226bdef21b02 (patch)
treeb759ec5050b56aa561874ce214ca7fddd6c1567f /src/lib
parentdc60cd09c49f52d2eba6c169f973f757695e4f5a (diff)
Added the ability to specify trusted issueDN often used in companies to self-signed certificates
This allows to avoid triggering alerts for trusted albeit private certificate issuers. Extended the example/protos.txt with the new syntax for specifying trusted issueDN. Example: trusted_issuer_dn:"CN=813845657003339838, O=Code42, OU=TEST, ST=MN, C=US"
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ndpi_main.c126
-rw-r--r--src/lib/protocols/tls.c20
2 files changed, 106 insertions, 40 deletions
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index cbd875eef..8d88b5c2e 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -2368,7 +2368,7 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs
ndpi_init_ptree_ipv4(ndpi_str, ndpi_str->protocols_ptree, ndpi_protocol_microsoft_azure_protocol_list,
prefs & ndpi_dont_load_tor_hosts); /* Microsoft Azure */
}
-
+
ndpi_str->ip_risk_mask_ptree = ndpi_patricia_new(32 /* IPv4 */);
NDPI_BITMASK_RESET(ndpi_str->detection_bitmask);
@@ -2397,6 +2397,7 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs
ndpi_str->malicious_ja3_automa.ac_automa = NULL; /* Initialized on demand */
ndpi_str->malicious_sha1_automa.ac_automa = NULL; /* Initialized on demand */
ndpi_str->risky_domain_automa.ac_automa = NULL; /* Initialized on demand */
+ ndpi_str->trusted_issuer_dn = NULL;
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,
@@ -2779,6 +2780,19 @@ void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_str) {
ac_automata_release((AC_AUTOMATA_t *) ndpi_str->common_alpns_automa.ac_automa,
1 /* free patterns strings memory */);
+ if(ndpi_str->trusted_issuer_dn) {
+ ndpi_list *head = ndpi_str->trusted_issuer_dn;
+
+ while(head != NULL) {
+ ndpi_list *next;
+
+ if(head->value) ndpi_free(head->value);
+ next = head->next;
+ ndpi_free(head);
+ head = next;
+ }
+ }
+
#ifdef CUSTOM_NDPI_PROTOCOLS
#include "../../../nDPI-custom/ndpi_exit_detection_module.c"
#endif
@@ -3042,6 +3056,40 @@ int ndpi_add_host_risk_mask(struct ndpi_detection_module_struct *ndpi_str,
/* ******************************************************************** */
+int ndpi_add_trusted_issuer_dn(struct ndpi_detection_module_struct *ndpi_str, char *dn) {
+ ndpi_list *head;
+
+ if(dn == NULL)
+ return(-1);
+ else
+ head = (ndpi_list*)ndpi_malloc(sizeof(ndpi_list));
+
+ if(head == NULL) return(-2);
+
+ if(dn[0] == '"') {
+ char buf[128], *quote;
+
+ snprintf(buf, sizeof(buf), "%s", &dn[1]);
+
+ if((quote = strchr(buf, '"')) != NULL)
+ quote[0] = '\0';
+
+ head->value = strdup(buf);
+ } else
+ head->value = strdup(dn);
+
+ if(head->value == NULL) {
+ ndpi_free(head);
+ return(-3);
+ }
+
+ head->next = ndpi_str->trusted_issuer_dn;
+ ndpi_str->trusted_issuer_dn = head;
+
+ return(0);
+}
+/* ******************************************************************** */
+
int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str, char *rule, u_int8_t do_add) {
char *at, *proto, *elem;
ndpi_proto_defaults_t *def;
@@ -3060,13 +3108,15 @@ int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str, char *rule,
return(-1);
}
- key = strtok(NULL, "=");
+ if(!strcmp(rule_type, "trusted_issuer_dn"))
+ return(ndpi_add_trusted_issuer_dn(ndpi_str, strtok(NULL, ":")));
+ key = strtok(NULL, "=");
if(key) {
- char *mask = strtok(NULL, "=");
+ char *value = strtok(NULL, "=");
- if(mask) {
- ndpi_risk risk_mask = (ndpi_risk)atoll(mask);
+ if(value) {
+ ndpi_risk risk_mask = (ndpi_risk)atoll(value);
if(!strcmp(rule_type, "ip_risk_mask")) {
return(ndpi_add_ip_risk_mask(ndpi_str, key, risk_mask));
@@ -3449,7 +3499,7 @@ int ndpi_load_malicious_sha1_file(struct ndpi_detection_module_struct *ndpi_str,
int ndpi_load_protocols_file(struct ndpi_detection_module_struct *ndpi_str, const char *path) {
FILE *fd;
char *buffer, *old_buffer;
- int chunk_len = 512, buffer_len = chunk_len, old_buffer_len;
+ int chunk_len = 1024, buffer_len = chunk_len, old_buffer_len;
int i, rc = -1;
fd = fopen(path, "r");
@@ -4541,7 +4591,7 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str,
flow->is_ipv6 = (packet->iphv6 != NULL);
if(flow->is_ipv6 == 0)
flow->saddr = packet->iph->saddr, flow->daddr = packet->iph->daddr; /* See (*#*) */
-
+
flow->last_packet_time_ms = packet->current_time_ms;
packet->packet_lines_parsed_complete = 0;
@@ -4554,7 +4604,7 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str,
if(tcph != NULL) {
flow->sport = tcph->source, flow->dport = tcph->dest; /* (*#*) */
-
+
if(!ndpi_str->direction_detect_disable)
packet->packet_direction = (ntohs(tcph->source) < ntohs(tcph->dest)) ? 1 : 0;
@@ -4616,7 +4666,7 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str,
}
} else if(udph != NULL) {
flow->sport = udph->source, flow->dport = udph->dest; /* (*#*) */
-
+
if(!ndpi_str->direction_detect_disable)
packet->packet_direction = (htons(udph->source) < htons(udph->dest)) ? 1 : 0;
}
@@ -4878,7 +4928,7 @@ static void ndpi_reconcile_protocols(struct ndpi_detection_module_struct *ndpi_s
case NDPI_PROTOCOL_RDP:
ndpi_set_risk(ndpi_str, flow, NDPI_DESKTOP_OR_FILE_SHARING_SESSION); /* Remote assistance */
break;
-
+
case NDPI_PROTOCOL_ANYDESK:
if(flow->l4_proto == IPPROTO_TCP) /* TCP only */
ndpi_set_risk(ndpi_str, flow, NDPI_DESKTOP_OR_FILE_SHARING_SESSION); /* Remote assistance */
@@ -4922,7 +4972,7 @@ int ndpi_search_into_bittorrent_cache(struct ndpi_detection_module_struct *ndpi_
if(flow && flow->bt_check_performed /* Do the check once */)
return(0);
-
+
if(ndpi_struct->bittorrent_cache) {
u_int16_t cached_proto;
u_int8_t found = 0;
@@ -4930,7 +4980,7 @@ int ndpi_search_into_bittorrent_cache(struct ndpi_detection_module_struct *ndpi_
if(flow)
flow->bt_check_performed = 1;
-
+
/* Check cached communications */
key1 = ndpi_bittorrent_hash_funct(saddr, sport), key2 = ndpi_bittorrent_hash_funct(daddr, dport);
@@ -5111,7 +5161,7 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st
ret.app_protocol = NDPI_PROTOCOL_BITTORRENT;
}
}
-
+
if(ret.app_protocol != NDPI_PROTOCOL_UNKNOWN) {
*protocol_was_guessed = 1;
ndpi_fill_protocol_category(ndpi_str, flow, &ret);
@@ -5908,7 +5958,7 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_str,
packet->server_line.len = packet->line[packet->parsed_lines].len - NDPI_STATICSTRING_LEN("Server:");
}
packet->http_num_headers++;
- } else
+ } else
/* "Host:" header line in HTTP request */
if(packet->line[packet->parsed_lines].len > 6 &&
strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Host:", 5) == 0) {
@@ -5921,7 +5971,7 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_str,
packet->host_line.len = packet->line[packet->parsed_lines].len - 5;
}
packet->http_num_headers++;
- } else
+ } else
/* "X-Forwarded-For:" header line in HTTP request. Commonly used for HTTP proxies. */
if(packet->line[packet->parsed_lines].len > 17 &&
strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "X-Forwarded-For:", 16) == 0) {
@@ -5934,7 +5984,7 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_str,
packet->forwarded_line.len = packet->line[packet->parsed_lines].len - 16;
}
packet->http_num_headers++;
- } else
+ } else
/* "Authorization:" header line in HTTP. */
if(packet->line[packet->parsed_lines].len > 15 &&
@@ -5960,63 +6010,63 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_str,
packet->referer_line.ptr = &packet->line[packet->parsed_lines].ptr[9];
packet->referer_line.len = packet->line[packet->parsed_lines].len - 9;
packet->http_num_headers++;
- } else
+ } else
/* "User-Agent:" header line in HTTP request. */
if(packet->line[packet->parsed_lines].len > 12 &&
strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "User-agent: ", 12) == 0) {
packet->user_agent_line.ptr = &packet->line[packet->parsed_lines].ptr[12];
packet->user_agent_line.len = packet->line[packet->parsed_lines].len - 12;
packet->http_num_headers++;
- } else
+ } else
/* "Content-Encoding:" header line in HTTP response (and request?). */
if(packet->line[packet->parsed_lines].len > 18 &&
strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Encoding: ", 18) == 0) {
packet->http_encoding.ptr = &packet->line[packet->parsed_lines].ptr[18];
packet->http_encoding.len = packet->line[packet->parsed_lines].len - 18;
packet->http_num_headers++;
- } else
+ } else
/* "Transfer-Encoding:" header line in HTTP. */
if(packet->line[packet->parsed_lines].len > 19 &&
strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Transfer-Encoding: ", 19) == 0) {
packet->http_transfer_encoding.ptr = &packet->line[packet->parsed_lines].ptr[19];
packet->http_transfer_encoding.len = packet->line[packet->parsed_lines].len - 19;
packet->http_num_headers++;
- } else
+ } else
/* "Content-Length:" header line in HTTP. */
if(packet->line[packet->parsed_lines].len > 16 &&
strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "content-length: ", 16) == 0) {
packet->http_contentlen.ptr = &packet->line[packet->parsed_lines].ptr[16];
packet->http_contentlen.len = packet->line[packet->parsed_lines].len - 16;
packet->http_num_headers++;
- } else
+ } else
/* "Content-Disposition"*/
if(packet->line[packet->parsed_lines].len > 21 &&
((strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Disposition: ", 21) == 0))) {
packet->content_disposition_line.ptr = &packet->line[packet->parsed_lines].ptr[21];
packet->content_disposition_line.len = packet->line[packet->parsed_lines].len - 21;
packet->http_num_headers++;
- } else
+ } else
/* "Cookie:" header line in HTTP. */
if(packet->line[packet->parsed_lines].len > 8 &&
strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Cookie: ", 8) == 0) {
packet->http_cookie.ptr = &packet->line[packet->parsed_lines].ptr[8];
packet->http_cookie.len = packet->line[packet->parsed_lines].len - 8;
packet->http_num_headers++;
- } else
+ } else
/* "Origin:" header line in HTTP. */
if(packet->line[packet->parsed_lines].len > 8 &&
strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Origin: ", 8) == 0) {
packet->http_origin.ptr = &packet->line[packet->parsed_lines].ptr[8];
packet->http_origin.len = packet->line[packet->parsed_lines].len - 8;
packet->http_num_headers++;
- } else
+ } else
/* "X-Session-Type:" header line in HTTP. */
if(packet->line[packet->parsed_lines].len > 16 &&
strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "X-Session-Type: ", 16) == 0) {
packet->http_x_session_type.ptr = &packet->line[packet->parsed_lines].ptr[16];
packet->http_x_session_type.len = packet->line[packet->parsed_lines].len - 16;
packet->http_num_headers++;
- } else
+ } else
/* Identification and counting of other HTTP headers.
* We consider the most common headers, but there are many others,
* which can be seen at references below:
@@ -6046,7 +6096,7 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_str,
"Upgrade-Insecure-Requests: ", 27) == 0)) {
/* Just count. In the future, if needed, this if can be splited to parse these headers */
packet->http_num_headers++;
- } else
+ } else
/* "Content-Type:" header line in HTTP. */
if(packet->line[packet->parsed_lines].len > 14 &&
strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Type: ", 14) == 0 ) {
@@ -6057,7 +6107,7 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_str,
packet->content_line.len--, packet->content_line.ptr++;
packet->http_num_headers++;
- } else
+ } else
/* "Content-Type:" header line in HTTP AGAIN. Probably a bogus response without space after ":" */
if((packet->content_line.len == 0) && (packet->line[packet->parsed_lines].len > 13) &&
@@ -6065,8 +6115,8 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_str,
packet->content_line.ptr = &packet->line[packet->parsed_lines].ptr[13];
packet->content_line.len = packet->line[packet->parsed_lines].len - 13;
packet->http_num_headers++;
- }
-
+ }
+
if(packet->content_line.len > 0) {
/* application/json; charset=utf-8 */
char separator[] = {';', '\r', '\0'};
@@ -6538,7 +6588,7 @@ ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct
#ifdef BITTORRENT_CACHE_DEBUG
printf("[%s:%u] Guessed %u.%u\n", __FILE__, __LINE__, ret.master_protocol, ret.app_protocol);
#endif
-
+
ret.category = ndpi_get_proto_category(ndpi_str, ret);
return(ret);
}
@@ -6558,7 +6608,7 @@ ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct
#ifdef BITTORRENT_CACHE_DEBUG
printf("[%s:%u] Guessed %u.%u\n", __FILE__, __LINE__, ret.master_protocol, ret.app_protocol);
#endif
-
+
ret.category = ndpi_get_proto_category(ndpi_str, ret);
return(ret);
}
@@ -6575,7 +6625,7 @@ ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct
#ifdef BITTORRENT_CACHE_DEBUG
printf("[%s:%u] Guessed %u.%u\n", __FILE__, __LINE__, ret.master_protocol, ret.app_protocol);
#endif
-
+
return(ret);
}
@@ -6596,7 +6646,7 @@ ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct
#ifdef BITTORRENT_CACHE_DEBUG
printf("[%s:%u] Guessed %u.%u\n", __FILE__, __LINE__, ret.master_protocol, ret.app_protocol);
#endif
-
+
return(ret);
}
@@ -6897,7 +6947,7 @@ void ndpi_generate_options(u_int opt) {
{
for(i = 1 /* Skip no risk */; i < NDPI_MAX_RISK; i++) {
ndpi_risk_enum r = (ndpi_risk_enum)i;
-
+
printf(" <Option%d value=\"%u\">%s</Option%d>\n",
i, i, ndpi_risk2str(r), i);
}
@@ -7580,7 +7630,7 @@ u_int8_t ndpi_ends_with(char *str, char *ends) {
u_int8_t ends_len = strlen(ends);
u_int8_t rc;
-
+
if(str_len < ends_len) return(0);
rc = (strncmp(&str[str_len-ends_len], ends, ends_len) != 0) ? 0 : 1;
@@ -7631,7 +7681,7 @@ int ndpi_check_dga_name(struct ndpi_detection_module_struct *ndpi_str,
if(rc) {
if(flow)
- ndpi_set_risk(ndpi_str, flow, NDPI_SUSPICIOUS_DGA_DOMAIN);
+ ndpi_set_risk(ndpi_str, flow, NDPI_SUSPICIOUS_DGA_DOMAIN);
}
return(rc);
@@ -7640,7 +7690,7 @@ int ndpi_check_dga_name(struct ndpi_detection_module_struct *ndpi_str,
u_int8_t max_num_char_repetitions = 0, last_char = 0, num_char_repetitions = 0, num_dots = 0, num_trigram_dots = 0;
u_int8_t max_domain_element_len = 0, curr_domain_element_len = 0, first_element_is_numeric = 1;
ndpi_protocol_match_result ret_match;
-
+
if((!name)
|| (strchr(name, '_') != NULL)
|| (ndpi_ends_with(name, "in-addr.arpa"))
@@ -7665,7 +7715,7 @@ int ndpi_check_dga_name(struct ndpi_detection_module_struct *ndpi_str,
if(strcmp(inet_ntoa(ip_addr), name) == 0)
return(0); /* Ignore numeric IPs */
}
-
+
if(strncmp(name, "www.", 4) == 0)
name = &name[4];
diff --git a/src/lib/protocols/tls.c b/src/lib/protocols/tls.c
index 4815275d4..b83505cd5 100644
--- a/src/lib/protocols/tls.c
+++ b/src/lib/protocols/tls.c
@@ -469,7 +469,7 @@ static void processCertificateElements(struct ndpi_detection_module_struct *ndpi
if(flow->protos.tls_quic.notBefore > TLS_LIMIT_DATE)
if((flow->protos.tls_quic.notAfter-flow->protos.tls_quic.notBefore) > TLS_THRESHOLD)
- ndpi_set_risk(ndpi_struct, flow, NDPI_TLS_CERT_VALIDITY_TOO_LONG); /* Certificate validity longer than 13 months*/
+ 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.notBefore)
|| (time_sec > flow->protos.tls_quic.notAfter))
@@ -652,8 +652,24 @@ static void processCertificateElements(struct ndpi_detection_module_struct *ndpi
}
if(flow->protos.tls_quic.subjectDN && flow->protos.tls_quic.issuerDN
- && (!strcmp(flow->protos.tls_quic.subjectDN, flow->protos.tls_quic.issuerDN)))
+ && (!strcmp(flow->protos.tls_quic.subjectDN, flow->protos.tls_quic.issuerDN))) {
+ /* Last resort: we check if this is a trusted issuerDN */
+ ndpi_list *head = ndpi_struct->trusted_issuer_dn;
+
+ while(head != NULL) {
+#if DEBUG_TLS
+ printf("TLS] %s() issuerDN %s / %s\n", __FUNCTION__,
+ flow->protos.tls_quic.issuerDN, head->value);
+#endif
+
+ if(strcmp(flow->protos.tls_quic.issuerDN, head->value) == 0)
+ return; /* This is a trusted DN */
+ else
+ head = head->next;
+ }
+
ndpi_set_risk(ndpi_struct, flow, NDPI_TLS_SELFSIGNED_CERTIFICATE);
+ }
#if DEBUG_TLS
printf("[TLS] %s() SubjectDN [%s]\n", __FUNCTION__, rdnSeqBuf);