aboutsummaryrefslogtreecommitdiff
path: root/src/lib/ndpi_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/ndpi_main.c')
-rw-r--r--src/lib/ndpi_main.c201
1 files changed, 139 insertions, 62 deletions
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index e18c220a5..7a954a710 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -423,7 +423,8 @@ static const char* categories[] = {
"Malware",
"Advertisement",
"Banned_Site",
- "Site_Unavailable"
+ "Site_Unavailable",
+ "Allowed_Site",
};
/* ****************************************** */
@@ -545,7 +546,7 @@ ndpi_port_range * ndpi_build_default_ports_range(ndpi_port_range *ports,
ports[i].port_low = portB_low, ports[i].port_high = portB_high; i++;
ports[i].port_low = portC_low, ports[i].port_high = portC_high; i++;
ports[i].port_low = portD_low, ports[i].port_high = portD_high; i++;
- ports[i].port_low = portE_low, ports[i].port_high = portE_high; i++;
+ ports[i].port_low = portE_low, ports[i].port_high = portE_high;
return(ports);
}
@@ -564,7 +565,7 @@ ndpi_port_range * ndpi_build_default_ports(ndpi_port_range *ports,
ports[i].port_low = portB, ports[i].port_high = portB; i++;
ports[i].port_low = portC, ports[i].port_high = portC; i++;
ports[i].port_low = portD, ports[i].port_high = portD; i++;
- ports[i].port_low = portE, ports[i].port_high = portE; i++;
+ ports[i].port_low = portE, ports[i].port_high = portE;
return(ports);
}
@@ -718,8 +719,7 @@ static void addDefaultPort(struct ndpi_detection_module_struct *ndpi_mod,
ndpi_proto_defaults_t *def,
u_int8_t customUserProto,
ndpi_default_ports_tree_node_t **root,
- const char *_func, int _line)
-{
+ const char *_func, int _line) {
ndpi_default_ports_tree_node_t *ret;
u_int16_t port;
@@ -999,6 +999,7 @@ static void free_hyperscan_memory(struct hs *h) {
if(h) {
hs_free_scratch(h->scratch);
hs_free_database(h->database);
+ free(h);
}
}
@@ -2174,16 +2175,6 @@ u_int16_t ndpi_network_ptree_match(struct ndpi_detection_module_struct *ndpi_str
/* ******************************************* */
-/* u_int16_t ndpi_host_ptree_match(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t host /\* network byte order *\/) { */
-/* struct in_addr pin; */
-
-/* pin.s_addr = host; */
-
-/* return(ndpi_network_ptree_match(ndpi_struct, &pin)); */
-/* } */
-
-/* ******************************************* */
-
#if 0
static u_int8_t tor_ptree_match(struct ndpi_detection_module_struct *ndpi_struct, struct in_addr *pin) {
return((ndpi_network_ptree_match(ndpi_struct, pin) == NDPI_PROTOCOL_TOR) ? 1 : 0);
@@ -2380,7 +2371,7 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(void) {
for(i=0; i<NUM_CUSTOM_CATEGORIES; i++)
snprintf(ndpi_str->custom_category_labels[i],
- CUSTOM_CATEGORY_LABEL_LEN, "User custom category %u", i+1);
+ CUSTOM_CATEGORY_LABEL_LEN, "User custom category %u", (unsigned int)(i+1));
return ndpi_str;
}
@@ -2698,8 +2689,8 @@ u_int16_t ndpi_guess_protocol_id(struct ndpi_detection_module_struct *ndpi_struc
struct ndpi_flow_struct *flow,
u_int8_t proto, u_int16_t sport, u_int16_t dport,
u_int8_t *user_defined_proto) {
-
*user_defined_proto = 0; /* Default */
+
if(sport && dport) {
ndpi_default_ports_tree_node_t *found = ndpi_get_guessed_protocol_id(ndpi_struct, proto, sport, dport);
@@ -2895,12 +2886,18 @@ int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_mod,
Format:
<tcp|udp>:<port>,<tcp|udp>:<port>,.....@<proto>
+ Subprotocols Format:
+ host:"<value>",host:"<value>",.....@<subproto>
+
+ IP based Subprotocols Format (<value> is IP or CIDR):
+ ip:<value>,ip:<value>,.....@<subproto>
+
Example:
tcp:80,tcp:3128@HTTP
udp:139@NETBIOS
*/
-int ndpi_load_protocols_file(struct ndpi_detection_module_struct *ndpi_mod, char* path) {
+int ndpi_load_protocols_file(struct ndpi_detection_module_struct *ndpi_mod, const char* path) {
FILE *fd;
char *buffer, *old_buffer;
int chunk_len = 512, buffer_len = chunk_len, old_buffer_len;
@@ -2909,14 +2906,14 @@ int ndpi_load_protocols_file(struct ndpi_detection_module_struct *ndpi_mod, char
fd = fopen(path, "r");
if(fd == NULL) {
- NDPI_LOG_ERR(ndpi_mod, "Unable to open file %s [%s]", path, strerror(errno));
+ NDPI_LOG_ERR(ndpi_mod, "Unable to open file %s [%s]\n", path, strerror(errno));
goto error;
}
buffer = ndpi_malloc(buffer_len);
if(buffer == NULL) {
- NDPI_LOG_ERR(ndpi_mod, "Memory allocation failure");
+ NDPI_LOG_ERR(ndpi_mod, "Memory allocation failure\n");
goto close_fd;
}
@@ -2933,7 +2930,7 @@ int ndpi_load_protocols_file(struct ndpi_detection_module_struct *ndpi_mod, char
buffer = ndpi_realloc(old_buffer, old_buffer_len, buffer_len);
if(buffer == NULL) {
- NDPI_LOG_ERR(ndpi_mod, "Memory allocation failure");
+ NDPI_LOG_ERR(ndpi_mod, "Memory allocation failure\n");
free(old_buffer);
goto close_fd;
}
@@ -3023,8 +3020,7 @@ void ndpi_set_bitmask_protocol_detection(char * label,
/* ******************************************************************** */
void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *ndpi_struct,
- const NDPI_PROTOCOL_BITMASK * dbm)
-{
+ const NDPI_PROTOCOL_BITMASK * dbm) {
NDPI_PROTOCOL_BITMASK detection_bitmask_local;
NDPI_PROTOCOL_BITMASK *detection_bitmask = &detection_bitmask_local;
u_int32_t a = 0;
@@ -3861,8 +3857,6 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_struct,
const struct ndpi_tcphdr *tcph = packet->tcp;
const struct ndpi_udphdr *udph = flow->packet.udp;
- u_int8_t proxy_enabled = 0;
-
packet->tcp_retransmission = 0, packet->packet_direction = 0;
if(ndpi_struct->direction_detect_disable) {
@@ -3907,7 +3901,7 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_struct,
flow->l4.tcp.seen_ack = 1;
}
if((flow->next_tcp_seq_nr[0] == 0 && flow->next_tcp_seq_nr[1] == 0)
- || (proxy_enabled && (flow->next_tcp_seq_nr[0] == 0 || flow->next_tcp_seq_nr[1] == 0))) {
+ || (flow->next_tcp_seq_nr[0] == 0 || flow->next_tcp_seq_nr[1] == 0)) {
/* initialize tcp sequence counters */
/* the ack flag needs to be set to get valid sequence numbers from the other
* direction. Usually it will catch the second packet syn+ack but it works
@@ -3919,9 +3913,8 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_struct,
if(tcph->ack != 0) {
flow->next_tcp_seq_nr[flow->packet.packet_direction] =
ntohl(tcph->seq) + (tcph->syn ? 1 : packet->payload_packet_len);
- if(!proxy_enabled) {
- flow->next_tcp_seq_nr[1 -flow->packet.packet_direction] = ntohl(tcph->ack_seq);
- }
+
+ flow->next_tcp_seq_nr[1 -flow->packet.packet_direction] = ntohl(tcph->ack_seq);
}
} else if(packet->payload_packet_len > 0) {
/* check tcp sequence counters */
@@ -4185,7 +4178,7 @@ static ndpi_protocol ndpi_process_partial_detection(struct ndpi_detection_module
ret.app_protocol = ret.master_protocol;
ndpi_fill_protocol_category(ndpi_struct, flow, &ret);
-
+
ndpi_int_change_protocol(ndpi_struct, flow, ret.app_protocol, ret.master_protocol);
return(ret);
@@ -4279,6 +4272,20 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st
&& (flow->protos.stun_ssl.stun.num_processed_pkts > 0))
guessed_protocol_id = NDPI_PROTOCOL_STUN;
+
+ if(flow->host_server_name[0] != '\0') {
+ ndpi_protocol_match_result ret_match;
+
+ ndpi_match_host_subprotocol(ndpi_struct, flow,
+ (char *)flow->host_server_name,
+ strlen((const char*)flow->host_server_name),
+ &ret_match,
+ NDPI_PROTOCOL_DNS);
+
+ if(ret_match.protocol_id != NDPI_PROTOCOL_UNKNOWN)
+ guessed_host_protocol_id = ret_match.protocol_id;
+ }
+
ndpi_int_change_protocol(ndpi_struct, flow,
guessed_host_protocol_id,
guessed_protocol_id);
@@ -4433,18 +4440,8 @@ int ndpi_load_hostname_category(struct ndpi_detection_module_struct *ndpi_struct
struct hs_list *h = (struct hs_list*)malloc(sizeof(struct hs_list));
if(h) {
- char tmp[256];
int i, j;
- for(i=0, j=0; (j<sizeof(tmp)) && (name[i] != '\0'); i++) {
- if(name[i] == '.')
- tmp[j++] = '\\';
-
- tmp[j++] = name[i];
- }
-
- tmp[j] = '\0';
-
h->expression = ndpi_strdup(name), h->id = (unsigned int)category;
if(h->expression == NULL) {
free(h);
@@ -4507,7 +4504,8 @@ int ndpi_enable_loaded_categories(struct ndpi_detection_module_struct *ndpi_str)
ndpi_str->custom_categories.hostnames = (struct hs*)malloc(sizeof(struct hs));
if(ndpi_str->custom_categories.hostnames == NULL) {
- free(expressions), free(ids);
+ free(expressions);
+ free(ids);
return(-1); /* Failed */
}
@@ -4599,9 +4597,9 @@ void ndpi_fill_protocol_category(struct ndpi_detection_module_struct *ndpi_struc
ndpi_protocol *ret) {
if(ndpi_struct->custom_categories.categories_loaded) {
if(flow->guessed_header_category != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) {
- flow->category = flow->guessed_header_category;
+ flow->category = ret->category = flow->guessed_header_category;
return;
- }
+ }
if(flow->host_server_name[0] != '\0') {
unsigned long id;
@@ -4652,14 +4650,29 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
flow->num_processed_pkts++;
if(flow->server_id == NULL) flow->server_id = dst; /* Default */
- if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN)
- goto ret_protocols;
+ if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) {
+ /*
+ With SSL we might want to dissect further packets to decode
+ the certificate type for instance
+ */
+ if(flow->check_extra_packets
+ /*
+ && ((flow->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL)
+ || (flow->detected_protocol_stack[1] == NDPI_PROTOCOL_SSL))
+ */
+ ) {
+ ndpi_process_extra_packet(ndpi_struct, flow, packet, packetlen, current_tick_l, src, dst);
+ ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0];
+ return(ret);
+ } else
+ goto ret_protocols;
+ }
/* need at least 20 bytes for ip header */
if(packetlen < 20) {
/* reset protocol which is normally done in init_packet_header */
ndpi_int_reset_packet_protocol(&flow->packet);
- return(ret);
+ goto invalidate_ptr;
}
flow->packet.tick_timestamp_l = current_tick_l;
@@ -4670,7 +4683,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
/* we are interested in ipv4 packet */
if(ndpi_init_packet_header(ndpi_struct, flow, packetlen) != 0)
- return(ret);
+ goto invalidate_ptr;
/* detect traffic for tcp or udp only */
flow->src = src, flow->dst = dst;
@@ -4731,19 +4744,19 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
flow->guessed_host_protocol_id = ndpi_guess_host_protocol_id(ndpi_struct, flow);
if(ndpi_struct->custom_categories.categories_loaded && flow->packet.iph) {
- ndpi_protocol ret;
-
+ ndpi_protocol ret = { NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED };
+
ndpi_fill_ip_protocol_category(ndpi_struct, flow->packet.iph->saddr, flow->packet.iph->daddr, &ret);
flow->guessed_header_category = ret.category;
} else
flow->guessed_header_category = NDPI_PROTOCOL_CATEGORY_UNSPECIFIED;
-
+
if(flow->guessed_protocol_id >= (NDPI_MAX_SUPPORTED_PROTOCOLS-1)) {
/* This is a custom protocol and it has priority over everything else */
ret.master_protocol = NDPI_PROTOCOL_UNKNOWN,
ret.app_protocol = flow->guessed_protocol_id ? flow->guessed_protocol_id : flow->guessed_host_protocol_id;
ndpi_fill_protocol_category(ndpi_struct, flow, &ret);
- return(ret);
+ goto invalidate_ptr;
}
if(user_defined_proto && flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) {
@@ -4754,7 +4767,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
}
ndpi_fill_protocol_category(ndpi_struct, flow, &ret);
- return(ret);
+ goto invalidate_ptr;
}
} else {
/* guess host protocol */
@@ -4784,8 +4797,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
ndpi_check_flow_func(ndpi_struct, flow, &ndpi_selection_packet);
ndpi_fill_protocol_category(ndpi_struct, flow, &ret);
-
- return(ret);
+ goto invalidate_ptr;
}
ndpi_check_flow_func(ndpi_struct, flow, &ndpi_selection_packet);
@@ -4797,10 +4809,14 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
if(a != NDPI_PROTOCOL_UNKNOWN) {
int i;
- for(i=0; (i<sizeof(flow->host_server_name)) && (flow->host_server_name[i] != '\0'); i++)
- flow->host_server_name[i] = tolower(flow->host_server_name[i]);
-
- flow->host_server_name[i] ='\0';
+ for(i=0; i<sizeof(flow->host_server_name); i++) {
+ if(flow->host_server_name[i] != '\0')
+ flow->host_server_name[i] = tolower(flow->host_server_name[i]);
+ else {
+ flow->host_server_name[i] ='\0';
+ break;
+ }
+ }
}
ret_protocols:
@@ -4831,6 +4847,13 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
ret = ndpi_detection_giveup(ndpi_struct, flow, 0);
}
+ invalidate_ptr:
+ /*
+ Invalidate packet memory to avoid accessing the pointers below
+ when the packet is no longer accessible
+ */
+ flow->packet.iph = NULL, flow->packet.tcp = NULL, flow->packet.udp = NULL;
+
return(ret);
}
@@ -5030,7 +5053,8 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_struc
packet->line[packet->parsed_lines].ptr = packet->payload;
packet->line[packet->parsed_lines].len = 0;
- for(a = 0; a < packet->payload_packet_len; a++) {
+ for(a = 0; (a < packet->payload_packet_len)
+ && (packet->parsed_lines < NDPI_MAX_PARSE_LINES_PER_PACKET); a++) {
if((a + 1) == packet->payload_packet_len)
return; /* Return if only one byte remains (prevent invalid reads past end-of-buffer) */
@@ -5691,8 +5715,8 @@ char *ndpi_get_packet_dst_ip_string(struct ndpi_detection_module_struct *ndpi_st
/* ****************************************************** */
u_int16_t ntohs_ndpi_bytestream_to_number(const u_int8_t * str,
- u_int16_t max_chars_to_read, u_int16_t * bytes_read)
-{
+ u_int16_t max_chars_to_read,
+ u_int16_t * bytes_read) {
u_int16_t val = ndpi_bytestream_to_number(str, max_chars_to_read, bytes_read);
return ntohs(val);
}
@@ -6107,7 +6131,7 @@ static int ndpi_automa_match_string_subprotocol(struct ndpi_detection_module_str
u_int16_t master_protocol_id,
ndpi_protocol_match_result *ret_match,
u_int8_t is_host_match) {
- int matching_protocol_id = NDPI_PROTOCOL_UNKNOWN;
+ int matching_protocol_id;
struct ndpi_packet_struct *packet = &flow->packet;
#ifndef HAVE_HYPERSCAN
@@ -6117,6 +6141,8 @@ static int ndpi_automa_match_string_subprotocol(struct ndpi_detection_module_str
#else
struct hs *hs = (struct hs*)ndpi_struct->hyperscan;
hs_error_t status;
+
+ matching_protocol_id = NDPI_PROTOCOL_UNKNOWN;
/*
TODO HYPERSCAN
In case of match fill up ret_match and set flow protocol + category
@@ -6378,3 +6404,54 @@ int ndpi_flowv6_flow_hash(u_int8_t l4_proto, struct ndpi_in6_addr *src_ip, struc
return(0); /* OK */
}
+
+/* **************************************** */
+
+/* **************************************** */
+
+struct cipher_weakness {
+ u_int16_t cipher_id;
+ ndpi_cipher_weakness weakness_type;
+};
+
+static struct cipher_weakness safe_ssl_ciphers[] = {
+ /* https://community.qualys.com/thread/18212-how-does-qualys-determine-the-server-cipher-suites */
+ /* INSECURE */
+ { 0xc011, NDPI_CIPHER_INSECURE }, /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */
+ { 0x0005, NDPI_CIPHER_INSECURE }, /* TLS_RSA_WITH_RC4_128_SHA */
+ { 0x0004, NDPI_CIPHER_INSECURE }, /* TLS_RSA_WITH_RC4_128_MD5 */
+ /* WEAK */
+ { 0x009d, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_AES_256_GCM_SHA384 */
+ { 0x003d, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_AES_256_CBC_SHA256 */
+ { 0x0035, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_AES_256_CBC_SHA */
+ { 0x0084, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_CAMELLIA_256_CBC_SHA */
+ { 0x009c, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_AES_128_GCM_SHA256 */
+ { 0x003c, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_AES_128_CBC_SHA256 */
+ { 0x002f, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_AES_128_CBC_SHA */
+ { 0x0041, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_CAMELLIA_128_CBC_SHA */
+ { 0xc012, NDPI_CIPHER_WEAK }, /* TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA */
+ { 0x0016, NDPI_CIPHER_WEAK }, /* TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA */
+ { 0x000a, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_3DES_EDE_CBC_SHA */
+ { 0x0096, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_SEED_CBC_SHA */
+ { 0x0007, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_IDEA_CBC_SHA */
+
+ { 0x0, NDPI_CIPHER_SAFE } /* END */
+};
+
+u_int8_t ndpi_is_safe_ssl_cipher(u_int16_t cipher) {
+ u_int i;
+
+ for(i=0; safe_ssl_ciphers[i].cipher_id != 0; i++) {
+ if(safe_ssl_ciphers[i].cipher_id == cipher) {
+#ifdef CERTIFICATE_DEBUG
+ printf("%s %s(%04X / %u)\n",
+ (safe_ssl_ciphers[i].weakness_type == NDPI_CIPHER_WEAK) ? "WEAK" : "INSECURE",
+ __FUNCTION__, cipher, cipher);
+#endif
+
+ return(safe_ssl_ciphers[i].weakness_type);
+ }
+ }
+
+ return(NDPI_CIPHER_SAFE); /* We're safe */
+}