diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/ndpi_main.c | 224 | ||||
-rw-r--r-- | src/lib/protocols/dns.c | 32 | ||||
-rw-r--r-- | src/lib/protocols/ssl.c | 37 | ||||
-rw-r--r-- | src/lib/protocols/tor.c | 3 |
4 files changed, 151 insertions, 145 deletions
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index 896b8a43c..6dc19d743 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -1749,7 +1749,7 @@ static int ac_match_handler(AC_MATCH_t *m, AC_TEXT_t *txt, AC_REP_t *match) { #ifdef MATCH_DEBUG printf("Searching [to search: %s/%u][pattern: %s/%u] [len: %u][match_num: %u][%s]\n", - buf, txt->length, m->patterns->astring, m->patterns->length, min_len, + buf, (unigned int)txt->length, m->patterns->astring, m->patterns->length, min_len, m->match_num, m->patterns->astring); #endif @@ -1768,7 +1768,8 @@ static int ac_match_handler(AC_MATCH_t *m, AC_TEXT_t *txt, AC_REP_t *match) { to avoid matching aws.amazon.com whereas a.ws.amazon.com has to match */ - if(whatfound && (whatfound != buf) + if(whatfound + && (whatfound != buf) && (m->patterns->astring[0] != '.') /* The searched pattern does not start with . */ && strchr(m->patterns->astring, '.') /* The matched pattern has a . (e.g. numeric or sym IPs) */ && (whatfound[-1] != '.') @@ -3627,125 +3628,124 @@ static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str } void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_struct, - struct ndpi_flow_struct *flow) -{ - /* const for gcc code optimization and cleaner code */ - struct ndpi_packet_struct *packet = &flow->packet; - const struct ndpi_iphdr *iph = packet->iph; + struct ndpi_flow_struct *flow) { + if(!flow) { + return; + } else { + /* const for gcc code optimization and cleaner code */ + struct ndpi_packet_struct *packet = &flow->packet; + const struct ndpi_iphdr *iph = packet->iph; #ifdef NDPI_DETECTION_SUPPORT_IPV6 - const struct ndpi_ipv6hdr *iphv6 = packet->iphv6; + const struct ndpi_ipv6hdr *iphv6 = packet->iphv6; #endif - const struct ndpi_tcphdr *tcph = packet->tcp; - const struct ndpi_udphdr *udph = flow->packet.udp; - - if (!flow) { - return; - } + const struct ndpi_tcphdr *tcph = packet->tcp; + const struct ndpi_udphdr *udph = flow->packet.udp; - packet->tcp_retransmission = 0, packet->packet_direction = 0; + packet->tcp_retransmission = 0, packet->packet_direction = 0; - if(ndpi_struct->direction_detect_disable) { - packet->packet_direction = flow->packet_direction; - } else { - if(iph != NULL && ntohl(iph->saddr) < ntohl(iph->daddr)) - packet->packet_direction = 1; + if(ndpi_struct->direction_detect_disable) { + packet->packet_direction = flow->packet_direction; + } else { + if(iph != NULL && ntohl(iph->saddr) < ntohl(iph->daddr)) + packet->packet_direction = 1; #ifdef NDPI_DETECTION_SUPPORT_IPV6 - if(iphv6 != NULL && NDPI_COMPARE_IPV6_ADDRESS_STRUCTS(&iphv6->ip6_src, - &iphv6->ip6_dst) != 0) - packet->packet_direction = 1; + if(iphv6 != NULL && NDPI_COMPARE_IPV6_ADDRESS_STRUCTS(&iphv6->ip6_src, + &iphv6->ip6_dst) != 0) + packet->packet_direction = 1; #endif - } + } - packet->packet_lines_parsed_complete = 0; + packet->packet_lines_parsed_complete = 0; - if(flow->init_finished == 0) { - flow->init_finished = 1; - flow->setup_packet_direction = packet->packet_direction; - } - - if(tcph != NULL) { - /* reset retried bytes here before setting it */ - packet->num_retried_bytes = 0; + if(flow->init_finished == 0) { + flow->init_finished = 1; + flow->setup_packet_direction = packet->packet_direction; + } - if(!ndpi_struct->direction_detect_disable) - packet->packet_direction = (ntohs(tcph->source) < ntohs(tcph->dest)) ? 1 : 0; + if(tcph != NULL) { + /* reset retried bytes here before setting it */ + packet->num_retried_bytes = 0; - if(tcph->syn != 0 && tcph->ack == 0 && flow->l4.tcp.seen_syn == 0 && flow->l4.tcp.seen_syn_ack == 0 - && flow->l4.tcp.seen_ack == 0) { - flow->l4.tcp.seen_syn = 1; - } - if(tcph->syn != 0 && tcph->ack != 0 && flow->l4.tcp.seen_syn == 1 && flow->l4.tcp.seen_syn_ack == 0 - && flow->l4.tcp.seen_ack == 0) { - flow->l4.tcp.seen_syn_ack = 1; - } - if(tcph->syn == 0 && tcph->ack == 1 && flow->l4.tcp.seen_syn == 1 && flow->l4.tcp.seen_syn_ack == 1 - && flow->l4.tcp.seen_ack == 0) { - flow->l4.tcp.seen_ack = 1; - } - if((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 - * also for asymmetric traffic where it will use the first data packet - * - * if the syn flag is set add one to the sequence number, - * otherwise use the payload length. - */ - if(tcph->ack != 0) { - flow->next_tcp_seq_nr[flow->packet.packet_direction] = - ntohl(tcph->seq) + (tcph->syn ? 1 : packet->payload_packet_len); + if(!ndpi_struct->direction_detect_disable) + packet->packet_direction = (ntohs(tcph->source) < ntohs(tcph->dest)) ? 1 : 0; - flow->next_tcp_seq_nr[1 -flow->packet.packet_direction] = ntohl(tcph->ack_seq); + if(tcph->syn != 0 && tcph->ack == 0 && flow->l4.tcp.seen_syn == 0 && flow->l4.tcp.seen_syn_ack == 0 + && flow->l4.tcp.seen_ack == 0) { + flow->l4.tcp.seen_syn = 1; } - } else if(packet->payload_packet_len > 0) { - /* check tcp sequence counters */ - if(((u_int32_t)(ntohl(tcph->seq) - flow->next_tcp_seq_nr[packet->packet_direction])) > - ndpi_struct->tcp_max_retransmission_window_size) { - - packet->tcp_retransmission = 1; - - /* CHECK IF PARTIAL RETRY IS HAPPENING */ - if((flow->next_tcp_seq_nr[packet->packet_direction] - ntohl(tcph->seq) < packet->payload_packet_len)) { - /* num_retried_bytes actual_payload_len hold info about the partial retry - analyzer which require this info can make use of this info - Other analyzer can use packet->payload_packet_len */ - packet->num_retried_bytes = (u_int16_t)(flow->next_tcp_seq_nr[packet->packet_direction] - ntohl(tcph->seq)); - packet->actual_payload_len = packet->payload_packet_len - packet->num_retried_bytes; + if(tcph->syn != 0 && tcph->ack != 0 && flow->l4.tcp.seen_syn == 1 && flow->l4.tcp.seen_syn_ack == 0 + && flow->l4.tcp.seen_ack == 0) { + flow->l4.tcp.seen_syn_ack = 1; + } + if(tcph->syn == 0 && tcph->ack == 1 && flow->l4.tcp.seen_syn == 1 && flow->l4.tcp.seen_syn_ack == 1 + && flow->l4.tcp.seen_ack == 0) { + flow->l4.tcp.seen_ack = 1; + } + if((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 + * also for asymmetric traffic where it will use the first data packet + * + * if the syn flag is set add one to the sequence number, + * otherwise use the payload length. + */ + 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) { + /* check tcp sequence counters */ + if(((u_int32_t)(ntohl(tcph->seq) - flow->next_tcp_seq_nr[packet->packet_direction])) > + ndpi_struct->tcp_max_retransmission_window_size) { + + packet->tcp_retransmission = 1; + + /* CHECK IF PARTIAL RETRY IS HAPPENING */ + if((flow->next_tcp_seq_nr[packet->packet_direction] - ntohl(tcph->seq) < packet->payload_packet_len)) { + /* num_retried_bytes actual_payload_len hold info about the partial retry + analyzer which require this info can make use of this info + Other analyzer can use packet->payload_packet_len */ + packet->num_retried_bytes = (u_int16_t)(flow->next_tcp_seq_nr[packet->packet_direction] - ntohl(tcph->seq)); + packet->actual_payload_len = packet->payload_packet_len - packet->num_retried_bytes; + flow->next_tcp_seq_nr[packet->packet_direction] = ntohl(tcph->seq) + packet->payload_packet_len; + } + } + + /* normal path + actual_payload_len is initialized to payload_packet_len during tcp header parsing itself. + It will be changed only in case of retransmission */ + else { + packet->num_retried_bytes = 0; flow->next_tcp_seq_nr[packet->packet_direction] = ntohl(tcph->seq) + packet->payload_packet_len; } } - /* normal path - actual_payload_len is initialized to payload_packet_len during tcp header parsing itself. - It will be changed only in case of retransmission */ - else { - packet->num_retried_bytes = 0; - flow->next_tcp_seq_nr[packet->packet_direction] = ntohl(tcph->seq) + packet->payload_packet_len; + if(tcph->rst) { + flow->next_tcp_seq_nr[0] = 0; + flow->next_tcp_seq_nr[1] = 0; } + } else if(udph != NULL) { + if(!ndpi_struct->direction_detect_disable) + packet->packet_direction = (htons(udph->source) < htons(udph->dest)) ? 1 : 0; } - if(tcph->rst) { - flow->next_tcp_seq_nr[0] = 0; - flow->next_tcp_seq_nr[1] = 0; + if(flow->packet_counter < MAX_PACKET_COUNTER && packet->payload_packet_len) { + flow->packet_counter++; } - } else if(udph != NULL) { - if(!ndpi_struct->direction_detect_disable) - packet->packet_direction = (htons(udph->source) < htons(udph->dest)) ? 1 : 0; - } - if(flow->packet_counter < MAX_PACKET_COUNTER && packet->payload_packet_len) { - flow->packet_counter++; - } - - if(flow->packet_direction_counter[packet->packet_direction] < MAX_PACKET_COUNTER && packet->payload_packet_len) { - flow->packet_direction_counter[packet->packet_direction]++; - } + if(flow->packet_direction_counter[packet->packet_direction] < MAX_PACKET_COUNTER && packet->payload_packet_len) { + flow->packet_direction_counter[packet->packet_direction]++; + } - if(flow->byte_counter[packet->packet_direction] + packet->payload_packet_len > - flow->byte_counter[packet->packet_direction]) { - flow->byte_counter[packet->packet_direction] += packet->payload_packet_len; + if(flow->byte_counter[packet->packet_direction] + packet->payload_packet_len > + flow->byte_counter[packet->packet_direction]) { + flow->byte_counter[packet->packet_direction] += packet->payload_packet_len; + } } } @@ -4544,8 +4544,6 @@ 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_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 @@ -6092,23 +6090,25 @@ char* ndpi_revision() { return(NDPI_GIT_RELEASE); } #ifdef WIN32 -/* http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/port/gettimeofday.c;h=75a91993b74414c0a1c13a2a09ce739cb8aa8a08;hb=HEAD */ -int gettimeofday(struct timeval * tp, struct timezone * tzp) { - /* FILETIME of Jan 1 1970 00:00:00. */ - const unsigned __int64 epoch = (__int64)(116444736000000000); +/* https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows */ +int gettimeofday(struct timeval * tp, struct timezone * tzp) +{ + // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's + // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) + // until 00:00:00 January 1, 1970 + static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); - FILETIME file_time; SYSTEMTIME system_time; - ULARGE_INTEGER ularge; + FILETIME file_time; + uint64_t time; - GetSystemTime(&system_time); - SystemTimeToFileTime(&system_time, &file_time); - ularge.LowPart = file_time.dwLowDateTime; - ularge.HighPart = file_time.dwHighDateTime; + GetSystemTime( &system_time ); + SystemTimeToFileTime( &system_time, &file_time ); + time = ((uint64_t)file_time.dwLowDateTime ) ; + time += ((uint64_t)file_time.dwHighDateTime) << 32; - tp->tv_sec = (long) ((ularge.QuadPart - epoch) / 10000000L); + tp->tv_sec = (long) ((time - EPOCH) / 10000000L); tp->tv_usec = (long) (system_time.wMilliseconds * 1000); - return 0; } #endif diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c index dc97f3fe7..6a4a02f60 100644 --- a/src/lib/protocols/dns.c +++ b/src/lib/protocols/dns.c @@ -128,19 +128,17 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd || ((dns_header.num_answers == 0) && (dns_header.authority_rrs == 0)))) { /* This is a good query */ - if(dns_header.num_queries > 0) { - while(x < flow->packet.payload_packet_len) { - if(flow->packet.payload[x] == '\0') { - x++; - flow->protos.dns.query_type = get16(&x, flow->packet.payload); + while(x < flow->packet.payload_packet_len) { + if(flow->packet.payload[x] == '\0') { + x++; + flow->protos.dns.query_type = get16(&x, flow->packet.payload); #ifdef DNS_DEBUG - NDPI_LOG_DBG2(ndpi_struct, "query_type=%2d\n", flow->protos.dns.query_type); + NDPI_LOG_DBG2(ndpi_struct, "query_type=%2d\n", flow->protos.dns.query_type); #endif - break; - } else - x++; - } - } + break; + } else + x++; + } } else invalid = 1; } else { @@ -222,15 +220,19 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd off = sizeof(struct ndpi_dns_packet_header) + payload_offset; while(j < max_len && off < flow->packet.payload_packet_len && flow->packet.payload[off] != '\0') { - uint8_t c,cl = flow->packet.payload[off++]; + uint8_t c, cl = flow->packet.payload[off++]; + if( (cl & 0xc0) != 0 || // we not support compressed names in query - off + cl >= flow->packet.payload_packet_len) { - j = 0; break; + off + cl >= flow->packet.payload_packet_len) { + j = 0; + break; } + if(j && j < max_len) flow->host_server_name[j++] = '.'; + while(j < max_len && cl != 0) { c = flow->packet.payload[off++]; - flow->host_server_name[j++] = dns_validchar[c >> 5] & (1 << (c & 0x1f)) ? c:'_'; + flow->host_server_name[j++] = (dns_validchar[c >> 5] & (1 << (c & 0x1f))) ? c : '_'; cl--; } } diff --git a/src/lib/protocols/ssl.c b/src/lib/protocols/ssl.c index 18e8ca469..b8a3a643a 100644 --- a/src/lib/protocols/ssl.c +++ b/src/lib/protocols/ssl.c @@ -51,11 +51,11 @@ static int is_big_endian(void) { } static void byteReverse(unsigned char *buf, unsigned longs) { - uint32_t t; - // Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN - if (is_big_endian()) { + if (is_big_endian()) { do { + uint32_t t; + t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]); * (uint32_t *) buf = t; @@ -367,13 +367,14 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, char *buffer, int buffer_len) { struct ndpi_packet_struct *packet = &flow->packet; struct ja3_info ja3; + int i; u_int8_t invalid_ja3 = 0; - u_int16_t ssl_version = (packet->payload[1] << 8) + packet->payload[2], ja3_str_len; + u_int16_t pkt_ssl_version = (packet->payload[1] << 8) + packet->payload[2], ja3_str_len; char ja3_str[JA3_STR_LEN]; MD5_CTX ctx; u_char md5_hash[16]; - flow->protos.stun_ssl.ssl.ssl_version = ssl_version; + flow->protos.stun_ssl.ssl.ssl_version = pkt_ssl_version; memset(&ja3, 0, sizeof(ja3)); @@ -381,7 +382,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, { u_int16_t ssl_len = (packet->payload[3] << 8) + packet->payload[4]; - printf("SSL Record [version: %u][len: %u]\n", ssl_version, ssl_len); + printf("SSL Record [version: %u][len: %u]\n", pkt_ssl_version, ssl_len); } #endif @@ -401,17 +402,16 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, /* At least "magic" 3 bytes, null for string end, otherwise no need to waste cpu cycles */ if(total_len > 4) { - int i; - #ifdef CERTIFICATE_DEBUG printf("SSL [len: %u][handshake_protocol: %02X]\n", packet->payload_packet_len, handshake_protocol); #endif - + if((handshake_protocol == 0x02) || (handshake_protocol == 0xb) /* Server Hello and Certificate message types are interesting for us */) { u_int num_found = 0; u_int16_t ssl_version = ntohs(*((u_int16_t*)&packet->payload[9])); - + int i; + ja3.ssl_version = ssl_version; if(handshake_protocol == 0x02) { @@ -564,8 +564,8 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, if((session_id_len+base_offset+2) <= total_len) { u_int16_t cipher_len = packet->payload[session_id_len+base_offset+2] + (packet->payload[session_id_len+base_offset+1] << 8); - u_int16_t i, cipher_offset = base_offset + session_id_len + 3; - + u_int16_t cipher_offset = base_offset + session_id_len + 3; + #ifdef CERTIFICATE_DEBUG printf("Client SSL [client cipher_len: %u]\n", cipher_len); #endif @@ -676,8 +676,8 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, sizeof(flow->protos.stun_ssl.ssl.client_certificate), "%s", buffer); } } else if(extension_id == 10 /* supported groups */) { - u_int16_t i, s_offset = offset+extension_offset + 2; - + u_int16_t s_offset = offset+extension_offset + 2; + #ifdef CERTIFICATE_DEBUG printf("Client SSL [EllipticCurveGroups: len=%u]\n", extension_len); #endif @@ -710,8 +710,8 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, #endif } } else if(extension_id == 11 /* ec_point_formats groups */) { - u_int16_t i, s_offset = offset+extension_offset + 1; - + u_int16_t s_offset = offset+extension_offset + 1; + #ifdef CERTIFICATE_DEBUG printf("Client SSL [EllipticCurveFormat: len=%u]\n", extension_len); #endif @@ -877,13 +877,15 @@ int sslTryAndRetrieveServerCertificate(struct ndpi_detection_module_struct *ndpi /* consider only specific SSL packets (handshake) */ if((packet->payload_packet_len > 9) && (packet->payload[0] == 0x16)) { char certificate[64]; - char organization[64]; int rc; certificate[0] = '\0'; rc = getSSLcertificate(ndpi_struct, flow, certificate, sizeof(certificate)); packet->ssl_certificate_num_checks++; + if(rc > 0) { + char organization[64]; + // try fetch server organization once server certificate is found organization[0] = '\0'; getSSLorganization(ndpi_struct, flow, organization, sizeof(organization)); @@ -893,6 +895,7 @@ int sslTryAndRetrieveServerCertificate(struct ndpi_detection_module_struct *ndpi /* 0 means we're done processing extra packets (since we found what we wanted) */ return 0; } + /* Client hello, Server Hello, and certificate packets probably all checked in this case */ if((packet->ssl_certificate_num_checks >= 3) && (flow->l4.tcp.seen_syn) diff --git a/src/lib/protocols/tor.c b/src/lib/protocols/tor.c index f1c6f586a..1a5d4097e 100644 --- a/src/lib/protocols/tor.c +++ b/src/lib/protocols/tor.c @@ -96,11 +96,12 @@ int ndpi_is_ssl_tor(struct ndpi_detection_module_struct *ndpi_struct, void ndpi_search_tor(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; - u_int16_t dport = 0, sport = 0; NDPI_LOG_DBG(ndpi_struct, "search for TOR\n"); if(packet->tcp != NULL) { + u_int16_t dport, sport; + sport = ntohs(packet->tcp->source), dport = ntohs(packet->tcp->dest); NDPI_LOG_DBG2(ndpi_struct, "calculating TOR over tcp\n"); |