diff options
author | Luca Deri <deri@ntop.org> | 2015-06-16 18:31:01 +0200 |
---|---|---|
committer | Luca Deri <deri@ntop.org> | 2015-06-16 18:31:01 +0200 |
commit | 85db524a35e8b143f6eae498e4d2d38bb1b3a346 (patch) | |
tree | 775b21c46098b0bdd63c30dd52936b7a455ac045 /src | |
parent | 031f1709f24bbedb7147cffc28e6fe1a39b52b3c (diff) |
Added fix for detecting SSL certificate decoding. The old code did not discard non-SSL packets thus incrementing a counter when not necessary and thus terminating SSL decoding too early. This causes some SSL certificates not to be properly dissected and thus handled.
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/protocols/ssl.c | 145 |
1 files changed, 76 insertions, 69 deletions
diff --git a/src/lib/protocols/ssl.c b/src/lib/protocols/ssl.c index c61c039c1..f4b70ed62 100644 --- a/src/lib/protocols/ssl.c +++ b/src/lib/protocols/ssl.c @@ -25,7 +25,7 @@ #include "ndpi_api.h" -// #define CERTIFICATE_DEBUG 1 +/* #define CERTIFICATE_DEBUG 1 */ #ifdef NDPI_PROTOCOL_SSL @@ -134,6 +134,14 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, char *buffer, int buffer_len) { struct ndpi_packet_struct *packet = &flow->packet; +#ifdef CERTIFICATE_DEBUG + { + static u_int8_t id = 0; + + printf("-> [%u] %02X\n", ++id, packet->payload[0] & 0xFF); + } +#endif + /* Nothing matched so far: let's decode the certificate with some heuristics Patches courtesy of Denys Fedoryshchenko <nuclearcat@nuclearcat.com> @@ -145,7 +153,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, memset(buffer, 0, buffer_len); /* Truncate total len, search at least in incomplete packet */ - if (total_len > packet->payload_packet_len) + if(total_len > packet->payload_packet_len) total_len = packet->payload_packet_len; /* At least "magic" 3 bytes, null for string end, otherwise no need to waste cpu cycles */ @@ -282,38 +290,41 @@ int sslDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_s if(!packet->iph /* IPv4 */) return(-1); - if((packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) - || (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL)) { - char certificate[64]; - int rc; + if((packet->payload_packet_len > 9) + && (packet->payload[0] == 0x16 /* consider only specific SSL packets (handshake) */)) { + if((packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) + || (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL)) { + char certificate[64]; + int rc; - certificate[0] = '\0'; - rc = getSSLcertificate(ndpi_struct, flow, certificate, sizeof(certificate)); - packet->ssl_certificate_num_checks++; + certificate[0] = '\0'; + rc = getSSLcertificate(ndpi_struct, flow, certificate, sizeof(certificate)); + packet->ssl_certificate_num_checks++; - if(rc > 0) { - packet->ssl_certificate_detected++; + if(rc > 0) { + packet->ssl_certificate_detected++; #ifdef CERTIFICATE_DEBUG - printf("***** [SSL] %s\n", certificate); + printf("***** [SSL] %s\n", certificate); #endif - if(ndpi_match_string_subprotocol(ndpi_struct, flow, certificate, strlen(certificate)) != NDPI_PROTOCOL_UNKNOWN) - return(rc); /* Fix courtesy of Gianluca Costa <g.costa@xplico.org> */ + if(ndpi_match_string_subprotocol(ndpi_struct, flow, certificate, strlen(certificate)) != NDPI_PROTOCOL_UNKNOWN) + return(rc); /* Fix courtesy of Gianluca Costa <g.costa@xplico.org> */ #ifdef NDPI_PROTOCOL_TOR - if(ndpi_is_ssl_tor(ndpi_struct, flow, certificate) != 0) - return(rc); + if(ndpi_is_ssl_tor(ndpi_struct, flow, certificate) != 0) + return(rc); #endif - } + } - if(((packet->ssl_certificate_num_checks >= 2) - && flow->l4.tcp.seen_syn - && flow->l4.tcp.seen_syn_ack - && flow->l4.tcp.seen_ack /* We have seen the 3-way handshake */) - || (flow->protos.ssl.server_certificate[0] != '\0') - || (flow->protos.ssl.client_certificate[0] != '\0') - ) - ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL); + if(((packet->ssl_certificate_num_checks >= 2) + && flow->l4.tcp.seen_syn + && flow->l4.tcp.seen_syn_ack + && flow->l4.tcp.seen_ack /* We have seen the 3-way handshake */) + || (flow->protos.ssl.server_certificate[0] != '\0') + || (flow->protos.ssl.client_certificate[0] != '\0') + ) + ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL); + } } return(0); @@ -330,11 +341,11 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct u_int32_t a; u_int32_t end; #if defined(NDPI_PROTOCOL_UNENCRYPED_JABBER) - if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_UNENCRYPED_JABBER) != 0) + if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_UNENCRYPED_JABBER) != 0) goto check_for_ssl_payload; #endif #if defined(NDPI_PROTOCOL_OSCAR) - if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_OSCAR) != 0) + if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_OSCAR) != 0) goto check_for_ssl_payload; #endif goto no_check_for_ssl_payload; @@ -343,10 +354,10 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct end = packet->payload_packet_len - 20; for (a = 5; a < end; a++) { #ifdef NDPI_PROTOCOL_UNENCRYPED_JABBER - if (packet->payload[a] == 't') { - if (memcmp(&packet->payload[a], "talk.google.com", 15) == 0) { + if(packet->payload[a] == 't') { + if(memcmp(&packet->payload[a], "talk.google.com", 15) == 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "ssl jabber packet match\n"); - if (NDPI_COMPARE_PROTOCOL_TO_BITMASK + if(NDPI_COMPARE_PROTOCOL_TO_BITMASK (ndpi_struct->detection_bitmask, NDPI_PROTOCOL_UNENCRYPED_JABBER) != 0) { ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_UNENCRYPED_JABBER); return; @@ -355,9 +366,9 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct } #endif #ifdef NDPI_PROTOCOL_OSCAR - if (packet->payload[a] == 'A' || packet->payload[a] == 'k' || packet->payload[a] == 'c' + if(packet->payload[a] == 'A' || packet->payload[a] == 'k' || packet->payload[a] == 'c' || packet->payload[a] == 'h') { - if (((a + 19) < packet->payload_packet_len && memcmp(&packet->payload[a], "America Online Inc.", 19) == 0) + if(((a + 19) < packet->payload_packet_len && memcmp(&packet->payload[a], "America Online Inc.", 19) == 0) // || (end - c > 3 memcmp (&packet->payload[c],"AOL", 3) == 0 ) // || (end - c > 7 && memcmp (&packet->payload[c], "AOL LLC", 7) == 0) || ((a + 15) < packet->payload_packet_len && memcmp(&packet->payload[a], "kdc.uas.aol.com", 15) == 0) @@ -370,7 +381,7 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct && memcmp(&packet->payload[a], "http://pki-info.aol.com/AOLMSPKI", 32) == 0)) { NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR SERVER SSL DETECTED\n"); - if (flow->dst != NULL && packet->payload_packet_len > 75) { + if(flow->dst != NULL && packet->payload_packet_len > 75) { memcpy(flow->dst->oscar_ssl_session_id, &packet->payload[44], 32); flow->dst->oscar_ssl_session_id[32] = '\0'; flow->dst->oscar_last_safe_access_time = packet->tick_timestamp; @@ -381,8 +392,8 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct } } - if (packet->payload[a] == 'm' || packet->payload[a] == 's') { - if ((a + 21) < packet->payload_packet_len && + if(packet->payload[a] == 'm' || packet->payload[a] == 's') { + if((a + 21) < packet->payload_packet_len && (memcmp(&packet->payload[a], "my.screenname.aol.com", 21) == 0 || memcmp(&packet->payload[a], "sns-static.aolcdn.com", 21) == 0)) { NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR SERVER SSL DETECTED\n"); @@ -418,7 +429,7 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct // struct ndpi_id_struct *dst=flow->dst; - if ((packet->payload_packet_len >= 5) + if((packet->payload_packet_len >= 5) && (packet->payload[0] == 0x16) && (packet->payload[1] == 0x03) && ((packet->payload[2] == 0x00) @@ -429,17 +440,17 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct u_int32_t temp; NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "search sslv3\n"); // SSLv3 Record - if (packet->payload_packet_len >= 1300) { + if(packet->payload_packet_len >= 1300) { return 1; } temp = ntohs(get_u_int16_t(packet->payload, 3)) + 5; NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "temp = %u.\n", temp); - if (packet->payload_packet_len == temp + if(packet->payload_packet_len == temp || (temp < packet->payload_packet_len && packet->payload_packet_len > 500)) { return 1; } - if (packet->payload_packet_len < temp && temp < 5000 && packet->payload_packet_len > 9) { + if(packet->payload_packet_len < temp && temp < 5000 && packet->payload_packet_len > 9) { /* the server hello may be split into small packets */ u_int32_t cert_start; @@ -451,14 +462,14 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "suspected start of certificate: %u\n", cert_start); - if (cert_start < packet->payload_packet_len && packet->payload[cert_start] == 0x0b) { + if(cert_start < packet->payload_packet_len && packet->payload[cert_start] == 0x0b) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "found 0x0b at suspected start of certificate block\n"); return 2; } } - if ((packet->payload_packet_len > temp && packet->payload_packet_len > 100) && packet->payload_packet_len > 9) { + if((packet->payload_packet_len > temp && packet->payload_packet_len > 100) && packet->payload_packet_len > 9) { /* the server hello may be split into small packets and the certificate has its own SSL Record * so temp contains only the length for the first ServerHello block */ u_int32_t cert_start; @@ -471,7 +482,7 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "suspected start of certificate: %u\n", cert_start); - if (cert_start < packet->payload_packet_len && packet->payload[cert_start] == 0x0b) { + if(cert_start < packet->payload_packet_len && packet->payload[cert_start] == 0x0b) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "found 0x0b at suspected start of certificate block\n"); return 2; @@ -479,49 +490,45 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct } - if (packet->payload_packet_len >= temp + 5 && (packet->payload[temp] == 0x14 || packet->payload[temp] == 0x16) + if(packet->payload_packet_len >= temp + 5 && (packet->payload[temp] == 0x14 || packet->payload[temp] == 0x16) && packet->payload[temp + 1] == 0x03) { u_int32_t temp2 = ntohs(get_u_int16_t(packet->payload, temp + 3)) + 5; - if (temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) { + if(temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) { return 1; } temp += temp2; NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "temp = %u.\n", temp); - if (packet->payload_packet_len == temp) { + if(packet->payload_packet_len == temp) { return 1; } - if (packet->payload_packet_len >= temp + 5 && + if(packet->payload_packet_len >= temp + 5 && packet->payload[temp] == 0x16 && packet->payload[temp + 1] == 0x03) { temp2 = ntohs(get_u_int16_t(packet->payload, temp + 3)) + 5; - if (temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) { + if(temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) { return 1; } temp += temp2; NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "temp = %u.\n", temp); - if (packet->payload_packet_len == temp) { + if(packet->payload_packet_len == temp) { return 1; } - if (packet->payload_packet_len >= temp + 5 && + if(packet->payload_packet_len >= temp + 5 && packet->payload[temp] == 0x16 && packet->payload[temp + 1] == 0x03) { temp2 = ntohs(get_u_int16_t(packet->payload, temp + 3)) + 5; - if (temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) { + if(temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) { return 1; } temp += temp2; NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "temp = %u.\n", temp); - if (temp == packet->payload_packet_len) { + if(temp == packet->payload_packet_len) { return 1; } } - } - - } - } - return 0; + return 0; } void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) @@ -533,15 +540,15 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc u_int8_t ret; - if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) { - if (flow->l4.tcp.ssl_stage == 3 && packet->payload_packet_len > 20 && flow->packet_counter < 5) { + if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) { + if(flow->l4.tcp.ssl_stage == 3 && packet->payload_packet_len > 20 && flow->packet_counter < 5) { /* this should only happen, when we detected SSL with a packet that had parts of the certificate in subsequent packets * so go on checking for certificate patterns for a couple more packets */ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "ssl flow but check another packet for patterns\n"); ssl_mark_and_payload_search_for_other_protocols(ndpi_struct, flow); - if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) { + if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) { /* still ssl so check another packet */ return; } else { @@ -571,10 +578,10 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc } } - if (packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 0) { + if(packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 0) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "first ssl packet\n"); // SSLv2 Record - if (packet->payload[2] == 0x01 && packet->payload[3] == 0x03 + if(packet->payload[2] == 0x01 && packet->payload[3] == 0x03 && (packet->payload[4] == 0x00 || packet->payload[4] == 0x01 || packet->payload[4] == 0x02) && (packet->payload_packet_len - packet->payload[1] == 2)) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "sslv2 len match\n"); @@ -582,7 +589,7 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc return; } - if (packet->payload[0] == 0x16 && packet->payload[1] == 0x03 + if(packet->payload[0] == 0x16 && packet->payload[1] == 0x03 && (packet->payload[2] == 0x00 || packet->payload[2] == 0x01 || packet->payload[2] == 0x02) && (packet->payload_packet_len - ntohs(get_u_int16_t(packet->payload, 3)) == 5)) { // SSLv3 Record @@ -592,16 +599,16 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc } } - if (packet->payload_packet_len > 40 && + if(packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 1 + packet->packet_direction && flow->packet_direction_counter[packet->packet_direction] < 5) { return; } - if (packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 2 - packet->packet_direction) { + if(packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 2 - packet->packet_direction) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "second ssl packet\n"); // SSLv2 Record - if (packet->payload[2] == 0x01 && packet->payload[3] == 0x03 + if(packet->payload[2] == 0x01 && packet->payload[3] == 0x03 && (packet->payload[4] == 0x00 || packet->payload[4] == 0x01 || packet->payload[4] == 0x02) && (packet->payload_packet_len - 2) >= packet->payload[1]) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "sslv2 server len match\n"); @@ -610,21 +617,21 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc } ret = ndpi_search_sslv3_direction1(ndpi_struct, flow); - if (ret == 1) { + if(ret == 1) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "sslv3 server len match\n"); ssl_mark_and_payload_search_for_other_protocols(ndpi_struct, flow); return; - } else if (ret == 2) { + } else if(ret == 2) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "sslv3 server len match with split packet -> check some more packets for SSL patterns\n"); ssl_mark_and_payload_search_for_other_protocols(ndpi_struct, flow); - if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) { + if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) { flow->l4.tcp.ssl_stage = 3; } return; } - if (packet->payload_packet_len > 40 && flow->packet_direction_counter[packet->packet_direction] < 5) { + if(packet->payload_packet_len > 40 && flow->packet_direction_counter[packet->packet_direction] < 5) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "need next packet\n"); return; } |