diff options
Diffstat (limited to 'src/lib/ndpi_main.c')
-rw-r--r-- | src/lib/ndpi_main.c | 201 |
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 */ +} |