diff options
-rw-r--r-- | example/ndpi_util.c | 1 | ||||
-rw-r--r-- | src/include/ndpi_api.h | 1 | ||||
-rw-r--r-- | src/include/ndpi_typedefs.h | 2 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 83 | ||||
-rw-r--r-- | src/lib/protocols/ssl.c | 54 |
5 files changed, 69 insertions, 72 deletions
diff --git a/example/ndpi_util.c b/example/ndpi_util.c index 92d8dca80..2c05ddcd1 100644 --- a/example/ndpi_util.c +++ b/example/ndpi_util.c @@ -572,7 +572,6 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl flow->ndpi_flow->protos.stun_ssl.ssl.ja3_client); snprintf(flow->ssh_ssl.ja3_server, sizeof(flow->ssh_ssl.ja3_server), "%s", flow->ndpi_flow->protos.stun_ssl.ssl.ja3_server); - flow->ssh_ssl.client_unsafe_cipher = flow->ndpi_flow->protos.stun_ssl.ssl.client_unsafe_cipher; flow->ssh_ssl.server_unsafe_cipher = flow->ndpi_flow->protos.stun_ssl.ssl.server_unsafe_cipher; } } diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h index 6e0e4787b..afe22c329 100644 --- a/src/include/ndpi_api.h +++ b/src/include/ndpi_api.h @@ -807,6 +807,7 @@ extern "C" { u_int16_t src_port, u_int16_t dst_port, u_int8_t icmp_type, u_int8_t icmp_code, u_char *hash_buf, u_int8_t hash_buf_len); + u_int8_t ndpi_is_safe_ssl_cipher(u_int16_t cipher); #ifdef __cplusplus } #endif diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 89d119098..69970a3e1 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -1100,7 +1100,7 @@ struct ndpi_flow_struct { char client_certificate[64], server_certificate[64], server_organization[64]; char ja3_client[33], ja3_server[33]; u_int16_t server_cipher; - ndpi_cipher_weakness client_unsafe_cipher, server_unsafe_cipher; + ndpi_cipher_weakness server_unsafe_cipher; } ssl; struct { diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index fc898d4b8..e200f32f0 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -2690,7 +2690,7 @@ u_int16_t ndpi_guess_protocol_id(struct ndpi_detection_module_struct *ndpi_struc 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); @@ -3913,7 +3913,7 @@ 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); - + flow->next_tcp_seq_nr[1 -flow->packet.packet_direction] = ntohl(tcph->ack_seq); } } else if(packet->payload_packet_len > 0) { @@ -4178,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); @@ -4275,17 +4275,17 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st 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); @@ -4584,7 +4584,7 @@ int ndpi_fill_ip_protocol_category(struct ndpi_detection_module_struct *ndpi_str return 1; } } - + ret->category = ndpi_get_proto_category(ndpi_struct, *ret); return 0; @@ -4599,7 +4599,7 @@ void ndpi_fill_protocol_category(struct ndpi_detection_module_struct *ndpi_struc if(flow->guessed_header_category != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) { flow->category = ret->category = flow->guessed_header_category; return; - } + } if(flow->host_server_name[0] != '\0') { unsigned long id; @@ -4653,7 +4653,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct 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 + the certificate type for instance */ if(flow->check_extra_packets /* @@ -4667,7 +4667,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct } 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 */ @@ -4683,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) - goto invalidate_ptr; + goto invalidate_ptr; /* detect traffic for tcp or udp only */ flow->src = src, flow->dst = dst; @@ -4745,12 +4745,12 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct if(ndpi_struct->custom_categories.categories_loaded && flow->packet.iph) { 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, @@ -4797,7 +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); - goto invalidate_ptr; + goto invalidate_ptr; } ndpi_check_flow_func(ndpi_struct, flow, &ndpi_selection_packet); @@ -4812,7 +4812,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct 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 { + else { flow->host_server_name[i] ='\0'; break; } @@ -4848,12 +4848,12 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct } 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); } @@ -6406,3 +6406,52 @@ int ndpi_flowv6_flow_hash(u_int8_t l4_proto, struct ndpi_in6_addr *src_ip, struc } /* **************************************** */ + +/* **************************************** */ + +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 */ +} diff --git a/src/lib/protocols/ssl.c b/src/lib/protocols/ssl.c index 2ea5362cf..1f51ab4b6 100644 --- a/src/lib/protocols/ssl.c +++ b/src/lib/protocols/ssl.c @@ -356,55 +356,6 @@ struct ja3_info { /* **************************************** */ -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 */ -}; - -static u_int8_t 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 */ -} -/* **************************************** */ - /* code fixes courtesy of Alexsandro Brahm <alex@digistar.com.br> */ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, @@ -464,7 +415,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, 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 = is_safe_ssl_cipher(ja3.cipher[0]); + 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 @@ -785,9 +736,6 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, 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]); - - if(flow->protos.stun_ssl.ssl.client_unsafe_cipher < NDPI_CIPHER_INSECURE) - flow->protos.stun_ssl.ssl.client_unsafe_cipher = is_safe_ssl_cipher(ja3.cipher[i]); } ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ","); |