aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ndpi_content_match.c.inc6
-rw-r--r--src/lib/ndpi_main.c303
-rw-r--r--src/lib/ndpi_serializer.c1107
-rw-r--r--src/lib/ndpi_utils.c929
-rw-r--r--src/lib/protocols/directconnect.c141
-rw-r--r--src/lib/protocols/dns.c32
-rw-r--r--src/lib/protocols/hangout.c28
-rw-r--r--src/lib/protocols/http.c22
-rw-r--r--src/lib/protocols/mail_imap.c2
-rw-r--r--src/lib/protocols/msn.c6
-rw-r--r--src/lib/protocols/ookla.c4
-rw-r--r--src/lib/protocols/quic.c16
-rw-r--r--src/lib/protocols/rtp.c107
-rw-r--r--src/lib/protocols/ssh.c240
-rw-r--r--src/lib/protocols/stun.c201
-rw-r--r--src/lib/protocols/teamspeak.c45
-rw-r--r--src/lib/protocols/tls.c (renamed from src/lib/protocols/ssl.c)632
-rw-r--r--src/lib/protocols/tor.c12
-rw-r--r--src/lib/protocols/yahoo.c2
-rw-r--r--src/lib/third_party/include/ndpi_md5.h18
-rw-r--r--src/lib/third_party/src/ndpi_md5.c204
21 files changed, 2446 insertions, 1611 deletions
diff --git a/src/lib/ndpi_content_match.c.inc b/src/lib/ndpi_content_match.c.inc
index 9c0356ec8..79ab8e5e4 100644
--- a/src/lib/ndpi_content_match.c.inc
+++ b/src/lib/ndpi_content_match.c.inc
@@ -8382,10 +8382,10 @@ ndpi_protocol_match host_match[] = {
{ "ntop.org", NULL, "ntop\\.org$", "ntop", NDPI_PROTOCOL_NTOP, NDPI_PROTOCOL_CATEGORY_NETWORK, NDPI_PROTOCOL_SAFE },
- { "docs.googleusercontent.com", NULL, "docs.googleusercontent" TLD, "GoogleDocs", NDPI_PROTOCOL_GOOGLE_DOCS, NDPI_PROTOCOL_CATEGORY_MEDIA, NDPI_PROTOCOL_ACCEPTABLE },
- { "docs.google.com", NULL, "docs.google" TLD, "GoogleDocs", NDPI_PROTOCOL_GOOGLE_DOCS, NDPI_PROTOCOL_CATEGORY_MEDIA, NDPI_PROTOCOL_ACCEPTABLE },
+ { "docs.googleusercontent.com", NULL, "docs.googleusercontent" TLD, "GoogleDocs", NDPI_PROTOCOL_GOOGLE_DOCS, NDPI_PROTOCOL_CATEGORY_COLLABORATIVE, NDPI_PROTOCOL_ACCEPTABLE },
+ { "docs.google.com", NULL, "docs.google" TLD, "GoogleDocs", NDPI_PROTOCOL_GOOGLE_DOCS, NDPI_PROTOCOL_CATEGORY_COLLABORATIVE, NDPI_PROTOCOL_ACCEPTABLE },
- { "drive-thirdparty.googleusercontent.com", NULL, "drive-thirdparty\\.googleusercontent" TLD, "GoogleDrive", NDPI_PROTOCOL_GOOGLE_DRIVE, NDPI_PROTOCOL_CATEGORY_COLLABORATIVE, NDPI_PROTOCOL_ACCEPTABLE },
+ { "drive-thirdparty.googleusercontent.com", NULL, "drive-thirdparty\\.googleusercontent" TLD, "GoogleDrive", NDPI_PROTOCOL_GOOGLE_DRIVE, NDPI_PROTOCOL_CATEGORY_CLOUD, NDPI_PROTOCOL_ACCEPTABLE },
{ "drive.google.com", NULL, "drive.google" TLD, "GoogleDrive", NDPI_PROTOCOL_GOOGLE_DRIVE, NDPI_PROTOCOL_CATEGORY_CLOUD, NDPI_PROTOCOL_ACCEPTABLE },
{ "android.clients.google.com", NULL, "android\\.clients\\.google" TLD, "PlayStore", NDPI_PROTOCOL_PLAYSTORE, NDPI_PROTOCOL_CATEGORY_SW_UPDATE, NDPI_PROTOCOL_SAFE },
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index 9b6bdc632..cca061856 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -51,6 +51,9 @@
#define NDPI_CONST_GENERIC_PROTOCOL_NAME "GenericProtocol"
+/* stun.c */
+extern u_int32_t get_stun_lru_key(struct ndpi_flow_struct *flow);
+
static int _ndpi_debug_callbacks = 0;
/* #define MATCH_DEBUG 1 */
@@ -846,7 +849,7 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp
no_master, "XDMCP", NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS,
ndpi_build_default_ports(ports_a, 177, 0, 0, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 177, 0, 0, 0, 0) /* UDP */);
- ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SMBV1,
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_DANGEROUS, NDPI_PROTOCOL_SMBV1,
0 /* can_have_a_subprotocol */, no_master,
no_master, "SMBv1", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,
ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
@@ -1097,10 +1100,10 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp
ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
- custom_master[0] = NDPI_PROTOCOL_SSL, custom_master[1] = NDPI_PROTOCOL_UNKNOWN;
- ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SSL_NO_CERT,
+ custom_master[0] = NDPI_PROTOCOL_TLS, custom_master[1] = NDPI_PROTOCOL_UNKNOWN;
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TLS_NO_CERT,
1 /* can_have_a_subprotocol */, custom_master,
- no_master, "SSL_No_Cert", NDPI_PROTOCOL_CATEGORY_WEB,
+ no_master, "TLS_No_Cert", NDPI_PROTOCOL_CATEGORY_WEB,
ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_IRC,
@@ -1241,10 +1244,10 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp
ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
- custom_master[0] = NDPI_PROTOCOL_SSL_NO_CERT, custom_master[1] = NDPI_PROTOCOL_UNKNOWN;
- ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_SSL,
+ custom_master[0] = NDPI_PROTOCOL_TLS_NO_CERT, custom_master[1] = NDPI_PROTOCOL_UNKNOWN;
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_TLS,
1 /* can_have_a_subprotocol */, no_master,
- custom_master, "SSL", NDPI_PROTOCOL_CATEGORY_WEB,
+ custom_master, "TLS", NDPI_PROTOCOL_CATEGORY_WEB,
ndpi_build_default_ports(ports_a, 443, 3001 /* ntop */, 0, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SSH,
@@ -1749,7 +1752,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 +1771,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] != '.')
@@ -2288,7 +2292,7 @@ int ndpi_get_custom_category_match(struct ndpi_detection_module_struct *ndpi_str
if(!ndpi_struct->custom_categories.categories_loaded)
return -1;
-
+
snprintf(ipbuf, sizeof(ipbuf)-1, "%s", name_or_ip);
ptr = strrchr(ipbuf, '/');
@@ -2337,6 +2341,9 @@ void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_struct
if(ndpi_struct->ookla_cache)
ndpi_lru_free_cache(ndpi_struct->ookla_cache);
+ if(ndpi_struct->stun_cache)
+ ndpi_lru_free_cache(ndpi_struct->stun_cache);
+
if(ndpi_struct->protocols_ptree)
ndpi_Destroy_Patricia((patricia_tree_t*)ndpi_struct->protocols_ptree, free_ptree_data);
@@ -2810,8 +2817,8 @@ void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *n
/* STARCRAFT */
init_starcraft_dissector(ndpi_struct, &a, detection_bitmask);
- /* SSL */
- init_ssl_dissector(ndpi_struct, &a, detection_bitmask);
+ /* TLS */
+ init_tls_dissector(ndpi_struct, &a, detection_bitmask);
/* STUN */
init_stun_dissector(ndpi_struct, &a, detection_bitmask);
@@ -3630,125 +3637,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;
+ const struct ndpi_tcphdr *tcph = packet->tcp;
+ const struct ndpi_udphdr *udph = flow->packet.udp;
- if (!flow) {
- return;
- }
+ 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(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(tcph != NULL) {
+ /* reset retried bytes here before setting it */
+ packet->num_retried_bytes = 0;
- if(!ndpi_struct->direction_detect_disable)
- packet->packet_direction = (ntohs(tcph->source) < ntohs(tcph->dest)) ? 1 : 0;
+ if(!ndpi_struct->direction_detect_disable)
+ packet->packet_direction = (ntohs(tcph->source) < ntohs(tcph->dest)) ? 1 : 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);
-
- 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;
+ }
+ 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;
}
- } 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 == 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;
+ }
}
}
@@ -3785,7 +3791,7 @@ void check_ndpi_other_flow_func(struct ndpi_detection_module_struct *ndpi_struct
if((func != ndpi_struct->callback_buffer_non_tcp_udp[a].func)
&& (ndpi_struct->callback_buffer_non_tcp_udp[a].ndpi_selection_bitmask & *ndpi_selection_packet) ==
ndpi_struct->callback_buffer_non_tcp_udp[a].ndpi_selection_bitmask
- &&
+ &&
NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask,
ndpi_struct->callback_buffer_non_tcp_udp[a].excluded_protocol_bitmask) == 0
&& NDPI_BITMASK_COMPARE(ndpi_struct->callback_buffer_non_tcp_udp[a].detection_bitmask,
@@ -3938,7 +3944,7 @@ u_int16_t ndpi_guess_host_protocol_id(struct ndpi_detection_module_struct *ndpi_
struct in_addr addr;
addr.s_addr = flow->packet.iph->saddr;
-
+
/* guess host protocol */
ret = ndpi_network_ptree_match(ndpi_struct, &addr);
@@ -4026,9 +4032,13 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st
if(flow->guessed_protocol_id == NDPI_PROTOCOL_STUN)
goto check_stun_export;
+ else if((flow->guessed_protocol_id == NDPI_PROTOCOL_HANGOUT_DUO)
+ || (flow->guessed_protocol_id == NDPI_PROTOCOL_MESSENGER)
+ || (flow->guessed_protocol_id == NDPI_PROTOCOL_WHATSAPP_VOICE))
+ ndpi_set_detected_protocol(ndpi_struct, flow, flow->guessed_protocol_id, NDPI_PROTOCOL_UNKNOWN);
else if((flow->l4.tcp.ssl_seen_client_cert == 1)
&& (flow->protos.stun_ssl.ssl.client_certificate[0] != '\0')) {
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SSL, NDPI_PROTOCOL_UNKNOWN);
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_TLS, NDPI_PROTOCOL_UNKNOWN);
} else {
ndpi_protocol ret_g = ndpi_get_partial_detection(ndpi_struct, flow);
@@ -4042,7 +4052,7 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st
if((flow->guessed_protocol_id == NDPI_PROTOCOL_UNKNOWN)
&& (flow->packet.l4_protocol == IPPROTO_TCP)
&& (flow->l4.tcp.ssl_stage > 1))
- flow->guessed_protocol_id = NDPI_PROTOCOL_SSL_NO_CERT;
+ flow->guessed_protocol_id = NDPI_PROTOCOL_TLS_NO_CERT;
guessed_protocol_id = flow->guessed_protocol_id, guessed_host_protocol_id = flow->guessed_host_protocol_id;
@@ -4102,10 +4112,11 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st
// if(/* (flow->protos.stun_ssl.stun.num_processed_pkts >= NDPI_MIN_NUM_STUN_DETECTION) */
if(flow->protos.stun_ssl.stun.num_processed_pkts && flow->protos.stun_ssl.stun.is_skype) {
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE_CALL, NDPI_PROTOCOL_SKYPE);
- } else
+ } else {
ndpi_set_detected_protocol(ndpi_struct, flow,
flow->guessed_host_protocol_id,
NDPI_PROTOCOL_STUN);
+ }
}
}
@@ -4416,7 +4427,9 @@ void ndpi_fill_protocol_category(struct ndpi_detection_module_struct *ndpi_struc
if((flow->l4.tcp.ssl_seen_client_cert == 1) && (flow->protos.stun_ssl.ssl.client_certificate[0] != '\0')) {
unsigned long id;
- int rc = ndpi_match_custom_category(ndpi_struct, (char *)flow->protos.stun_ssl.ssl.client_certificate, &id);
+ int rc = ndpi_match_custom_category(ndpi_struct,
+ (char *)flow->protos.stun_ssl.ssl.client_certificate,
+ &id);
if(rc == 0) {
flow->category = ret->category = (ndpi_protocol_category_t)id;
@@ -4460,8 +4473,8 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
*/
if(flow->check_extra_packets
/*
- && ((flow->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL)
- || (flow->detected_protocol_stack[1] == NDPI_PROTOCOL_SSL))
+ && ((flow->detected_protocol_stack[0] == NDPI_PROTOCOL_TLS)
+ || (flow->detected_protocol_stack[1] == NDPI_PROTOCOL_TLS))
*/
) {
ndpi_process_extra_packet(ndpi_struct, flow, packet, packetlen, current_tick_l, src, dst);
@@ -4547,8 +4560,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
@@ -4579,7 +4590,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
addr.s_addr = flow->packet.iph->saddr;
flow->guessed_host_protocol_id = ndpi_network_ptree_match(ndpi_struct, &addr);
-
+
if(flow->guessed_host_protocol_id == NDPI_PROTOCOL_UNKNOWN) {
addr.s_addr = flow->packet.iph->daddr;
flow->guessed_host_protocol_id = ndpi_network_ptree_match(ndpi_struct, &addr);
@@ -4598,16 +4609,16 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
for(i=0; i<2; i++) {
u_int16_t port = (i == 0) ? ntohs(flow->packet.tcp->dest) : ntohs(flow->packet.tcp->source);
-
+
switch(port) {
case 80:
ret.master_protocol = NDPI_PROTOCOL_HTTP;
break;
case 443:
- ret.master_protocol = NDPI_PROTOCOL_SSL; /* QUIC could also match */
+ ret.master_protocol = NDPI_PROTOCOL_TLS; /* QUIC could also match */
break;
}
-
+
if(ret.master_protocol != NDPI_PROTOCOL_UNKNOWN)
break;
}
@@ -5594,7 +5605,7 @@ ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct
else {
ret.app_protocol = rc;
- if(rc == NDPI_PROTOCOL_SSL)
+ if(rc == NDPI_PROTOCOL_TLS)
goto check_guessed_skype;
else {
ret.category = ndpi_get_proto_category(ndpi_struct, ret);
@@ -5928,7 +5939,7 @@ int ndpi_match_string_subprotocol(struct ndpi_detection_module_struct *ndpi_stru
ret_match->protocol_id = match.number,
ret_match->protocol_category = match.category,
ret_match->protocol_breed = match.breed;
-
+
return(match.number);
}
@@ -6095,23 +6106,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
@@ -6178,7 +6191,8 @@ struct ndpi_lru_cache* ndpi_lru_cache_init(u_int32_t num_entries) {
if(!c) return(NULL);
- c->entries = (u_int32_t*)calloc(num_entries, sizeof(u_int32_t));
+ c->entries = (struct ndpi_lru_cache_entry*)calloc(num_entries,
+ sizeof(struct ndpi_lru_cache_entry));
if(!c->entries) {
free(c);
@@ -6194,21 +6208,23 @@ void ndpi_lru_free_cache(struct ndpi_lru_cache *c) {
free(c);
}
-
-u_int8_t ndpi_lru_find_cache(struct ndpi_lru_cache *c, u_int32_t key, u_int8_t clean_key_when_found) {
+u_int8_t ndpi_lru_find_cache(struct ndpi_lru_cache *c, u_int32_t key, u_int16_t *value, u_int8_t clean_key_when_found) {
u_int32_t slot = key % c->num_entries;
- if(c->entries[slot] == key) {
- if(clean_key_when_found) c->entries[slot] = 0;
+ if(c->entries[slot].is_full) {
+ *value = c->entries[slot].value;
+ if(clean_key_when_found) c->entries[slot].is_full = 0;
return(1);
} else
return(0);
}
-void ndpi_lru_add_to_cache(struct ndpi_lru_cache *c, u_int32_t key) {
+void ndpi_lru_add_to_cache(struct ndpi_lru_cache *c, u_int32_t key, u_int16_t value) {
u_int32_t slot = key % c->num_entries;
- c->entries[slot] = key;
+ c->entries[slot].is_full = 1,
+ c->entries[slot].key = key,
+ c->entries[slot].value = value;
}
/* ******************************************************************** */
@@ -6236,4 +6252,3 @@ int ndpi_flowv6_flow_hash(u_int8_t l4_proto, struct ndpi_in6_addr *src_ip, struc
}
/* **************************************** */
-
diff --git a/src/lib/ndpi_serializer.c b/src/lib/ndpi_serializer.c
new file mode 100644
index 000000000..a6546a909
--- /dev/null
+++ b/src/lib/ndpi_serializer.c
@@ -0,0 +1,1107 @@
+/*
+ * ndpi_serializer.c
+ *
+ * Copyright (C) 2011-19 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "ndpi_config.h"
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include "ndpi_api.h"
+#include "ndpi_config.h"
+
+#include <time.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
+#include <sys/endian.h>
+#endif
+
+/* ********************************** */
+
+static u_int64_t ndpi_htonll(u_int64_t v) {
+ union { u_int32_t lv[2]; u_int64_t llv; } u;
+ u.lv[0] = htonl(v >> 32);
+ u.lv[1] = htonl(v & 0xFFFFFFFFULL);
+ return u.llv;
+}
+
+/* ********************************** */
+
+static u_int64_t ndpi_ntohll(u_int64_t v) {
+ union { u_int32_t lv[2]; u_int64_t llv; } u;
+ u.llv = v;
+ return ((u_int64_t)ntohl(u.lv[0]) << 32) | (u_int64_t)ntohl(u.lv[1]);
+}
+
+/* ********************************** */
+
+/*
+ * Escapes a string to be suitable for a JSON value, adding double quotes, and terminating the string with a null byte.
+ * It is recommended to provide a destination buffer (dst) which is as large as double the source buffer (src) at least.
+ * Upon successful return, these functions return the number of characters printed (excluding the null byte used to terminate the string).
+ */
+static int ndpi_json_string_escape(const char *src, int src_len, char *dst, int dst_max_len) {
+ char c = 0;
+ int i, j = 0;
+
+ dst[j++] = '"';
+
+ for (i = 0; i < src_len && j < dst_max_len; i++) {
+
+ c = src[i];
+
+ switch (c) {
+ case '\\':
+ case '"':
+ case '/':
+ dst[j++] = '\\';
+ dst[j++] = c;
+ break;
+ case '\b':
+ dst[j++] = '\\';
+ dst[j++] = 'b';
+ break;
+ case '\t':
+ dst[j++] = '\\';
+ dst[j++] = 't';
+ break;
+ case '\n':
+ dst[j++] = '\\';
+ dst[j++] = 'n';
+ break;
+ case '\f':
+ dst[j++] = '\\';
+ dst[j++] = 'f';
+ break;
+ case '\r':
+ dst[j++] = '\\';
+ dst[j++] = 'r';
+ break;
+ default:
+ if(c < ' ')
+ ; /* non printable */
+ else
+ dst[j++] = c;
+ }
+ }
+
+ dst[j++] = '"';
+ dst[j+1] = '\0';
+
+ return j;
+}
+
+/* ********************************** */
+
+void ndpi_reset_serializer(ndpi_serializer *_serializer) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ u_int32_t buff_diff;
+
+ serializer->size_used = 0;
+ buff_diff = serializer->buffer_size - serializer->size_used;
+
+ /* Note: please keep a space at the beginning as it is used for arrays when an end-of-record is used */
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff, " {}");
+ } else if(serializer->fmt == ndpi_serialization_format_csv)
+ serializer->size_used = 0;
+ else /* TLV */
+ serializer->size_used = 2 * sizeof(u_int8_t);
+}
+
+/* ********************************** */
+
+int ndpi_init_serializer(ndpi_serializer *_serializer,
+ ndpi_serialization_format fmt) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+
+ memset(serializer, 0, sizeof(ndpi_private_serializer));
+
+ serializer->buffer_size = 8192;
+ serializer->buffer = (u_int8_t *) malloc(serializer->buffer_size * sizeof(u_int8_t));
+
+ if(serializer->buffer == NULL)
+ return(-1);
+
+ serializer->fmt = fmt;
+
+ serializer->buffer[0] = 1; /* version */
+ serializer->buffer[1] = (u_int8_t) fmt;
+
+ serializer->csv_separator[0] = ',';
+ serializer->csv_separator[1] = '\0';
+
+ ndpi_reset_serializer(_serializer);
+
+ return(1);
+}
+
+/* ********************************** */
+
+char* ndpi_serializer_get_buffer(ndpi_serializer *_serializer, u_int32_t *buffer_len) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+ char *buf = (char*)serializer->buffer;
+
+ /* NULL terminate the buffer if there is space available */
+ if(serializer->buffer_size > serializer->size_used)
+ serializer->buffer[serializer->size_used] = '\0';
+
+ *buffer_len = serializer->size_used;
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ while(buf[0] == '\0')
+ buf++, *buffer_len = *buffer_len - 1 ;
+ }
+
+ return(buf);
+}
+
+/* ********************************** */
+
+u_int32_t ndpi_serializer_get_buffer_len(ndpi_serializer *_serializer) {
+ return(((ndpi_private_serializer*)_serializer)->size_used);
+}
+
+ /* ********************************** */
+
+void ndpi_serializer_set_csv_separator(ndpi_serializer *_serializer, char separator) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+
+ serializer->csv_separator[0] = separator;
+}
+
+/* ********************************** */
+
+void ndpi_term_serializer(ndpi_serializer *_serializer) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+
+ if(serializer->buffer) {
+ free(serializer->buffer);
+ serializer->buffer_size = 0;
+ serializer->buffer = NULL;
+ }
+}
+
+/* ********************************** */
+
+static int ndpi_extend_serializer_buffer(ndpi_serializer *_serializer, u_int32_t min_len) {
+ u_int32_t new_size;
+ void *r;
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+
+ if(min_len < 1024)
+ min_len = 1024;
+
+ new_size = serializer->buffer_size + min_len;
+
+ r = realloc((void *) serializer->buffer, new_size);
+
+ if(r == NULL)
+ return(-1);
+
+ serializer->buffer = r;
+ serializer->buffer_size = new_size;
+
+ return(0);
+}
+
+/* ********************************** */
+
+static void ndpi_serialize_single_uint32(ndpi_serializer *_serializer,
+ u_int32_t s) {
+ u_int32_t v = htonl(s);
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+
+ memcpy(&serializer->buffer[serializer->size_used], &v, sizeof(u_int32_t));
+ serializer->size_used += sizeof(u_int32_t);
+}
+
+/* ********************************** */
+
+static void ndpi_serialize_single_uint64(ndpi_serializer *_serializer,
+ u_int64_t s) {
+ u_int64_t v = ndpi_htonll(s);
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+
+ memcpy(&serializer->buffer[serializer->size_used], &v, sizeof(u_int64_t));
+ serializer->size_used += sizeof(u_int64_t);
+}
+
+/* ********************************** */
+
+/* TODO: fix portability across platforms */
+static void ndpi_serialize_single_float(ndpi_serializer *_serializer, float s) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+
+ memcpy(&serializer->buffer[serializer->size_used], &s, sizeof(s));
+ serializer->size_used += sizeof(float);
+}
+
+/* ********************************** */
+
+static void ndpi_serialize_single_string(ndpi_serializer *_serializer,
+ const char *s, u_int16_t slen) {
+ u_int16_t l = htons(slen);
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+
+ memcpy(&serializer->buffer[serializer->size_used], &l, sizeof(u_int16_t));
+ serializer->size_used += sizeof(u_int16_t);
+
+ if(slen > 0)
+ memcpy(&serializer->buffer[serializer->size_used], s, slen);
+
+ serializer->size_used += slen;
+}
+
+/* ********************************** */
+
+static void ndpi_deserialize_single_uint32(ndpi_serializer *_deserializer,
+ u_int32_t *s) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ *s = ntohl(*((u_int32_t *) &deserializer->buffer[deserializer->size_used]));
+ deserializer->size_used += sizeof(u_int32_t);
+}
+
+/* ********************************** */
+
+static void ndpi_deserialize_single_int32(ndpi_serializer *_deserializer,
+ int32_t *s) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ *s = ntohl(*((int32_t *) &deserializer->buffer[deserializer->size_used]));
+ deserializer->size_used += sizeof(int32_t);
+}
+
+/* ********************************** */
+
+static void ndpi_deserialize_single_uint64(ndpi_serializer *_deserializer,
+ u_int64_t *s) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ *s = ndpi_ntohll(*(u_int64_t*)&deserializer->buffer[deserializer->size_used]);
+ deserializer->size_used += sizeof(u_int64_t);
+}
+
+/* ********************************** */
+
+static void ndpi_deserialize_single_int64(ndpi_serializer *_deserializer,
+ int64_t *s) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ *s = ndpi_ntohll(*(int64_t*)&deserializer->buffer[deserializer->size_used]);
+ deserializer->size_used += sizeof(int64_t);
+}
+
+/* ********************************** */
+
+/* TODO: fix portability across platforms */
+static void ndpi_deserialize_single_float(ndpi_serializer *_deserializer,
+ float *s) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ *s = *(float*)&deserializer->buffer[deserializer->size_used];
+ deserializer->size_used += sizeof(float);
+}
+
+/* ********************************** */
+
+static void ndpi_deserialize_single_string(ndpi_serializer *_deserializer,
+ ndpi_string *v) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ v->str_len = ntohs(*((u_int16_t *) &deserializer->buffer[deserializer->size_used]));
+ deserializer->size_used += sizeof(u_int16_t);
+
+ v->str = (char *) &deserializer->buffer[deserializer->size_used];
+ deserializer->size_used += v->str_len;
+}
+
+/* ********************************** */
+
+int ndpi_serialize_end_of_record(ndpi_serializer *_serializer) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+ u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
+ u_int16_t needed =
+ sizeof(u_int8_t) /* type */;
+
+ if(serializer->fmt == ndpi_serialization_format_json)
+ needed += 1;
+
+ if(buff_diff < needed) {
+ if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ return(-1);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ }
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ if(!(serializer->status & NDPI_SERIALIZER_STATUS_ARRAY)) {
+ // serializer->json_buffer[0] = '[';
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used],
+ buff_diff, "]");
+ }
+ serializer->status |= NDPI_SERIALIZER_STATUS_ARRAY | NDPI_SERIALIZER_STATUS_EOR;
+ serializer->status &= ~NDPI_SERIALIZER_STATUS_COMMA;
+ } else {
+ serializer->buffer[serializer->size_used++] = ndpi_serialization_end_of_record;
+ }
+
+ return(0);
+}
+
+/* ********************************** */
+
+static void ndpi_serialize_json_pre(ndpi_serializer *_serializer) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+
+ if(serializer->status & NDPI_SERIALIZER_STATUS_EOR) {
+ serializer->size_used--; /* Remove ']' */
+ serializer->status &= ~NDPI_SERIALIZER_STATUS_EOR;
+ serializer->buffer[serializer->size_used++] = ',';
+ serializer->buffer[serializer->size_used++] = '{';
+ } else {
+ if(serializer->status & NDPI_SERIALIZER_STATUS_ARRAY)
+ serializer->size_used--; /* Remove ']'*/
+ serializer->size_used--; /* Remove '}'*/
+ }
+ if(serializer->status & NDPI_SERIALIZER_STATUS_COMMA)
+ serializer->buffer[serializer->size_used++] = ',';
+}
+
+/* ********************************** */
+
+static void ndpi_serialize_json_post(ndpi_serializer *_serializer) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+
+ serializer->buffer[serializer->size_used++] = '}';
+ if(serializer->status & NDPI_SERIALIZER_STATUS_ARRAY)
+ serializer->buffer[serializer->size_used++] = ']';
+
+ serializer->status |= NDPI_SERIALIZER_STATUS_COMMA;
+}
+
+/* ********************************** */
+
+int ndpi_serialize_uint32_uint32(ndpi_serializer *_serializer,
+ u_int32_t key, u_int32_t value) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+ u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
+ u_int16_t needed =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int32_t) /* key */ +
+ sizeof(u_int32_t);
+
+ if(serializer->fmt == ndpi_serialization_format_json)
+ needed += 24;
+
+ if(buff_diff < needed) {
+ if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ return(-1);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ }
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ ndpi_serialize_json_pre(_serializer);
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ "\"%u\":%u", key, value);
+ ndpi_serialize_json_post(_serializer);
+ } else if(serializer->fmt == ndpi_serialization_format_csv) {
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ "%s%u", (serializer->size_used > 0) ? serializer->csv_separator : "", value);
+ } else {
+ serializer->buffer[serializer->size_used++] = ndpi_serialization_uint32_uint32;
+
+ ndpi_serialize_single_uint32(_serializer, key);
+ ndpi_serialize_single_uint32(_serializer, value);
+ }
+
+ return(0);
+}
+
+/* ********************************** */
+
+int ndpi_serialize_uint32_uint64(ndpi_serializer *_serializer,
+ u_int32_t key, u_int64_t value) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+ u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
+ u_int16_t needed =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int32_t) /* key */ +
+ sizeof(u_int64_t);
+
+ if(serializer->fmt == ndpi_serialization_format_json)
+ needed += 32;
+
+ if(buff_diff < needed) {
+ if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ return(-1);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ }
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ ndpi_serialize_json_pre(_serializer);
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ "\"%u\":%llu", key, (unsigned long long)value);
+ ndpi_serialize_json_post(_serializer);
+ } else if(serializer->fmt == ndpi_serialization_format_csv) {
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ "%s%llu",
+ (serializer->size_used > 0) ? serializer->csv_separator : "",
+ (unsigned long long)value);
+
+ } else {
+ serializer->buffer[serializer->size_used++] = ndpi_serialization_uint32_uint64;
+
+ ndpi_serialize_single_uint32(_serializer, key);
+ ndpi_serialize_single_uint64(_serializer, value);
+ }
+
+ return(0);
+}
+
+/* ********************************** */
+
+int ndpi_serialize_uint32_string(ndpi_serializer *_serializer,
+ u_int32_t key, const char *_value) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+ const char *value = _value ? _value : "";
+ u_int16_t slen = strlen(value);
+ u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
+ u_int32_t needed =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int32_t) /* key */ +
+ sizeof(u_int16_t) /* len */ +
+ slen;
+
+ if(serializer->fmt == ndpi_serialization_format_json)
+ needed += 24 + slen;
+
+ if(buff_diff < needed) {
+ if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ return(-1);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ }
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ ndpi_serialize_json_pre(_serializer);
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ "\"%u\":", key);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ serializer->size_used += ndpi_json_string_escape(value, slen,
+ (char *) &serializer->buffer[serializer->size_used], buff_diff);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ ndpi_serialize_json_post(_serializer);
+ } else if(serializer->fmt == ndpi_serialization_format_csv) {
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ "%s%s", (serializer->size_used > 0) ? serializer->csv_separator : "", value);
+ } else {
+ serializer->buffer[serializer->size_used++] = ndpi_serialization_uint32_string;
+
+ ndpi_serialize_single_uint32(_serializer, key);
+ ndpi_serialize_single_string(_serializer, value, slen);
+ }
+
+ return(0);
+}
+
+/* ********************************** */
+
+int ndpi_serialize_string_int32(ndpi_serializer *_serializer,
+ const char *key, int32_t value) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+ u_int16_t klen = strlen(key);
+ u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
+ u_int32_t needed =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int16_t) /* key len */ +
+ klen /* key */ +
+ sizeof(u_int32_t);
+
+ if(serializer->fmt == ndpi_serialization_format_json)
+ needed += 16 + klen;
+
+ if(buff_diff < needed) {
+ if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ return(-1);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ }
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ ndpi_serialize_json_pre(_serializer);
+ serializer->size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer[serializer->size_used], buff_diff);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ ":%d", value);
+ ndpi_serialize_json_post(_serializer);
+ } else if(serializer->fmt == ndpi_serialization_format_csv) {
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ "%s%d", (serializer->size_used > 0) ? serializer->csv_separator : "", value);
+ } else {
+ serializer->buffer[serializer->size_used++] = ndpi_serialization_string_int32;
+
+ ndpi_serialize_single_string(_serializer, key, klen);
+ ndpi_serialize_single_uint32(_serializer, value);
+ }
+
+ return(0);
+}
+
+/* ********************************** */
+
+int ndpi_serialize_string_int64(ndpi_serializer *_serializer,
+ const char *key, int64_t value) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+ u_int16_t klen = strlen(key);
+ u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
+ u_int32_t needed =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int16_t) /* key len */ +
+ klen /* key */ +
+ sizeof(u_int32_t);
+
+ if(serializer->fmt == ndpi_serialization_format_json)
+ needed += 16 + klen;
+
+ if(buff_diff < needed) {
+ if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ return(-1);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ }
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ ndpi_serialize_json_pre(_serializer);
+ serializer->size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer[serializer->size_used], buff_diff);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ ":%lld", (long long int)value);
+ ndpi_serialize_json_post(_serializer);
+ } else if(serializer->fmt == ndpi_serialization_format_csv) {
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ "%s%lld", (serializer->size_used > 0) ? serializer->csv_separator : "",
+ (long long int)value);
+ } else {
+ serializer->buffer[serializer->size_used++] = ndpi_serialization_string_int64;
+
+ ndpi_serialize_single_string(_serializer, key, klen);
+ ndpi_serialize_single_uint32(_serializer, value);
+ }
+
+ return(0);
+}
+
+/* ********************************** */
+
+int ndpi_serialize_string_uint32(ndpi_serializer *_serializer,
+ const char *key, u_int32_t value) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+ u_int16_t klen = strlen(key);
+ u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
+ u_int32_t needed =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int16_t) /* key len */ +
+ klen /* key */ +
+ sizeof(u_int32_t);
+
+ if(serializer->fmt == ndpi_serialization_format_json)
+ needed += 16 + klen;
+
+ if(buff_diff < needed) {
+ if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ return(-1);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ }
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ ndpi_serialize_json_pre(_serializer);
+ serializer->size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer[serializer->size_used], buff_diff);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ ":%u", value);
+ ndpi_serialize_json_post(_serializer);
+ } else if(serializer->fmt == ndpi_serialization_format_csv) {
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ "%s%u", (serializer->size_used > 0) ? serializer->csv_separator : "", value);
+ } else {
+ serializer->buffer[serializer->size_used++] = ndpi_serialization_string_uint32;
+
+ ndpi_serialize_single_string(_serializer, key, klen);
+ ndpi_serialize_single_uint32(_serializer, value);
+ }
+
+ return(0);
+}
+
+/* ********************************** */
+
+int ndpi_serialize_string_uint32_format(ndpi_serializer *_serializer,
+ const char *key, u_int32_t value,
+ const char *format) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ /*
+ JSON supports base 10 numbers only
+ http://cjihrig.com/blog/json-overview/
+ */
+
+ return(ndpi_serialize_string_uint32(_serializer, key, value));
+ } else
+ return(ndpi_serialize_string_uint32_format(_serializer, key, value, format));
+}
+
+/* ********************************** */
+
+int ndpi_serialize_string_uint64(ndpi_serializer *_serializer,
+ const char *key, u_int64_t value) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+ u_int16_t klen = strlen(key);
+ u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
+ u_int32_t needed =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int16_t) /* key len */ +
+ klen /* key */ +
+ sizeof(u_int64_t);
+
+ if(serializer->fmt == ndpi_serialization_format_json)
+ needed += 32 + klen;
+
+ if(buff_diff < needed) {
+ if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ return(-1);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ }
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ ndpi_serialize_json_pre(_serializer);
+ serializer->size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer[serializer->size_used], buff_diff);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ ":%llu", (unsigned long long)value);
+ ndpi_serialize_json_post(_serializer);
+ } else if(serializer->fmt == ndpi_serialization_format_csv) {
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ "%s%llu", (serializer->size_used > 0) ? serializer->csv_separator : "",
+ (unsigned long long)value);
+ } else {
+ serializer->buffer[serializer->size_used++] = ndpi_serialization_string_uint64;
+
+ ndpi_serialize_single_string(_serializer, key, klen);
+ ndpi_serialize_single_uint64(_serializer, value);
+ }
+
+ return(0);
+}
+
+/* ********************************** */
+
+int ndpi_serialize_string_float(ndpi_serializer *_serializer,
+ const char *key, float value,
+ const char *format /* e.f. "%.2f" */) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+ u_int16_t klen = strlen(key);
+ u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
+ u_int32_t needed =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int16_t) /* key len */ +
+ klen /* key */ +
+ sizeof(float);
+
+ if(serializer->fmt == ndpi_serialization_format_json)
+ needed += 32 + klen;
+
+ if(buff_diff < needed) {
+ if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ return(-1);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ }
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ ndpi_serialize_json_pre(_serializer);
+ serializer->size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer[serializer->size_used], buff_diff);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+
+ serializer->buffer[serializer->size_used] = ':';
+ serializer->size_used++;
+
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff, format, value);
+
+ ndpi_serialize_json_post(_serializer);
+ } else if(serializer->fmt == ndpi_serialization_format_csv) {
+ if(serializer->size_used > 0)
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff, "%s", serializer->csv_separator);
+
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff, format, value);
+ } else {
+ serializer->buffer[serializer->size_used++] = ndpi_serialization_string_float;
+
+ ndpi_serialize_single_string(_serializer, key, klen);
+ ndpi_serialize_single_float(_serializer, value);
+ }
+
+ return(0);
+}
+
+/* ********************************** */
+
+int ndpi_serialize_string_string(ndpi_serializer *_serializer,
+ const char *key, const char *_value) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+ const char *value = _value ? _value : "";
+ u_int16_t klen = strlen(key), vlen = strlen(value);
+ u_int32_t needed =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int16_t) /* key len */ +
+ klen +
+ sizeof(u_int16_t) /* len */ +
+ vlen;
+ u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
+
+ if(serializer->fmt == ndpi_serialization_format_json)
+ needed += 16 + klen + vlen;
+
+ if(buff_diff < needed) {
+ if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ return(-1);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ }
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ ndpi_serialize_json_pre(_serializer);
+ serializer->size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer[serializer->size_used], buff_diff);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff, ":");
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ serializer->size_used += ndpi_json_string_escape(value, vlen,
+ (char *) &serializer->buffer[serializer->size_used], buff_diff);
+ buff_diff = serializer->buffer_size - serializer->size_used;
+ ndpi_serialize_json_post(_serializer);
+ } else if(serializer->fmt == ndpi_serialization_format_csv) {
+ serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
+ "%s%s", (serializer->size_used > 0) ? serializer->csv_separator : "",
+ value);
+ } else {
+ serializer->buffer[serializer->size_used++] = ndpi_serialization_string_string;
+
+ ndpi_serialize_single_string(_serializer, key, klen);
+ ndpi_serialize_single_string(_serializer, value, vlen);
+ }
+
+ return(0);
+}
+
+/* ********************************** */
+/* ********************************** */
+
+int ndpi_init_deserializer_buf(ndpi_deserializer *_deserializer,
+ u_int8_t *serialized_buffer,
+ u_int32_t serialized_buffer_len) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ if(serialized_buffer_len < (2 * sizeof(u_int8_t)))
+ return(-1);
+
+ deserializer->buffer = serialized_buffer;
+
+ if(deserializer->buffer[0] != 1)
+ return(-2); /* Invalid version */
+
+ deserializer->buffer_size = serialized_buffer_len;
+ deserializer->fmt = deserializer->buffer[1];
+ ndpi_reset_serializer(_deserializer);
+
+ return(0);
+}
+
+/* ********************************** */
+
+int ndpi_init_deserializer(ndpi_deserializer *deserializer,
+ ndpi_serializer *_serializer) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+
+ return(ndpi_init_deserializer_buf(deserializer,
+ serializer->buffer,
+ serializer->size_used));
+}
+
+/* ********************************** */
+
+ndpi_serialization_element_type ndpi_deserialize_get_nextitem_type(ndpi_deserializer *_deserializer) {
+ ndpi_serialization_element_type et;
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ if(deserializer->size_used >= deserializer->buffer_size)
+ return(ndpi_serialization_unknown);
+
+ et = (ndpi_serialization_element_type) deserializer->buffer[deserializer->size_used];
+
+ return et;
+}
+
+/* ********************************** */
+
+int ndpi_deserialize_end_of_record(ndpi_deserializer *_deserializer) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ if(ndpi_deserialize_get_nextitem_type(_deserializer) == ndpi_serialization_end_of_record) {
+ u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
+ u_int16_t expected =
+ sizeof(u_int8_t) /* type */;
+
+ if(buff_diff < expected) return(-2);
+
+ deserializer->size_used++; /* Skip element type */
+
+ return(0);
+ } else
+ return(-1);
+}
+
+/* ********************************** */
+
+int ndpi_deserialize_uint32_uint32(ndpi_deserializer *_deserializer,
+ u_int32_t *key, u_int32_t *value) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ if(ndpi_deserialize_get_nextitem_type(_deserializer) == ndpi_serialization_uint32_uint32) {
+ u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
+ u_int16_t expected =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int32_t) /* key */ +
+ sizeof(u_int32_t);
+
+ if(buff_diff < expected) return(-2);
+
+ deserializer->size_used++; /* Skip element type */
+ ndpi_deserialize_single_uint32(_deserializer, key);
+ ndpi_deserialize_single_uint32(_deserializer, value);
+
+ return(0);
+ } else
+ return(-1);
+}
+
+/* ********************************** */
+
+int ndpi_deserialize_uint32_uint64(ndpi_deserializer *_deserializer,
+ u_int32_t *key, u_int64_t *value) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ if(ndpi_deserialize_get_nextitem_type(_deserializer) == ndpi_serialization_uint32_uint64) {
+ u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
+ u_int16_t expected =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int32_t) /* key */ +
+ sizeof(u_int64_t);
+
+ if(buff_diff < expected) return(-2);
+
+ deserializer->size_used++; /* Skip element type */
+ ndpi_deserialize_single_uint32(_deserializer, key);
+ ndpi_deserialize_single_uint64(_deserializer, value);
+
+ return(0);
+ } else
+ return(-1);
+}
+
+/* ********************************** */
+
+int ndpi_deserialize_uint32_string(ndpi_deserializer *_deserializer,
+ u_int32_t *key, ndpi_string *value) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ if(ndpi_deserialize_get_nextitem_type(_deserializer) == ndpi_serialization_uint32_string) {
+ u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
+ u_int32_t expected =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int32_t) /* key */ +
+ sizeof(u_int16_t) /* len */;
+
+ if(buff_diff < expected) return(-2);
+
+ deserializer->size_used++; /* Skip element type */
+ ndpi_deserialize_single_uint32(_deserializer, key);
+ ndpi_deserialize_single_string(_deserializer, value);
+
+ return(0);
+ } else
+ return(-1);
+}
+
+/* ********************************** */
+
+int ndpi_deserialize_string_int32(ndpi_deserializer *_deserializer,
+ ndpi_string *key, int32_t *value) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ if(ndpi_deserialize_get_nextitem_type(_deserializer) == ndpi_serialization_string_int32) {
+ u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
+ u_int32_t expected =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int16_t) /* key len */ +
+ sizeof(int32_t);
+
+ if(buff_diff < expected) return(-2);
+
+ deserializer->size_used++; /* Skip element type */
+ ndpi_deserialize_single_string(_deserializer, key);
+ ndpi_deserialize_single_int32(_deserializer, value);
+
+ return(0);
+ } else
+ return(-1);
+}
+
+/* ********************************** */
+
+int ndpi_deserialize_string_int64(ndpi_deserializer *_deserializer,
+ ndpi_string *key, int64_t *value) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ if(ndpi_deserialize_get_nextitem_type(_deserializer) == ndpi_serialization_string_int64) {
+ u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
+ u_int32_t expected =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int16_t) /* key len */ +
+ sizeof(int64_t);
+
+ if(buff_diff < expected) return(-2);
+
+ deserializer->size_used++; /* Skip element type */
+ ndpi_deserialize_single_string(_deserializer, key);
+ ndpi_deserialize_single_int64(_deserializer, value);
+
+ return(0);
+ } else
+ return(-1);
+}
+
+/* ********************************** */
+
+int ndpi_deserialize_string_uint32(ndpi_deserializer *_deserializer,
+ ndpi_string *key, u_int32_t *value) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ if(ndpi_deserialize_get_nextitem_type(_deserializer) == ndpi_serialization_string_uint32) {
+ u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
+ u_int32_t expected =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int16_t) /* key len */ +
+ sizeof(u_int32_t);
+
+ if(buff_diff < expected) return(-2);
+
+ deserializer->size_used++; /* Skip element type */
+ ndpi_deserialize_single_string(_deserializer, key);
+ ndpi_deserialize_single_uint32(_deserializer, value);
+
+ return(0);
+ } else
+ return(-1);
+}
+
+/* ********************************** */
+
+int ndpi_deserialize_string_uint64(ndpi_deserializer *_deserializer,
+ ndpi_string *key, u_int64_t *value) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ if(ndpi_deserialize_get_nextitem_type(_deserializer) == ndpi_serialization_string_uint64) {
+ u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
+ u_int32_t expected =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int16_t) /* key len */ +
+ sizeof(u_int64_t);
+
+ if(buff_diff < expected) return(-2);
+
+ deserializer->size_used++; /* Skip element type */
+ ndpi_deserialize_single_string(_deserializer, key);
+ ndpi_deserialize_single_uint64(_deserializer, value);
+
+ return(0);
+ } else
+ return(-1);
+}
+
+/* ********************************** */
+
+int ndpi_deserialize_string_float(ndpi_deserializer *_deserializer,
+ ndpi_string *key, float *value) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ if(ndpi_deserialize_get_nextitem_type(_deserializer) == ndpi_serialization_string_float) {
+ u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
+ u_int32_t expected =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int16_t) /* key len */ +
+ sizeof(float);
+
+ if(buff_diff < expected) return(-2);
+
+ deserializer->size_used++; /* Skip element type */
+ ndpi_deserialize_single_string(_deserializer, key);
+ ndpi_deserialize_single_float(_deserializer, value);
+
+ return(0);
+ } else
+ return(-1);
+}
+
+/* ********************************** */
+
+int ndpi_deserialize_string_string(ndpi_deserializer *_deserializer,
+ ndpi_string *key, ndpi_string *value) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+
+ if(ndpi_deserialize_get_nextitem_type(_deserializer) == ndpi_serialization_string_string) {
+ u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
+ u_int32_t expected =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int16_t) /* key len */ +
+ sizeof(u_int16_t) /* len */;
+
+ if(buff_diff < expected) return(-2);
+
+ deserializer->size_used++; /* Skip element type */
+ ndpi_deserialize_single_string(_deserializer, key);
+ ndpi_deserialize_single_string(_deserializer, value);
+
+ return(0);
+ } else
+ return(-1);
+}
+
+/* ********************************** */
diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c
index 8959aa05e..14a82065a 100644
--- a/src/lib/ndpi_utils.c
+++ b/src/lib/ndpi_utils.c
@@ -1,5 +1,5 @@
/*
- * ndpi_utils.cc
+ * ndpi_utils.c
*
* Copyright (C) 2011-19 - ntop.org
*
@@ -236,38 +236,38 @@ u_int8_t ndpi_ips_match(u_int32_t src, u_int32_t dst,
* based upon ascii character sequences.
*/
static const u_char charmap[] = {
- '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
- '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
- '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
- '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
- '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
- '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
- '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
- '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
- '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
- '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
- '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
- '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
- '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
- '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
- '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
- '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
- '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
- '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
- '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
- '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
- '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
- '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
- '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+ '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+ '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+ '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+ '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+ '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+ '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+ '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+ '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+ '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+ '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+ '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
+ '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
+ '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
+ '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
+ '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+ '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+ '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+ '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
};
int strcasecmp(const char *s1, const char *s2) {
@@ -304,8 +304,8 @@ int strncasecmp(const char *s1, const char *s2, size_t n) {
/* **************************************** */
u_int8_t ndpi_is_safe_ssl_cipher(u_int32_t cipher) {
- /* https://community.qualys.com/thread/18212-how-does-qualys-determine-the-server-cipher-suites */
- /* INSECURE */
+ /* https://community.qualys.com/thread/18212-how-does-qualys-determine-the-server-cipher-suites */
+ /* INSECURE */
switch(cipher) {
case 0xc011: return(NDPI_CIPHER_INSECURE); /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */
case 0x0005: return(NDPI_CIPHER_INSECURE); /* TLS_RSA_WITH_RC4_128_SHA */
@@ -360,9 +360,9 @@ const char* ndpi_cipher2str(u_int32_t cipher) {
case 0x000019: return("TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA");
case 0x00001a: return("TLS_DH_anon_WITH_DES_CBC_SHA");
case 0x00001b: return("TLS_DH_anon_WITH_3DES_EDE_CBC_SHA");
- case 0x00001c: return("SSL_FORTEZZA_KEA_WITH_NULL_SHA");
- case 0x00001d: return("SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA");
- /* case 0x00001e: return("SSL_FORTEZZA_KEA_WITH_RC4_128_SHA"); */
+ case 0x00001c: return("TLS_FORTEZZA_KEA_WITH_NULL_SHA");
+ case 0x00001d: return("TLS_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA");
+ /* case 0x00001e: return("TLS_FORTEZZA_KEA_WITH_RC4_128_SHA"); */
case 0x00001E: return("TLS_KRB5_WITH_DES_CBC_SHA");
case 0x00001F: return("TLS_KRB5_WITH_3DES_EDE_CBC_SHA");
case 0x000020: return("TLS_KRB5_WITH_RC4_128_SHA");
@@ -576,10 +576,10 @@ const char* ndpi_cipher2str(u_int32_t cipher) {
case 0x00E41D: return("TLS_DHE_PSK_WITH_SALSA20_SHA1");
case 0x00E41E: return("TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1");
case 0x00E41F: return("TLS_DHE_RSA_WITH_SALSA20_SHA1");
- case 0x00fefe: return("SSL_RSA_FIPS_WITH_DES_CBC_SHA");
- case 0x00feff: return("SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA");
- case 0x00ffe0: return("SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA");
- case 0x00ffe1: return("SSL_RSA_FIPS_WITH_DES_CBC_SHA");
+ case 0x00fefe: return("TLS_RSA_FIPS_WITH_DES_CBC_SHA");
+ case 0x00feff: return("TLS_RSA_FIPS_WITH_3DES_EDE_CBC_SHA");
+ case 0x00ffe0: return("TLS_RSA_FIPS_WITH_3DES_EDE_CBC_SHA");
+ case 0x00ffe1: return("TLS_RSA_FIPS_WITH_DES_CBC_SHA");
case 0x010080: return("SSL2_RC4_128_WITH_MD5");
case 0x020080: return("SSL2_RC4_128_EXPORT40_WITH_MD5");
case 0x030080: return("SSL2_RC2_128_CBC_WITH_MD5");
@@ -637,7 +637,7 @@ static int ndpi_find_non_eng_bigrams(struct ndpi_detection_module_struct *ndpi_s
|| ndpi_is_other_char(str[1])
)
return(1);
-
+
s[0] = tolower(str[0]), s[1] = tolower(str[1]), s[2] = '\0';
return(ndpi_match_bigram(ndpi_struct, &ndpi_struct->bigrams_automa, s));
@@ -655,10 +655,10 @@ int ndpi_has_human_readeable_string(struct ndpi_detection_module_struct *ndpi_st
if(buffer_size <= 0)
return(0);
-
+
outbuf_len--;
outbuf[outbuf_len] = '\0';
-
+
for(i=0; i<buffer_size-2; i++) {
if(ndpi_is_valid_char(buffer[i])
&& ndpi_is_valid_char(buffer[i+1])
@@ -687,14 +687,14 @@ int ndpi_has_human_readeable_string(struct ndpi_detection_module_struct *ndpi_st
being_o_idx = o_idx;
outbuf[o_idx] = '\0';
}
-
+
#ifdef PRINT_STRINGS
printf(" [len: %u]%s\n", len, ret ? "<-- HIT" : "");
#endif
if(ret)
break;
-
+
do_cr = 0, len = 0;
}
}
@@ -713,11 +713,13 @@ char* ndpi_ssl_version2str(u_int16_t version) {
static char v[8];
switch(version) {
- case 0x300: return("SSLv3");
- case 0x301: return("TLSv1");
- case 0x302: return("TLSv1.1");
- case 0x303: return("TLSv1.2");
- case 0x304: return("TLSv1.3");
+ case 0x0300: return("SSLv3");
+ case 0x0301: return("TLSv1");
+ case 0x0302: return("TLSv1.1");
+ case 0x0303: return("TLSv1.2");
+ case 0x0304: return("TLSv1.3");
+ case 0xfeff: return("DTLSv1.0");
+ case 0xfefd: return("DTLSv1.2");
}
if((version >= 0x7f00) && (version <= 0x7fff))
@@ -728,826 +730,3 @@ char* ndpi_ssl_version2str(u_int16_t version) {
}
/* ********************************** */
-/* ********************************** */
-
-static u_int64_t ndpi_htonll(u_int64_t v) {
- union { u_int32_t lv[2]; u_int64_t llv; } u;
- u.lv[0] = htonl(v >> 32);
- u.lv[1] = htonl(v & 0xFFFFFFFFULL);
- return u.llv;
-}
-
-/* ********************************** */
-
-static u_int64_t ndpi_ntohll(u_int64_t v) {
- union { u_int32_t lv[2]; u_int64_t llv; } u;
- u.llv = v;
- return ((u_int64_t)ntohl(u.lv[0]) << 32) | (u_int64_t)ntohl(u.lv[1]);
-}
-
-/* ********************************** */
-
-/*
- * Escapes a string to be suitable for a JSON value, adding double quotes, and terminating the string with a null byte.
- * It is recommended to provide a destination buffer (dst) which is as large as double the source buffer (src) at least.
- * Upon successful return, these functions return the number of characters printed (excluding the null byte used to terminate the string).
- */
-static int ndpi_json_string_escape(const char *src, int src_len, char *dst, int dst_max_len) {
- char c = 0;
- int i, j = 0;
-
- dst[j++] = '"';
-
- for (i = 0; i < src_len && j < dst_max_len; i++) {
-
- c = src[i];
-
- switch (c) {
- case '\\':
- case '"':
- case '/':
- dst[j++] = '\\';
- dst[j++] = c;
- break;
- case '\b':
- dst[j++] = '\\';
- dst[j++] = 'b';
- break;
- case '\t':
- dst[j++] = '\\';
- dst[j++] = 't';
- break;
- case '\n':
- dst[j++] = '\\';
- dst[j++] = 'n';
- break;
- case '\f':
- dst[j++] = '\\';
- dst[j++] = 'f';
- break;
- case '\r':
- dst[j++] = '\\';
- dst[j++] = 'r';
- break;
- default:
- if (c < ' ')
- ; /* non printable */
- else
- dst[j++] = c;
- }
- }
-
- dst[j++] = '"';
- dst[j+1] = '\0';
-
- return j;
-}
-
-/* ********************************** */
-
-void ndpi_reset_serializer(ndpi_serializer *serializer) {
- serializer->size_used = 2 * sizeof(u_int8_t);
- if (serializer->fmt == ndpi_serialization_format_json) {
- u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
- /* Note: please keep a space at the beginning as it is used for arrays when an end-of-record is used */
- serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff, " {}");
- }
-}
-
-/* ********************************** */
-
-int ndpi_init_serializer(ndpi_serializer *serializer,
- ndpi_serialization_format fmt) {
- serializer->buffer_size = 8192;
- serializer->buffer = (u_int8_t *) malloc(serializer->buffer_size * sizeof(u_int8_t));
-
- if (serializer->buffer == NULL)
- return(-1);
-
- serializer->fmt = fmt;
-
- serializer->buffer[0] = 1; /* version */
- serializer->buffer[1] = (u_int8_t) fmt;
-
- ndpi_reset_serializer(serializer);
-
- if (fmt == ndpi_serialization_format_json)
- serializer->json_buffer = (char *) &serializer->buffer[2];
-
- return(1);
-}
-
-/* ********************************** */
-
-void ndpi_term_serializer(ndpi_serializer *serializer) {
- if(serializer->buffer) {
- free(serializer->buffer);
- serializer->buffer_size = 0;
- serializer->buffer = NULL;
- }
-}
-
-/* ********************************** */
-
-static int ndpi_extend_serializer_buffer(ndpi_serializer *serializer, u_int32_t min_len) {
- u_int32_t new_size;
- void *r;
-
- if (min_len < 1024)
- min_len = 1024;
-
- new_size = serializer->buffer_size + min_len;
-
- r = realloc((void *) serializer->buffer, new_size);
-
- if(r == NULL)
- return(-1);
-
- serializer->buffer = r;
- serializer->buffer_size = new_size;
-
- return(0);
-}
-
-/* ********************************** */
-
-static void ndpi_serialize_single_uint32(ndpi_serializer *serializer,
- u_int32_t s) {
-
- u_int32_t v = htonl(s);
-
- memcpy(&serializer->buffer[serializer->size_used], &v, sizeof(u_int32_t));
- serializer->size_used += sizeof(u_int32_t);
-}
-
-/* ********************************** */
-
-static void ndpi_serialize_single_uint64(ndpi_serializer *serializer,
- u_int64_t s) {
-
- u_int64_t v = ndpi_htonll(s);
-
- memcpy(&serializer->buffer[serializer->size_used], &v, sizeof(u_int64_t));
- serializer->size_used += sizeof(u_int64_t);
-}
-
-/* ********************************** */
-
-static void ndpi_serialize_single_string(ndpi_serializer *serializer,
- const char *s, u_int16_t slen) {
- u_int16_t l = htons(slen);
-
- memcpy(&serializer->buffer[serializer->size_used], &l, sizeof(u_int16_t));
- serializer->size_used += sizeof(u_int16_t);
-
- if (slen > 0)
- memcpy(&serializer->buffer[serializer->size_used], s, slen);
-
- serializer->size_used += slen;
-}
-
-/* ********************************** */
-
-static void ndpi_deserialize_single_uint32(ndpi_serializer *deserializer,
- u_int32_t *s) {
- *s = ntohl(*((u_int32_t *) &deserializer->buffer[deserializer->size_used]));
- deserializer->size_used += sizeof(u_int32_t);
-}
-
-/* ********************************** */
-
-static void ndpi_deserialize_single_int32(ndpi_serializer *deserializer,
- int32_t *s) {
- *s = ntohl(*((int32_t *) &deserializer->buffer[deserializer->size_used]));
- deserializer->size_used += sizeof(int32_t);
-}
-
-/* ********************************** */
-
-static void ndpi_deserialize_single_uint64(ndpi_serializer *deserializer,
- u_int64_t *s) {
- *s = ndpi_ntohll(*(u_int64_t*)&deserializer->buffer[deserializer->size_used]);
- deserializer->size_used += sizeof(u_int64_t);
-}
-
-/* ********************************** */
-
-static void ndpi_deserialize_single_int64(ndpi_serializer *deserializer,
- int64_t *s) {
- *s = ndpi_ntohll(*(int64_t*)&deserializer->buffer[deserializer->size_used]);
- deserializer->size_used += sizeof(int64_t);
-}
-
-/* ********************************** */
-
-static void ndpi_deserialize_single_string(ndpi_serializer *deserializer,
- ndpi_string *v) {
- v->str_len = ntohs(*((u_int16_t *) &deserializer->buffer[deserializer->size_used]));
- deserializer->size_used += sizeof(u_int16_t);
-
- v->str = (char *) &deserializer->buffer[deserializer->size_used];
- deserializer->size_used += v->str_len;
-}
-
-/* ********************************** */
-
-int ndpi_serialize_end_of_record(ndpi_serializer *serializer) {
- u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
- u_int16_t needed =
- sizeof(u_int8_t) /* type */;
-
- if(serializer->fmt == ndpi_serialization_format_json)
- needed += 1;
-
- if(buff_diff < needed) {
- if (ndpi_extend_serializer_buffer(serializer, needed - buff_diff) < 0)
- return(-1);
- buff_diff = serializer->buffer_size - serializer->size_used;
- }
-
- if(serializer->fmt == ndpi_serialization_format_json) {
- if (!(serializer->status & NDPI_SERIALIZER_STATUS_ARRAY)) {
- serializer->json_buffer[0] = '[';
- serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff, "]");
- }
- serializer->status |= NDPI_SERIALIZER_STATUS_ARRAY | NDPI_SERIALIZER_STATUS_EOR;
- serializer->status &= ~NDPI_SERIALIZER_STATUS_COMMA;
- } else {
- serializer->buffer[serializer->size_used++] = ndpi_serialization_end_of_record;
- }
-
- return(0);
-}
-
-/* ********************************** */
-
-static void ndpi_serialize_json_pre(ndpi_serializer *serializer) {
- if (serializer->status & NDPI_SERIALIZER_STATUS_EOR) {
- serializer->size_used--; /* Remove ']' */
- serializer->status &= ~NDPI_SERIALIZER_STATUS_EOR;
- serializer->buffer[serializer->size_used++] = ',';
- serializer->buffer[serializer->size_used++] = '{';
- } else {
- if (serializer->status & NDPI_SERIALIZER_STATUS_ARRAY)
- serializer->size_used--; /* Remove ']'*/
- serializer->size_used--; /* Remove '}'*/
- }
- if (serializer->status & NDPI_SERIALIZER_STATUS_COMMA)
- serializer->buffer[serializer->size_used++] = ',';
-}
-
-/* ********************************** */
-
-static void ndpi_serialize_json_post(ndpi_serializer *serializer) {
- serializer->buffer[serializer->size_used++] = '}';
- if (serializer->status & NDPI_SERIALIZER_STATUS_ARRAY)
- serializer->buffer[serializer->size_used++] = ']';
-
- serializer->status |= NDPI_SERIALIZER_STATUS_COMMA;
-}
-
-/* ********************************** */
-
-int ndpi_serialize_uint32_uint32(ndpi_serializer *serializer,
- u_int32_t key, u_int32_t value) {
- u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
- u_int16_t needed =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int32_t) /* key */ +
- sizeof(u_int32_t);
-
- if(serializer->fmt == ndpi_serialization_format_json)
- needed += 24;
-
- if(buff_diff < needed) {
- if (ndpi_extend_serializer_buffer(serializer, needed - buff_diff) < 0)
- return(-1);
- buff_diff = serializer->buffer_size - serializer->size_used;
- }
-
- if(serializer->fmt == ndpi_serialization_format_json) {
- ndpi_serialize_json_pre(serializer);
- serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
- "\"%u\":%u", key, value);
- ndpi_serialize_json_post(serializer);
- } else {
- serializer->buffer[serializer->size_used++] = ndpi_serialization_uint32_uint32;
-
- ndpi_serialize_single_uint32(serializer, key);
- ndpi_serialize_single_uint32(serializer, value);
- }
-
- return(0);
-}
-
-/* ********************************** */
-
-int ndpi_serialize_uint32_uint64(ndpi_serializer *serializer,
- u_int32_t key, u_int64_t value) {
- u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
- u_int16_t needed =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int32_t) /* key */ +
- sizeof(u_int64_t);
-
- if(serializer->fmt == ndpi_serialization_format_json)
- needed += 32;
-
- if(buff_diff < needed) {
- if (ndpi_extend_serializer_buffer(serializer, needed - buff_diff) < 0)
- return(-1);
- buff_diff = serializer->buffer_size - serializer->size_used;
- }
-
- if(serializer->fmt == ndpi_serialization_format_json) {
- ndpi_serialize_json_pre(serializer);
- serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
- "\"%u\":%llu", key, (unsigned long long)value);
- ndpi_serialize_json_post(serializer);
- } else {
- serializer->buffer[serializer->size_used++] = ndpi_serialization_uint32_uint64;
-
- ndpi_serialize_single_uint32(serializer, key);
- ndpi_serialize_single_uint64(serializer, value);
- }
-
- return(0);
-}
-
-/* ********************************** */
-
-int ndpi_serialize_uint32_string(ndpi_serializer *serializer,
- u_int32_t key, const char *value) {
- u_int16_t slen = strlen(value);
- u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
- u_int32_t needed =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int32_t) /* key */ +
- sizeof(u_int16_t) /* len */ +
- slen;
-
- if(serializer->fmt == ndpi_serialization_format_json)
- needed += 24 + slen;
-
- if(buff_diff < needed) {
- if (ndpi_extend_serializer_buffer(serializer, needed - buff_diff) < 0)
- return(-1);
- buff_diff = serializer->buffer_size - serializer->size_used;
- }
-
- if(serializer->fmt == ndpi_serialization_format_json) {
- ndpi_serialize_json_pre(serializer);
- serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
- "\"%u\":", key);
- buff_diff = serializer->buffer_size - serializer->size_used;
- serializer->size_used += ndpi_json_string_escape(value, slen,
- (char *) &serializer->buffer[serializer->size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->size_used;
- ndpi_serialize_json_post(serializer);
- } else {
- serializer->buffer[serializer->size_used++] = ndpi_serialization_uint32_string;
-
- ndpi_serialize_single_uint32(serializer, key);
- ndpi_serialize_single_string(serializer, value, slen);
- }
-
- return(0);
-}
-
-/* ********************************** */
-
-int ndpi_serialize_string_int32(ndpi_serializer *serializer,
- const char *key, int32_t value) {
- u_int16_t klen = strlen(key);
- u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
- u_int32_t needed =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int16_t) /* key len */ +
- klen /* key */ +
- sizeof(u_int32_t);
-
- if(serializer->fmt == ndpi_serialization_format_json)
- needed += 16 + klen;
-
- if(buff_diff < needed) {
- if (ndpi_extend_serializer_buffer(serializer, needed - buff_diff) < 0)
- return(-1);
- buff_diff = serializer->buffer_size - serializer->size_used;
- }
-
- if(serializer->fmt == ndpi_serialization_format_json) {
- ndpi_serialize_json_pre(serializer);
- serializer->size_used += ndpi_json_string_escape(key, klen,
- (char *) &serializer->buffer[serializer->size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->size_used;
- serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
- ":%d", value);
- ndpi_serialize_json_post(serializer);
- } else {
- serializer->buffer[serializer->size_used++] = ndpi_serialization_string_int32;
-
- ndpi_serialize_single_string(serializer, key, klen);
- ndpi_serialize_single_uint32(serializer, value);
- }
-
- return(0);
-}
-
-/* ********************************** */
-
-int ndpi_serialize_string_int64(ndpi_serializer *serializer,
- const char *key, int64_t value) {
- u_int16_t klen = strlen(key);
- u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
- u_int32_t needed =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int16_t) /* key len */ +
- klen /* key */ +
- sizeof(u_int32_t);
-
- if(serializer->fmt == ndpi_serialization_format_json)
- needed += 16 + klen;
-
- if(buff_diff < needed) {
- if (ndpi_extend_serializer_buffer(serializer, needed - buff_diff) < 0)
- return(-1);
- buff_diff = serializer->buffer_size - serializer->size_used;
- }
-
- if(serializer->fmt == ndpi_serialization_format_json) {
- ndpi_serialize_json_pre(serializer);
- serializer->size_used += ndpi_json_string_escape(key, klen,
- (char *) &serializer->buffer[serializer->size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->size_used;
- serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
- ":%lld", value);
- ndpi_serialize_json_post(serializer);
- } else {
- serializer->buffer[serializer->size_used++] = ndpi_serialization_string_int64;
-
- ndpi_serialize_single_string(serializer, key, klen);
- ndpi_serialize_single_uint32(serializer, value);
- }
-
- return(0);
-}
-
-/* ********************************** */
-
-int ndpi_serialize_string_uint32(ndpi_serializer *serializer,
- const char *key, u_int32_t value) {
- u_int16_t klen = strlen(key);
- u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
- u_int32_t needed =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int16_t) /* key len */ +
- klen /* key */ +
- sizeof(u_int32_t);
-
- if(serializer->fmt == ndpi_serialization_format_json)
- needed += 16 + klen;
-
- if(buff_diff < needed) {
- if (ndpi_extend_serializer_buffer(serializer, needed - buff_diff) < 0)
- return(-1);
- buff_diff = serializer->buffer_size - serializer->size_used;
- }
-
- if(serializer->fmt == ndpi_serialization_format_json) {
- ndpi_serialize_json_pre(serializer);
- serializer->size_used += ndpi_json_string_escape(key, klen,
- (char *) &serializer->buffer[serializer->size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->size_used;
- serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
- ":%u", value);
- ndpi_serialize_json_post(serializer);
- } else {
- serializer->buffer[serializer->size_used++] = ndpi_serialization_string_uint32;
-
- ndpi_serialize_single_string(serializer, key, klen);
- ndpi_serialize_single_uint32(serializer, value);
- }
-
- return(0);
-}
-
-/* ********************************** */
-
-int ndpi_serialize_string_uint64(ndpi_serializer *serializer,
- const char *key, u_int64_t value) {
- u_int16_t klen = strlen(key);
- u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
- u_int32_t needed =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int16_t) /* key len */ +
- klen /* key */ +
- sizeof(u_int64_t);
-
- if(serializer->fmt == ndpi_serialization_format_json)
- needed += 32 + klen;
-
- if(buff_diff < needed) {
- if (ndpi_extend_serializer_buffer(serializer, needed - buff_diff) < 0)
- return(-1);
- buff_diff = serializer->buffer_size - serializer->size_used;
- }
-
- if(serializer->fmt == ndpi_serialization_format_json) {
- ndpi_serialize_json_pre(serializer);
- serializer->size_used += ndpi_json_string_escape(key, klen,
- (char *) &serializer->buffer[serializer->size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->size_used;
- serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff,
- ":%llu", (unsigned long long)value);
- ndpi_serialize_json_post(serializer);
- } else {
- serializer->buffer[serializer->size_used++] = ndpi_serialization_string_uint64;
-
- ndpi_serialize_single_string(serializer, key, klen);
- ndpi_serialize_single_uint64(serializer, value);
- }
-
- return(0);
-}
-
-/* ********************************** */
-
-int ndpi_serialize_string_string(ndpi_serializer *serializer,
- const char *key, const char *value) {
- u_int16_t klen = strlen(key), vlen = strlen(value);
- u_int32_t needed =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int16_t) /* key len */ +
- klen +
- sizeof(u_int16_t) /* len */ +
- vlen;
- u_int32_t buff_diff = serializer->buffer_size - serializer->size_used;
-
- if(serializer->fmt == ndpi_serialization_format_json)
- needed += 16 + klen + vlen;
-
- if(buff_diff < needed) {
- if (ndpi_extend_serializer_buffer(serializer, needed - buff_diff) < 0)
- return(-1);
- buff_diff = serializer->buffer_size - serializer->size_used;
- }
-
- if(serializer->fmt == ndpi_serialization_format_json) {
- ndpi_serialize_json_pre(serializer);
- serializer->size_used += ndpi_json_string_escape(key, klen,
- (char *) &serializer->buffer[serializer->size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->size_used;
- serializer->size_used += snprintf((char *) &serializer->buffer[serializer->size_used], buff_diff, ":");
- buff_diff = serializer->buffer_size - serializer->size_used;
- serializer->size_used += ndpi_json_string_escape(value, vlen,
- (char *) &serializer->buffer[serializer->size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->size_used;
- ndpi_serialize_json_post(serializer);
- } else {
- serializer->buffer[serializer->size_used++] = ndpi_serialization_string_string;
-
- ndpi_serialize_single_string(serializer, key, klen);
- ndpi_serialize_single_string(serializer, value, vlen);
- }
-
- return(0);
-}
-
-/* ********************************** */
-/* ********************************** */
-
-int ndpi_init_deserializer_buf(ndpi_deserializer *deserializer,
- u_int8_t *serialized_buffer,
- u_int32_t serialized_buffer_len) {
- if(serialized_buffer_len < (2 * sizeof(u_int8_t)))
- return(-1);
-
- deserializer->buffer = serialized_buffer;
-
- if(deserializer->buffer[0] != 1)
- return(-2); /* Invalid version */
-
- deserializer->buffer_size = serialized_buffer_len;
- deserializer->fmt = deserializer->buffer[1];
- ndpi_reset_serializer(deserializer);
-
- return(0);
-}
-
-/* ********************************** */
-
-int ndpi_init_deserializer(ndpi_deserializer *deserializer,
- ndpi_serializer *serializer) {
- return(ndpi_init_deserializer_buf(deserializer,
- serializer->buffer,
- serializer->size_used));
-}
-
-/* ********************************** */
-
-ndpi_serialization_element_type ndpi_deserialize_get_nextitem_type(ndpi_deserializer *deserializer) {
- ndpi_serialization_element_type et;
-
- if(deserializer->size_used >= deserializer->buffer_size)
- return(ndpi_serialization_unknown);
-
- et = (ndpi_serialization_element_type) deserializer->buffer[deserializer->size_used];
-
- return et;
-}
-
-/* ********************************** */
-
-int ndpi_deserialize_end_of_record(ndpi_deserializer *deserializer) {
- if(ndpi_deserialize_get_nextitem_type(deserializer) == ndpi_serialization_end_of_record) {
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
- u_int16_t expected =
- sizeof(u_int8_t) /* type */;
-
- if(buff_diff < expected) return(-2);
-
- deserializer->size_used++; /* Skip element type */
-
- return(0);
- } else
- return(-1);
-}
-
-/* ********************************** */
-
-int ndpi_deserialize_uint32_uint32(ndpi_deserializer *deserializer,
- u_int32_t *key, u_int32_t *value) {
- if(ndpi_deserialize_get_nextitem_type(deserializer) == ndpi_serialization_uint32_uint32) {
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
- u_int16_t expected =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int32_t) /* key */ +
- sizeof(u_int32_t);
-
- if(buff_diff < expected) return(-2);
-
- deserializer->size_used++; /* Skip element type */
- ndpi_deserialize_single_uint32(deserializer, key);
- ndpi_deserialize_single_uint32(deserializer, value);
-
- return(0);
- } else
- return(-1);
-}
-
-/* ********************************** */
-
-int ndpi_deserialize_uint32_uint64(ndpi_deserializer *deserializer,
- u_int32_t *key, u_int64_t *value) {
- if(ndpi_deserialize_get_nextitem_type(deserializer) == ndpi_serialization_uint32_uint64) {
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
- u_int16_t expected =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int32_t) /* key */ +
- sizeof(u_int64_t);
-
- if(buff_diff < expected) return(-2);
-
- deserializer->size_used++; /* Skip element type */
- ndpi_deserialize_single_uint32(deserializer, key);
- ndpi_deserialize_single_uint64(deserializer, value);
-
- return(0);
- } else
- return(-1);
-}
-
-/* ********************************** */
-
-int ndpi_deserialize_uint32_string(ndpi_deserializer *deserializer,
- u_int32_t *key, ndpi_string *value) {
- if(ndpi_deserialize_get_nextitem_type(deserializer) == ndpi_serialization_uint32_string) {
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
- u_int32_t expected =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int32_t) /* key */ +
- sizeof(u_int16_t) /* len */;
-
- if(buff_diff < expected) return(-2);
-
- deserializer->size_used++; /* Skip element type */
- ndpi_deserialize_single_uint32(deserializer, key);
- ndpi_deserialize_single_string(deserializer, value);
-
- return(0);
- } else
- return(-1);
-}
-
-/* ********************************** */
-
-int ndpi_deserialize_string_int32(ndpi_deserializer *deserializer,
- ndpi_string *key, int32_t *value) {
- if(ndpi_deserialize_get_nextitem_type(deserializer) == ndpi_serialization_string_int32) {
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
- u_int32_t expected =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int16_t) /* key len */ +
- sizeof(int32_t);
-
- if(buff_diff < expected) return(-2);
-
- deserializer->size_used++; /* Skip element type */
- ndpi_deserialize_single_string(deserializer, key);
- ndpi_deserialize_single_int32(deserializer, value);
-
- return(0);
- } else
- return(-1);
-}
-
-/* ********************************** */
-
-int ndpi_deserialize_string_int64(ndpi_deserializer *deserializer,
- ndpi_string *key, int64_t *value) {
- if(ndpi_deserialize_get_nextitem_type(deserializer) == ndpi_serialization_string_int64) {
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
- u_int32_t expected =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int16_t) /* key len */ +
- sizeof(int64_t);
-
- if(buff_diff < expected) return(-2);
-
- deserializer->size_used++; /* Skip element type */
- ndpi_deserialize_single_string(deserializer, key);
- ndpi_deserialize_single_int64(deserializer, value);
-
- return(0);
- } else
- return(-1);
-}
-
-/* ********************************** */
-
-int ndpi_deserialize_string_uint32(ndpi_deserializer *deserializer,
- ndpi_string *key, u_int32_t *value) {
- if(ndpi_deserialize_get_nextitem_type(deserializer) == ndpi_serialization_string_uint32) {
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
- u_int32_t expected =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int16_t) /* key len */ +
- sizeof(u_int32_t);
-
- if(buff_diff < expected) return(-2);
-
- deserializer->size_used++; /* Skip element type */
- ndpi_deserialize_single_string(deserializer, key);
- ndpi_deserialize_single_uint32(deserializer, value);
-
- return(0);
- } else
- return(-1);
-}
-
-/* ********************************** */
-
-int ndpi_deserialize_string_uint64(ndpi_deserializer *deserializer,
- ndpi_string *key, u_int64_t *value) {
- if(ndpi_deserialize_get_nextitem_type(deserializer) == ndpi_serialization_string_uint64) {
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
- u_int32_t expected =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int16_t) /* key len */ +
- sizeof(u_int64_t);
-
- if(buff_diff < expected) return(-2);
-
- deserializer->size_used++; /* Skip element type */
- ndpi_deserialize_single_string(deserializer, key);
- ndpi_deserialize_single_uint64(deserializer, value);
-
- return(0);
- } else
- return(-1);
-}
-
-/* ********************************** */
-
-int ndpi_deserialize_string_string(ndpi_deserializer *deserializer,
- ndpi_string *key, ndpi_string *value) {
- if(ndpi_deserialize_get_nextitem_type(deserializer) == ndpi_serialization_string_string) {
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->size_used;
- u_int32_t expected =
- sizeof(u_int8_t) /* type */ +
- sizeof(u_int16_t) /* key len */ +
- sizeof(u_int16_t) /* len */;
-
- if(buff_diff < expected) return(-2);
-
- deserializer->size_used++; /* Skip element type */
- ndpi_deserialize_single_string(deserializer, key);
- ndpi_deserialize_single_string(deserializer, value);
-
- return(0);
- } else
- return(-1);
-}
-
-/* ********************************** */
-
diff --git a/src/lib/protocols/directconnect.c b/src/lib/protocols/directconnect.c
index 19582724d..563540fba 100644
--- a/src/lib/protocols/directconnect.c
+++ b/src/lib/protocols/directconnect.c
@@ -58,9 +58,9 @@ static u_int16_t parse_binf_message(struct ndpi_detection_module_struct
u_int16_t ssl_port = 0;
while (i < payload_len) {
i = skip_unknown_headers(payload, payload_len, i);
- if ((i + 30) < payload_len) {
- if (memcmp(&payload[i], "DCTM", 4) == 0) {
- if (memcmp(&payload[i + 15], "ADCS", 4) == 0) {
+ if((i + 30) < payload_len) {
+ if(memcmp(&payload[i], "DCTM", 4) == 0) {
+ if(memcmp(&payload[i + 15], "ADCS", 4) == 0) {
ssl_port = ntohs_ndpi_bytestream_to_number(&payload[i + 25], 5, &bytes_read);
NDPI_LOG_DBG2(ndpi_struct, "DC ssl port parsed %d\n", ssl_port);
}
@@ -84,15 +84,15 @@ static void ndpi_int_directconnect_add_connection(struct ndpi_detection_module_s
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_DIRECTCONNECT, NDPI_PROTOCOL_UNKNOWN);
- if (src != NULL) {
+ if(src != NULL) {
src->directconnect_last_safe_access_time = packet->tick_timestamp;
- if (connection_type == DIRECT_CONNECT_TYPE_PEER) {
- if (packet->tcp != NULL
+ if(connection_type == DIRECT_CONNECT_TYPE_PEER) {
+ if(packet->tcp != NULL
&& flow->setup_packet_direction != packet->packet_direction && src->detected_directconnect_port == 0) {
src->detected_directconnect_port = packet->tcp->source;
NDPI_LOG_DBG2(ndpi_struct, "DC tcp PORT %u for src\n", ntohs(src->detected_directconnect_port));
}
- if (packet->udp != NULL && src->detected_directconnect_udp_port == 0) {
+ if(packet->udp != NULL && src->detected_directconnect_udp_port == 0) {
src->detected_directconnect_udp_port = packet->udp->source;
NDPI_LOG_DBG2(ndpi_struct, "DC udp PORT %u for src\n", ntohs(src->detected_directconnect_port));
@@ -100,10 +100,10 @@ static void ndpi_int_directconnect_add_connection(struct ndpi_detection_module_s
}
}
- if (dst != NULL) {
+ if(dst != NULL) {
dst->directconnect_last_safe_access_time = packet->tick_timestamp;
- if (connection_type == DIRECT_CONNECT_TYPE_PEER) {
- if (packet->tcp != NULL
+ if(connection_type == DIRECT_CONNECT_TYPE_PEER) {
+ if(packet->tcp != NULL
&& flow->setup_packet_direction == packet->packet_direction && dst->detected_directconnect_port == 0) {
/* DST PORT MARKING CAN LEAD TO PORT MISSDETECTIONS
* seen at large customer http servers, where someone has send faked DC tcp packets
@@ -121,35 +121,34 @@ static void ndpi_int_directconnect_add_connection(struct ndpi_detection_module_s
}
}
-static void ndpi_search_directconnect_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
-{
+static void ndpi_search_directconnect_tcp(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &flow->packet;
struct ndpi_id_struct *src = flow->src;
struct ndpi_id_struct *dst = flow->dst;
- if (flow->detected_protocol_stack[0] == NDPI_PROTOCOL_DIRECTCONNECT) {
- if (packet->payload_packet_len >= 40 && memcmp(&packet->payload[0], "BINF", 4) == 0) {
- u_int16_t ssl_port = 0;
- ssl_port = parse_binf_message(ndpi_struct, &packet->payload[4], packet->payload_packet_len - 4);
- if (dst != NULL && ssl_port) {
+ if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_DIRECTCONNECT) {
+ if(packet->payload_packet_len >= 40 && memcmp(&packet->payload[0], "BINF", 4) == 0) {
+ u_int16_t ssl_port = parse_binf_message(ndpi_struct,
+ &packet->payload[4],
+ packet->payload_packet_len - 4);
+ if(dst != NULL && ssl_port)
dst->detected_directconnect_ssl_port = ssl_port;
- }
- if (src != NULL && ssl_port) {
+
+ if(src != NULL && ssl_port)
src->detected_directconnect_ssl_port = ssl_port;
- }
-
-
}
- if ((packet->payload_packet_len >= 38 && packet->payload_packet_len <= 42)
+
+ if((packet->payload_packet_len >= 38 && packet->payload_packet_len <= 42)
&& memcmp(&packet->payload[0], "DCTM", 4) == 0 && memcmp(&packet->payload[15], "ADCS", 4) == 0) {
u_int16_t bytes_read = 0;
- if (dst != NULL) {
+ if(dst != NULL) {
dst->detected_directconnect_ssl_port =
ntohs_ndpi_bytestream_to_number(&packet->payload[25], 5, &bytes_read);
NDPI_LOG_DBG2(ndpi_struct, "DC ssl port parsed %d\n", ntohs(dst->detected_directconnect_ssl_port));
}
- if (src != NULL) {
+ if(src != NULL) {
src->detected_directconnect_ssl_port =
ntohs_ndpi_bytestream_to_number(&packet->payload[25], 5, &bytes_read);
NDPI_LOG_DBG2(ndpi_struct, "DC ssl port parsed %d\n", ntohs(src->detected_directconnect_ssl_port));
@@ -160,9 +159,9 @@ static void ndpi_search_directconnect_tcp(struct ndpi_detection_module_struct *n
return;
}
- if (src != NULL) {
- if (src->detected_directconnect_port == packet->tcp->source) {
- if ((u_int32_t)
+ if(src != NULL) {
+ if(src->detected_directconnect_port == packet->tcp->source) {
+ if((u_int32_t)
(packet->tick_timestamp -
src->directconnect_last_safe_access_time) < ndpi_struct->directconnect_connection_ip_tick_timeout) {
src->directconnect_last_safe_access_time = packet->tick_timestamp;
@@ -175,8 +174,8 @@ static void ndpi_search_directconnect_tcp(struct ndpi_detection_module_struct *n
return;
}
}
- if (src->detected_directconnect_ssl_port == packet->tcp->dest) {
- if ((u_int32_t)
+ if(src->detected_directconnect_ssl_port == packet->tcp->dest) {
+ if((u_int32_t)
(packet->tick_timestamp -
src->directconnect_last_safe_access_time) < ndpi_struct->directconnect_connection_ip_tick_timeout) {
src->directconnect_last_safe_access_time = packet->tick_timestamp;
@@ -192,9 +191,9 @@ static void ndpi_search_directconnect_tcp(struct ndpi_detection_module_struct *n
}
- if (dst != NULL) {
- if (dst->detected_directconnect_port == packet->tcp->dest) {
- if ((u_int32_t)
+ if(dst != NULL) {
+ if(dst->detected_directconnect_port == packet->tcp->dest) {
+ if((u_int32_t)
(packet->tick_timestamp -
dst->directconnect_last_safe_access_time) < ndpi_struct->directconnect_connection_ip_tick_timeout) {
dst->directconnect_last_safe_access_time = packet->tick_timestamp;
@@ -207,8 +206,8 @@ static void ndpi_search_directconnect_tcp(struct ndpi_detection_module_struct *n
return;
}
}
- if (dst->detected_directconnect_ssl_port == packet->tcp->dest) {
- if ((u_int32_t)
+ if(dst->detected_directconnect_ssl_port == packet->tcp->dest) {
+ if((u_int32_t)
(packet->tick_timestamp -
dst->directconnect_last_safe_access_time) < ndpi_struct->directconnect_connection_ip_tick_timeout) {
dst->directconnect_last_safe_access_time = packet->tick_timestamp;
@@ -224,17 +223,17 @@ static void ndpi_search_directconnect_tcp(struct ndpi_detection_module_struct *n
}
- if (flow->directconnect_stage == 0) {
+ if(flow->directconnect_stage == 0) {
- if (packet->payload_packet_len > 6) {
- if (packet->payload[0] == '$'
+ if(packet->payload_packet_len > 6) {
+ if(packet->payload[0] == '$'
&& packet->payload[packet->payload_packet_len - 1] == '|'
&& (memcmp(&packet->payload[1], "Lock ", 5) == 0)) {
NDPI_LOG_DBG2(ndpi_struct, "maybe first dc connect to hub detected\n");
flow->directconnect_stage = 1;
return;
}
- if (packet->payload_packet_len > 7
+ if(packet->payload_packet_len > 7
&& packet->payload[0] == '$'
&& packet->payload[packet->payload_packet_len - 1] == '|'
&& (memcmp(&packet->payload[1], "MyNick ", 7) == 0)) {
@@ -244,15 +243,15 @@ static void ndpi_search_directconnect_tcp(struct ndpi_detection_module_struct *n
}
}
- if (packet->payload_packet_len >= 11) {
+ if(packet->payload_packet_len >= 11) {
/* did not see this pattern in any trace */
- if (memcmp(&packet->payload[0], "HSUP ADBAS0", 11) == 0
+ if(memcmp(&packet->payload[0], "HSUP ADBAS0", 11) == 0
|| memcmp(&packet->payload[0], "HSUP ADBASE", 11) == 0) {
NDPI_LOG_INFO(ndpi_struct, "found DC HSUP ADBAS0 E\n");
ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_TYPE_HUB);
return;
/* did not see this pattern in any trace */
- } else if (memcmp(&packet->payload[0], "CSUP ADBAS0", 11) == 0 ||
+ } else if(memcmp(&packet->payload[0], "CSUP ADBAS0", 11) == 0 ||
memcmp(&packet->payload[0], "CSUP ADBASE", 11) == 0) {
NDPI_LOG_INFO(ndpi_struct, "found DC CSUP ADBAS0 E\n");
ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_ADC_PEER);
@@ -262,16 +261,16 @@ static void ndpi_search_directconnect_tcp(struct ndpi_detection_module_struct *n
}
- } else if (flow->directconnect_stage == 1) {
- if (packet->payload_packet_len >= 11) {
+ } else if(flow->directconnect_stage == 1) {
+ if(packet->payload_packet_len >= 11) {
/* did not see this pattern in any trace */
- if (memcmp(&packet->payload[0], "HSUP ADBAS0", 11) == 0
+ if(memcmp(&packet->payload[0], "HSUP ADBAS0", 11) == 0
|| memcmp(&packet->payload[0], "HSUP ADBASE", 11) == 0) {
NDPI_LOG_INFO(ndpi_struct, "found DC HSUP ADBAS E in second packet\n");
ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_TYPE_HUB);
return;
/* did not see this pattern in any trace */
- } else if (memcmp(&packet->payload[0], "CSUP ADBAS0", 11) == 0 ||
+ } else if(memcmp(&packet->payload[0], "CSUP ADBAS0", 11) == 0 ||
memcmp(&packet->payload[0], "CSUP ADBASE", 11) == 0) {
NDPI_LOG_INFO(ndpi_struct, "found DC HSUP ADBAS0 E in second packet\n");
ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_ADC_PEER);
@@ -280,8 +279,8 @@ static void ndpi_search_directconnect_tcp(struct ndpi_detection_module_struct *n
}
}
/* get client hello answer or server message */
- if (packet->payload_packet_len > 6) {
- if ((packet->payload[0] == '$' || packet->payload[0] == '<')
+ if(packet->payload_packet_len > 6) {
+ if((packet->payload[0] == '$' || packet->payload[0] == '<')
&& packet->payload[packet->payload_packet_len - 1] == '|') {
NDPI_LOG_INFO(ndpi_struct, "found DC second\n");
ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_TYPE_HUB);
@@ -291,10 +290,10 @@ static void ndpi_search_directconnect_tcp(struct ndpi_detection_module_struct *n
}
}
- } else if (flow->directconnect_stage == 2) {
+ } else if(flow->directconnect_stage == 2) {
/* get client hello answer or server message */
- if (packet->payload_packet_len > 6) {
- if (packet->payload[0] == '$' && packet->payload[packet->payload_packet_len - 1] == '|') {
+ if(packet->payload_packet_len > 6) {
+ if(packet->payload[0] == '$' && packet->payload[packet->payload_packet_len - 1] == '|') {
NDPI_LOG_INFO(ndpi_struct, "found DC between peers\n");
ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_TYPE_PEER);
return;
@@ -318,8 +317,8 @@ static void ndpi_search_directconnect_udp(struct ndpi_detection_module_struct
struct ndpi_id_struct *dst = flow->dst;
int pos, count = 0;
- if (dst != NULL && dst->detected_directconnect_udp_port == packet->udp->dest) {
- if ((u_int32_t)
+ if(dst != NULL && dst->detected_directconnect_udp_port == packet->udp->dest) {
+ if((u_int32_t)
(packet->tick_timestamp -
dst->directconnect_last_safe_access_time) < ndpi_struct->directconnect_connection_ip_tick_timeout) {
@@ -334,21 +333,21 @@ static void ndpi_search_directconnect_udp(struct ndpi_detection_module_struct
}
}
- if (packet->payload_packet_len > 58) {
- if (src != NULL
+ if(packet->payload_packet_len > 58) {
+ if(src != NULL
&& NDPI_COMPARE_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, NDPI_PROTOCOL_DIRECTCONNECT)) {
- if (packet->payload[0] == '$'
+ if(packet->payload[0] == '$'
&& packet->payload[packet->payload_packet_len - 1] == '|'
&& memcmp(&packet->payload[1], "SR ", 3) == 0) {
pos = packet->payload_packet_len - 2;
- if (packet->payload[pos] == ')') {
+ if(packet->payload[pos] == ')') {
while (pos > 0 && packet->payload[pos] != '(' && count < 21) {
pos--;
count++;
}
- if (packet->payload[pos] == '(') {
+ if(packet->payload[pos] == '(') {
pos = pos - 44;
- if (pos > 2 && memcmp(&packet->payload[pos], "TTH:", 4) == 0) {
+ if(pos > 2 && memcmp(&packet->payload[pos], "TTH:", 4) == 0) {
NDPI_LOG_INFO(ndpi_struct, "found DC udp\n");
ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_TYPE_PEER);
return;
@@ -356,25 +355,25 @@ static void ndpi_search_directconnect_udp(struct ndpi_detection_module_struct
}
}
flow->directconnect_stage++;
- if (flow->directconnect_stage < 3)
+ if(flow->directconnect_stage < 3)
return;
}
}
- if (dst != NULL
+ if(dst != NULL
&& NDPI_COMPARE_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, NDPI_PROTOCOL_DIRECTCONNECT)) {
- if (packet->payload[0] == '$'
+ if(packet->payload[0] == '$'
&& packet->payload[packet->payload_packet_len - 1] == '|'
&& memcmp(&packet->payload[1], "SR ", 3) == 0) {
pos = packet->payload_packet_len - 2;
- if (packet->payload[pos] == ')') {
+ if(packet->payload[pos] == ')') {
while (pos > 0 && packet->payload[pos] != '(' && count < 21) {
pos--;
count++;
}
- if (packet->payload[pos] == '(') {
+ if(packet->payload[pos] == '(') {
pos = pos - 44;
- if (pos > 2 && memcmp(&packet->payload[pos], "TTH:", 4) == 0) {
+ if(pos > 2 && memcmp(&packet->payload[pos], "TTH:", 4) == 0) {
NDPI_LOG_INFO(ndpi_struct, "found DC udp\n");
ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_TYPE_PEER);
return;
@@ -382,7 +381,7 @@ static void ndpi_search_directconnect_udp(struct ndpi_detection_module_struct
}
}
flow->directconnect_stage++;
- if (flow->directconnect_stage < 3)
+ if(flow->directconnect_stage < 3)
return;
}
}
@@ -404,14 +403,14 @@ void ndpi_search_directconnect(struct ndpi_detection_module_struct
NDPI_LOG_DBG(ndpi_struct, "search DC\n");
- if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_DIRECTCONNECT) {
- if (src != NULL && ((u_int32_t)
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_DIRECTCONNECT) {
+ if(src != NULL && ((u_int32_t)
(packet->tick_timestamp -
src->directconnect_last_safe_access_time) <
ndpi_struct->directconnect_connection_ip_tick_timeout)) {
src->directconnect_last_safe_access_time = packet->tick_timestamp;
- } else if (dst != NULL && ((u_int32_t)
+ } else if(dst != NULL && ((u_int32_t)
(packet->tick_timestamp -
dst->directconnect_last_safe_access_time) <
ndpi_struct->directconnect_connection_ip_tick_timeout)) {
@@ -423,9 +422,9 @@ void ndpi_search_directconnect(struct ndpi_detection_module_struct
return;
}
- if (packet->tcp != NULL) {
+ if(packet->tcp != NULL) {
ndpi_search_directconnect_tcp(ndpi_struct, flow);
- } else if (packet->udp != NULL) {
+ } else if(packet->udp != NULL) {
ndpi_search_directconnect_udp(ndpi_struct, flow);
}
}
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/hangout.c b/src/lib/protocols/hangout.c
index 99bf879cb..c96b36018 100644
--- a/src/lib/protocols/hangout.c
+++ b/src/lib/protocols/hangout.c
@@ -22,8 +22,12 @@
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_HANGOUT_DUO
+/* #define DEBUG_LRU 1 */
+
#include "ndpi_api.h"
+/* stun.c */
+extern u_int32_t get_stun_lru_key(struct ndpi_flow_struct *flow);
/* https://support.google.com/a/answer/1279090?hl=en */
#define HANGOUT_UDP_LOW_PORT 19302
@@ -85,11 +89,29 @@ void ndpi_search_hangout(struct ndpi_detection_module_struct *ndpi_struct,
if((packet->payload_packet_len > 24) && is_google_flow(ndpi_struct, flow)) {
if(
- ((packet->udp != NULL) && (isHangoutUDPPort(ntohs(packet->udp->source)) || isHangoutUDPPort(ntohs(packet->udp->dest))))
+ ((packet->udp != NULL) && (isHangoutUDPPort(ntohs(packet->udp->source))
+ || isHangoutUDPPort(ntohs(packet->udp->dest))))
||
- ((packet->tcp != NULL) && (isHangoutTCPPort(ntohs(packet->tcp->source)) || isHangoutTCPPort(ntohs(packet->tcp->dest))))) {
+ ((packet->tcp != NULL) && (isHangoutTCPPort(ntohs(packet->tcp->source))
+ || isHangoutTCPPort(ntohs(packet->tcp->dest))))) {
NDPI_LOG_INFO(ndpi_struct, "found Hangout\n");
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_HANGOUT_DUO, NDPI_PROTOCOL_UNKNOWN);
+
+ /* Hangout is over STUN hence the LRU cache is shared */
+ if(ndpi_struct->stun_cache == NULL)
+ ndpi_struct->stun_cache = ndpi_lru_cache_init(1024);
+
+ if(ndpi_struct->stun_cache && flow->packet.iph && flow->packet.udp) {
+ u_int32_t key = get_stun_lru_key(flow);
+
+#ifdef DEBUG_LRU
+ printf("[LRU] ADDING %u / %u.%u\n", key, NDPI_PROTOCOL_STUN, NDPI_PROTOCOL_HANGOUT_DUO);
+#endif
+
+ ndpi_lru_add_to_cache(ndpi_struct->stun_cache, key, NDPI_PROTOCOL_HANGOUT_DUO);
+ }
+
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_HANGOUT_DUO,
+ NDPI_PROTOCOL_STUN);
return;
}
}
diff --git a/src/lib/protocols/http.c b/src/lib/protocols/http.c
index 1e066c3ac..cd5f193db 100644
--- a/src/lib/protocols/http.c
+++ b/src/lib/protocols/http.c
@@ -35,7 +35,7 @@ static void ndpi_int_http_add_connection(struct ndpi_detection_module_struct *nd
printf("[%s] [http_dont_dissect_response: %u]->> %s\n", __FUNCTION__,
ndpi_struct->http_dont_dissect_response, flow->http.response_status_code);
#endif
-
+
if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
/* This is HTTP and it is not a sub protocol (e.g. skype or dropbox) */
@@ -157,7 +157,7 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
#endif
/* Leave the statement below commented necessary in case of call to ndpi_get_partial_detection() */
-
+
/* if(!ndpi_struct->http_dont_dissect_response) */ {
if((flow->http.url == NULL)
&& (packet->http_url_name.len > 0)
@@ -320,7 +320,7 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
/**
check result of host subprotocol detection
-
+
if "detected" in flow == 0 then "detected" = "guess"
else "guess" = "detected"
**/
@@ -338,7 +338,7 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
if(flow->detected_protocol_stack[0] != flow->guessed_host_protocol_id)
flow->guessed_host_protocol_id = flow->detected_protocol_stack[0];
}
-
+
if((flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN)
&& ((ndpi_struct->http_dont_dissect_response) || flow->http_detected)
&& (packet->http_origin.len > 0)) {
@@ -480,17 +480,17 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
if(packet->payload_packet_len >= 12) {
char buf[4];
-
+
/* Set server HTTP response code */
strncpy(buf, (char*)&packet->payload[9], 3);
buf[3] = '\0';
-
+
flow->http.response_status_code = atoi(buf);
/* https://en.wikipedia.org/wiki/List_of_HTTP_status_codes */
if((flow->http.response_status_code < 100) || (flow->http.response_status_code > 509))
flow->http.response_status_code = 0; /* Out of range */
}
-
+
ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP);
check_content_type_and_change_protocol(ndpi_struct, flow);
return;
@@ -533,14 +533,14 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
if(ndpi_struct->ookla_cache == NULL)
ndpi_struct->ookla_cache = ndpi_lru_cache_init(1024);
-
+
if(packet->iph != NULL && ndpi_struct->ookla_cache != NULL) {
if(packet->tcp->source == htons(8080))
- ndpi_lru_add_to_cache(ndpi_struct->ookla_cache, packet->iph->saddr);
+ ndpi_lru_add_to_cache(ndpi_struct->ookla_cache, packet->iph->saddr, 1 /* dummy */);
else
- ndpi_lru_add_to_cache(ndpi_struct->ookla_cache, packet->iph->daddr);
+ ndpi_lru_add_to_cache(ndpi_struct->ookla_cache, packet->iph->daddr, 1 /* dummy */);
}
-
+
return;
}
diff --git a/src/lib/protocols/mail_imap.c b/src/lib/protocols/mail_imap.c
index 65341cdc8..69d135943 100644
--- a/src/lib/protocols/mail_imap.c
+++ b/src/lib/protocols/mail_imap.c
@@ -48,7 +48,7 @@ void ndpi_search_mail_imap_tcp(struct ndpi_detection_module_struct *ndpi_struct,
if (flow->l4.tcp.mail_imap_starttls == 2) {
NDPI_LOG_DBG2(ndpi_struct, "starttls detected\n");
NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MAIL_IMAP);
- NDPI_DEL_PROTOCOL_FROM_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SSL);
+ NDPI_DEL_PROTOCOL_FROM_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_TLS);
return;
}
diff --git a/src/lib/protocols/msn.c b/src/lib/protocols/msn.c
index 8ab45ad32..8d52d690b 100644
--- a/src/lib/protocols/msn.c
+++ b/src/lib/protocols/msn.c
@@ -62,7 +62,7 @@ static void ndpi_search_msn_tcp(struct ndpi_detection_module_struct *ndpi_struct
u_int16_t plen;
u_int16_t status = 0;
- if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) {
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_TLS) {
NDPI_LOG_DBG2(ndpi_struct, "msn ssl ft test\n");
@@ -103,7 +103,7 @@ static void ndpi_search_msn_tcp(struct ndpi_detection_module_struct *ndpi_struct
*/
/* now we have a look at the first packet only. */
if(flow->packet_counter == 1
- || ((packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL)
+ || ((packet->detected_protocol_stack[0] == NDPI_PROTOCOL_TLS)
&& flow->packet_counter <= 3)
) {
@@ -497,7 +497,7 @@ void ndpi_search_msn(struct ndpi_detection_module_struct *ndpi_struct, struct nd
// need to do the ceck when protocol == http too (POST /gateway ...)
if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN
|| packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP
- || packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL
+ || packet->detected_protocol_stack[0] == NDPI_PROTOCOL_TLS
|| packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STUN
)
ndpi_search_msn_tcp(ndpi_struct, flow);
diff --git a/src/lib/protocols/ookla.c b/src/lib/protocols/ookla.c
index 44746fbd3..f3c2108bc 100644
--- a/src/lib/protocols/ookla.c
+++ b/src/lib/protocols/ookla.c
@@ -38,7 +38,9 @@ void ndpi_search_ookla(struct ndpi_detection_module_struct* ndpi_struct, struct
goto ookla_exclude;
if(ndpi_struct->ookla_cache != NULL) {
- if(ndpi_lru_find_cache(ndpi_struct->ookla_cache, addr, 0 /* Don't remove it as it can be used for other connections */)) {
+ u_int16_t dummy;
+
+ if(ndpi_lru_find_cache(ndpi_struct->ookla_cache, addr, &dummy, 0 /* Don't remove it as it can be used for other connections */)) {
NDPI_LOG_INFO(ndpi_struct, "found ookla tcp connection\n");
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_OOKLA, NDPI_PROTOCOL_UNKNOWN);
return;
diff --git a/src/lib/protocols/quic.c b/src/lib/protocols/quic.c
index 6d4d45044..87378ea61 100644
--- a/src/lib/protocols/quic.c
+++ b/src/lib/protocols/quic.c
@@ -83,15 +83,27 @@ void ndpi_search_quic(struct ndpi_detection_module_struct *ndpi_struct,
) {
int i;
-
if((packet->payload[1] == 'Q')
&& (packet->payload[2] == '0')
&& (packet->payload[3] == '4')
- && (packet->payload[4] == '6'))
+ && (packet->payload[4] == '6')
+ && (version_len == 1)
+ )
quic_hlen = 18; /* TODO: Better handle Q046 */
else {
+ u_int16_t potential_stun_len = ntohs((*((u_int16_t*)&packet->payload[2])));
+
if((version_len > 0) && (packet->payload[1+cid_len] != 'Q'))
goto no_quic;
+
+ if((version_len == 0) && ((packet->payload[0] & 0xC3 /* ignore CID len/packet number */) != 0))
+ goto no_quic;
+
+
+ /* Heuristic to see if this packet could be a STUN packet */
+ if((potential_stun_len /* STUN message len */ < udp_len)
+ && ((potential_stun_len+25 /* Attribute header overhead we assume is max */) /* STUN message len */ > udp_len))
+ return; /* This could be STUN, let's skip this packet */
NDPI_LOG_INFO(ndpi_struct, "found QUIC\n");
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_QUIC, NDPI_PROTOCOL_UNKNOWN);
diff --git a/src/lib/protocols/rtp.c b/src/lib/protocols/rtp.c
index bd0179287..90b73ab1e 100644
--- a/src/lib/protocols/rtp.c
+++ b/src/lib/protocols/rtp.c
@@ -58,14 +58,14 @@ static u_int8_t isValidMSRTPType(u_int8_t payloadType) {
case 127: /* x-data */
return(1 /* RTP */);
break;
-
+
case 200: /* RTCP PACKET SENDER */
case 201: /* RTCP PACKET RECEIVER */
case 202: /* RTCP Source Description */
case 203: /* RTCP Bye */
return(2 /* RTCP */);
break;
-
+
default:
return(0);
}
@@ -78,8 +78,10 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
const u_int8_t * payload, const u_int16_t payload_len) {
NDPI_LOG_DBG(ndpi_struct, "search RTP\n");
- if (payload_len < 2)
+ if((payload_len < 2) || flow->protos.stun_ssl.stun.num_binding_requests) {
+ NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
return;
+ }
//struct ndpi_packet_struct *packet = &flow->packet;
u_int8_t payloadType, payload_type = payload[1] & 0x7F;
@@ -91,17 +93,17 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
&& ((payload_type <= 34)
|| ((payload_type >= 96) && (payload_type <= 127))
/* http://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml */
- )
- ) {
+ )
+ ) {
struct ndpi_packet_struct *packet = &flow->packet;
-
+
if(packet->iph) {
/* 125.209.252.xxx */
if(((ntohl(packet->iph->saddr) & 0xFFFFFF00 /* 255.255.255.0 */) == 0x7DD1FC00)
|| ((ntohl(packet->iph->daddr) & 0xFFFFFF00 /* 255.255.255.0 */) == 0x7DD1FC00)) {
if((flow->packet.payload[0] == 0x80)
&& ((flow->packet.payload[1] == 0x78) || (flow->packet.payload[1] == 0xE8))
- ) {
+ ) {
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_LINE, NDPI_PROTOCOL_LINE);
return;
}
@@ -112,7 +114,7 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_RTP, NDPI_PROTOCOL_UNKNOWN);
return;
} else if((payload_len >= 12)
- && (((payload[0] & 0xFF) == 0x80) || ((payload[0] & 0xFF) == 0xA0)) /* RTP magic byte[1] */
+ && (((payload[0] & 0xFF) == 0x80) || ((payload[0] & 0xFF) == 0xA0)) /* RTP magic byte[1] */
&& (payloadType = isValidMSRTPType(payload[1] & 0xFF))) {
if(payloadType == 1 /* RTP */) {
NDPI_LOG_INFO(ndpi_struct, "Found Skype for Business (former MS Lync)\n");
@@ -126,7 +128,7 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
return;
#endif
}
- }
+ }
/* No luck this time */
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
@@ -139,7 +141,7 @@ void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, struct nd
struct ndpi_packet_struct *packet = &flow->packet;
/* printf("*** %s(pkt=%d)\n", __FUNCTION__, flow->packet_counter); */
-
+
if((packet->udp != NULL)
/* && (ntohs(packet->udp->source) > 1023) */
&& (ntohs(packet->udp->dest) > 1023))
@@ -204,14 +206,14 @@ u_int16_t update_seq(struct ndpi_detection_module_struct *ndpi_struct, struct nd
u_int16_t delta = seq - flow->rtp_seqnum[direction];
- if (delta < RTP_MAX_OUT_OF_ORDER) { /* in order, with permissible gap */
+ if(delta < RTP_MAX_OUT_OF_ORDER) { /* in order, with permissible gap */
flow->rtp_seqnum[direction] = seq;
NDPI_LOG_DBG(ndpi_struct, "rtp_seqnum[%u] = %u (increased by %u)\n",
- direction, seq, delta);
+ direction, seq, delta);
return delta;
} else {
NDPI_LOG_DBG(ndpi_struct, "retransmission (dir %u, seqnum %u)\n",
- direction, seq);
+ direction, seq);
return 0;
}
}
@@ -227,51 +229,51 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
NDPI_LOG_DBG(ndpi_struct, "search rtp\n");
- if (payload_len == 4 && get_u_int32_t(packet->payload, 0) == 0 && flow->packet_counter < 8) {
+ if(payload_len == 4 && get_u_int32_t(packet->payload, 0) == 0 && flow->packet_counter < 8) {
NDPI_LOG_DBG(ndpi_struct, "need next packet, maybe ClearSea out calls\n");
return;
}
- if (payload_len == 5 && memcmp(payload, "hello", 5) == 0) {
+ if(payload_len == 5 && memcmp(payload, "hello", 5) == 0) {
NDPI_LOG_DBG(ndpi_struct,
- "need next packet, initial hello packet of SIP out calls.\n");
+ "need next packet, initial hello packet of SIP out calls.\n");
return;
}
- if (payload_len == 1 && payload[0] == 0) {
+ if(payload_len == 1 && payload[0] == 0) {
NDPI_LOG_DBG(ndpi_struct,
- "need next packet, payload_packet_len == 1 && payload[0] == 0.\n");
+ "need next packet, payload_packet_len == 1 && payload[0] == 0.\n");
return;
}
- if (payload_len == 3 && memcmp(payload, "png", 3) == 0) {
+ if(payload_len == 3 && memcmp(payload, "png", 3) == 0) {
/* weird packet found in Ninja GlobalIP trace */
NDPI_LOG_DBG(ndpi_struct, "skipping packet with len = 3 and png payload\n");
return;
}
- if (payload_len < 12) {
+ if(payload_len < 12) {
NDPI_LOG_DBG(ndpi_struct, "minimal packet size for rtp packets: 12\n");
goto exclude_rtp;
}
- if (payload_len == 12 && get_u_int32_t(payload, 0) == 0 && get_u_int32_t(payload, 4) == 0 && get_u_int32_t(payload, 8) == 0) {
+ if(payload_len == 12 && get_u_int32_t(payload, 0) == 0 && get_u_int32_t(payload, 4) == 0 && get_u_int32_t(payload, 8) == 0) {
NDPI_LOG_DBG(ndpi_struct, "skipping packet with len = 12 and only 0-bytes\n");
return;
}
- if ((payload[0] & 0xc0) == 0xc0 || (payload[0] & 0xc0) == 0x40 || (payload[0] & 0xc0) == 0x00) {
+ if((payload[0] & 0xc0) == 0xc0 || (payload[0] & 0xc0) == 0x40 || (payload[0] & 0xc0) == 0x00) {
NDPI_LOG_DBG(ndpi_struct, "version = 3 || 1 || 0, maybe first rtp packet\n");
return;
}
- if ((payload[0] & 0xc0) != 0x80) {
+ if((payload[0] & 0xc0) != 0x80) {
NDPI_LOG_DBG(ndpi_struct, "rtp version must be 2, first two bits of a packets must be 10\n");
goto exclude_rtp;
}
/* rtp_payload_type are the last seven bits of the second byte */
- if (flow->rtp_payload_type[packet->packet_direction] != (payload[1] & 0x7F)) {
+ if(flow->rtp_payload_type[packet->packet_direction] != (payload[1] & 0x7F)) {
NDPI_LOG_DBG(ndpi_struct, "payload_type has changed, reset stages\n");
packet->packet_direction == 0 ? (flow->rtp_stage1 = 0) : (flow->rtp_stage2 = 0);
}
@@ -280,56 +282,56 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
stage = (packet->packet_direction == 0 ? flow->rtp_stage1 : flow->rtp_stage2);
- if (stage > 0) {
+ if(stage > 0) {
NDPI_LOG_DBG(ndpi_struct, "stage = %u\n", packet->packet_direction == 0 ? flow->rtp_stage1 : flow->rtp_stage2);
- if (flow->rtp_ssid[packet->packet_direction] != get_u_int32_t(payload, 8)) {
+ if(flow->rtp_ssid[packet->packet_direction] != get_u_int32_t(payload, 8)) {
NDPI_LOG_DBG(ndpi_struct, "ssid has changed, goto exclude rtp\n");
goto exclude_rtp;
}
- if (seqnum == flow->rtp_seqnum[packet->packet_direction]) {
+ if(seqnum == flow->rtp_seqnum[packet->packet_direction]) {
NDPI_LOG_DBG(ndpi_struct, "maybe \"retransmission\", need next packet\n");
return;
- } else if ((u_int16_t) (seqnum - flow->rtp_seqnum[packet->packet_direction]) < RTP_MAX_OUT_OF_ORDER) {
+ } else if((u_int16_t) (seqnum - flow->rtp_seqnum[packet->packet_direction]) < RTP_MAX_OUT_OF_ORDER) {
NDPI_LOG_DBG(ndpi_struct,
- "new packet has larger sequence number (within valid range)\n");
+ "new packet has larger sequence number (within valid range)\n");
update_seq(ndpi_struct, flow, packet->packet_direction, seqnum);
- } else if ((u_int16_t) (flow->rtp_seqnum[packet->packet_direction] - seqnum) < RTP_MAX_OUT_OF_ORDER) {
+ } else if((u_int16_t) (flow->rtp_seqnum[packet->packet_direction] - seqnum) < RTP_MAX_OUT_OF_ORDER) {
NDPI_LOG_DBG(ndpi_struct,
- "new packet has smaller sequence number (within valid range)\n");
+ "new packet has smaller sequence number (within valid range)\n");
init_seq(ndpi_struct, flow, packet->packet_direction, seqnum, 1);
} else {
NDPI_LOG_DBG(ndpi_struct,
- "sequence number diff is too big, goto exclude rtp.\n");
+ "sequence number diff is too big, goto exclude rtp.\n");
goto exclude_rtp;
}
} else {
NDPI_LOG_DBG(ndpi_struct, "rtp_ssid[%u] = %u\n", packet->packet_direction,
- flow->rtp_ssid[packet->packet_direction]);
+ flow->rtp_ssid[packet->packet_direction]);
flow->rtp_ssid[packet->packet_direction] = get_u_int32_t(payload, 8);
- if (flow->packet_counter < 3) {
+ if(flow->packet_counter < 3) {
NDPI_LOG_DBG(ndpi_struct, "packet_counter < 3, need next packet\n");
}
init_seq(ndpi_struct, flow, packet->packet_direction, seqnum, 1);
}
- if (seqnum <= 3) {
+ if(seqnum <= 3) {
NDPI_LOG_DBG(ndpi_struct, "sequence_number = %u, too small, need next packet, return\n", seqnum);
return;
}
- if (stage == 3) {
+ if(stage == 3) {
NDPI_LOG_DBG(ndpi_struct, "add connection I\n");
ndpi_int_rtp_add_connection(ndpi_struct, flow);
} else {
packet->packet_direction == 0 ? flow->rtp_stage1++ : flow->rtp_stage2++;
NDPI_LOG_DBG(ndpi_struct, "stage[%u]++; need next packet\n",
- packet->packet_direction);
+ packet->packet_direction);
}
return;
- exclude_rtp:
- if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STUN
- || /* packet->real_protocol_read_only == NDPI_PROTOCOL_STUN */) {
+exclude_rtp:
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STUN
+ || /* packet->real_protocol_read_only == NDPI_PROTOCOL_STUN */) {
NDPI_LOG_DBG(ndpi_struct, "STUN: is detected, need next packet\n");
return;
}
@@ -344,17 +346,17 @@ void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, struct nd
struct ndpi_packet_struct *packet = &flow->packet;
- if (packet->udp) {
+ if(packet->udp) {
ndpi_rtp_search(ndpi_struct, flow, packet->payload, packet->payload_packet_len);
- } else if (packet->tcp) {
+ } else if(packet->tcp) {
/* skip special packets seen at yahoo traces */
- if (packet->payload_packet_len >= 20 && ntohs(get_u_int16_t(packet->payload, 2)) + 20 == packet->payload_packet_len &&
- packet->payload[0] == 0x90 && packet->payload[1] >= 0x01 && packet->payload[1] <= 0x07) {
- if (flow->packet_counter == 2)
+ if(packet->payload_packet_len >= 20 && ntohs(get_u_int16_t(packet->payload, 2)) + 20 == packet->payload_packet_len &&
+ packet->payload[0] == 0x90 && packet->payload[1] >= 0x01 && packet->payload[1] <= 0x07) {
+ if(flow->packet_counter == 2)
flow->l4.tcp.rtp_special_packets_seen = 1;
NDPI_LOG_DBG(ndpi_struct,
- "skipping STUN-like, special yahoo packets with payload[0] == 0x90.\n");
+ "skipping STUN-like, special yahoo packets with payload[0] == 0x90.\n");
return;
}
@@ -365,12 +367,12 @@ void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, struct nd
* we can remove this restriction
*/
- if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STUN
- || packet->detected_protocol_stack[0] == NDPI_PROTOCOL_RTP) {
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STUN
+ || packet->detected_protocol_stack[0] == NDPI_PROTOCOL_RTP) {
/* RTP may be encapsulated in TCP packets */
- if (packet->payload_packet_len >= 2 && ntohs(get_u_int16_t(packet->payload, 0)) + 2 == packet->payload_packet_len) {
+ if(packet->payload_packet_len >= 2 && ntohs(get_u_int16_t(packet->payload, 0)) + 2 == packet->payload_packet_len) {
/* TODO there could be several RTP packets in a single TCP packet so maybe the detection could be
* improved by checking only the RTP packet of given length */
@@ -381,9 +383,9 @@ void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, struct nd
}
}
- if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN && flow->l4.tcp.rtp_special_packets_seen == 1) {
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN && flow->l4.tcp.rtp_special_packets_seen == 1) {
- if (packet->payload_packet_len >= 4 && ntohl(get_u_int32_t(packet->payload, 0)) + 4 == packet->payload_packet_len) {
+ if(packet->payload_packet_len >= 4 && ntohl(get_u_int32_t(packet->payload, 0)) + 4 == packet->payload_packet_len) {
/* TODO there could be several RTP packets in a single TCP packet so maybe the detection could be
* improved by checking only the RTP packet of given length */
@@ -394,7 +396,7 @@ void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, struct nd
}
}
- if (NDPI_FLOW_PROTOCOL_EXCLUDED(ndpi_struct, flow, NDPI_PROTOCOL_STUN)) {
+ if(NDPI_FLOW_PROTOCOL_EXCLUDED(ndpi_struct, flow, NDPI_PROTOCOL_STUN)) {
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
} else {
NDPI_LOG_DBG(ndpi_struct, "STUN not yet excluded, need next packet\n");
@@ -416,4 +418,3 @@ void init_rtp_dissector(struct ndpi_detection_module_struct *ndpi_struct,
*id += 1;
}
-
diff --git a/src/lib/protocols/ssh.c b/src/lib/protocols/ssh.c
index 1a20078c3..7e5ca5e62 100644
--- a/src/lib/protocols/ssh.c
+++ b/src/lib/protocols/ssh.c
@@ -2,7 +2,7 @@
* ssh.c
*
* Copyright (C) 2009-2011 by ipoque GmbH
- * Copyright (C) 2011-18 - ntop.org
+ * Copyright (C) 2011-19 - ntop.org
*
* This file is part of nDPI, an open source deep packet inspection
* library based on the OpenDPI and PACE technology by ipoque GmbH
@@ -19,7 +19,7 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with nDPI. If not, see <http://www.gnu.org/licenses/>.
- *
+ *
*/
#include "ndpi_protocol_ids.h"
@@ -27,12 +27,134 @@
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_SSH
#include "ndpi_api.h"
+#include "ndpi_md5.h"
+
+/*
+ HASSH - https://github.com/salesforce/hassh
+
+ https://github.com/salesforce/hassh/blob/master/python/hassh.py
+
+ [server]
+ skex = packet.ssh.kex_algorithms
+ seastc = packet.ssh.encryption_algorithms_server_to_client
+ smastc = packet.ssh.mac_algorithms_server_to_client
+ scastc = packet.ssh.compression_algorithms_server_to_client
+ hasshs_str = ';'.join([skex, seastc, smastc, scastc])
+
+ [client]
+ ckex = packet.ssh.kex_algorithms
+ ceacts = packet.ssh.encryption_algorithms_client_to_server
+ cmacts = packet.ssh.mac_algorithms_client_to_server
+ ccacts = packet.ssh.compression_algorithms_client_to_server
+ hassh_str = ';'.join([ckex, ceacts, cmacts, ccacts])
+*/
+
+/* #define SSH_DEBUG 1 */
+
+/* ************************************************************************ */
static void ndpi_int_ssh_add_connection(struct ndpi_detection_module_struct
- *ndpi_struct, struct ndpi_flow_struct *flow){
+ *ndpi_struct, struct ndpi_flow_struct *flow) {
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SSH, NDPI_PROTOCOL_UNKNOWN);
}
+/* ************************************************************************ */
+
+static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,
+ char *buf, u_int8_t client_hash) {
+ u_int16_t offset = 22, buf_out_len = 0;
+ u_int32_t len = ntohl(*(u_int32_t*)&packet->payload[offset]);
+
+ if(len < (packet->payload_packet_len-offset)) {
+ /* ssh.kex_algorithms [C/S] */
+ offset += 4;
+ strncpy(buf, (const char *)&packet->payload[offset], buf_out_len = len);
+ buf[buf_out_len++] = ';';
+ offset += len;
+
+ /* ssh.server_host_key_algorithms [None] */
+ len = ntohl(*(u_int32_t*)&packet->payload[offset]);
+ offset += 4 + len;
+
+ /* ssh.encryption_algorithms_client_to_server [C] */
+ len = ntohl(*(u_int32_t*)&packet->payload[offset]);
+
+ if(client_hash) {
+ offset += 4;
+ strncpy(&buf[buf_out_len], (const char *)&packet->payload[offset], len);
+ buf_out_len += len;
+ buf[buf_out_len++] = ';';
+ offset += len;
+ } else
+ offset += 4 + len;
+
+ /* ssh.encryption_algorithms_server_to_client [S] */
+ len = ntohl(*(u_int32_t*)&packet->payload[offset]);
+ if(!client_hash) {
+ offset += 4;
+ strncpy(&buf[buf_out_len], (const char *)&packet->payload[offset], len);
+ buf_out_len += len;
+ buf[buf_out_len++] = ';';
+ offset += len;
+ } else
+ offset += 4 + len;
+
+ /* ssh.mac_algorithms_client_to_server [C] */
+ len = ntohl(*(u_int32_t*)&packet->payload[offset]);
+ if(client_hash) {
+ offset += 4;
+ strncpy(&buf[buf_out_len], (const char *)&packet->payload[offset], len);
+ buf_out_len += len;
+ buf[buf_out_len++] = ';';
+ offset += len;
+ } else
+ offset += 4 + len;
+
+ /* ssh.mac_algorithms_server_to_client [S] */
+ len = ntohl(*(u_int32_t*)&packet->payload[offset]);
+ if(!client_hash) {
+ offset += 4;
+ strncpy(&buf[buf_out_len], (const char *)&packet->payload[offset], len);
+ buf_out_len += len;
+ buf[buf_out_len++] = ';';
+ offset += len;
+ } else
+ offset += 4 + len;
+
+ /* ssh.compression_algorithms_client_to_server [C] */
+ len = ntohl(*(u_int32_t*)&packet->payload[offset]);
+ if(client_hash) {
+ offset += 4;
+ strncpy(&buf[buf_out_len], (const char *)&packet->payload[offset], len);
+ buf_out_len += len;
+ offset += len;
+ } else
+ offset += 4 + len;
+
+ /* ssh.compression_algorithms_server_to_client [S] */
+ len = ntohl(*(u_int32_t*)&packet->payload[offset]);
+ if(!client_hash) {
+ offset += 4;
+ strncpy(&buf[buf_out_len], (const char *)&packet->payload[offset], len);
+ buf_out_len += len;
+ offset += len;
+ } else
+ offset += 4 + len;
+
+ /* ssh.languages_client_to_server [None] */
+
+ /* ssh.languages_server_to_client [None] */
+ }
+
+#ifdef SSH_DEBUG
+ printf("\n[SSH] %s\n", buf);
+#endif
+
+ return(buf_out_len);
+}
+
+/* ************************************************************************ */
+
static void ndpi_ssh_zap_cr(char *str, int len) {
len--;
@@ -45,46 +167,132 @@ static void ndpi_ssh_zap_cr(char *str, int len) {
}
}
-void ndpi_search_ssh_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
-{
- struct ndpi_packet_struct *packet = &flow->packet;
+/* ************************************************************************ */
+
+void ndpi_search_ssh_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+#ifdef SSH_DEBUG
+ printf("\n[SSH] [stage: %u]\n", flow->l4.tcp.ssh_stage);
+#endif
- if (flow->l4.tcp.ssh_stage == 0) {
- if (packet->payload_packet_len > 7 && packet->payload_packet_len < 100
+ if(flow->l4.tcp.ssh_stage == 0) {
+ if(packet->payload_packet_len > 7 && packet->payload_packet_len < 100
&& memcmp(packet->payload, "SSH-", 4) == 0) {
if(!ndpi_struct->disable_metadata_export) {
- int len = ndpi_min(sizeof(flow->protos.ssh.client_signature)-1, packet->payload_packet_len);
+ int len = ndpi_min(sizeof(flow->protos.ssh.client_signature)-1, packet->payload_packet_len);
+
strncpy(flow->protos.ssh.client_signature, (const char *)packet->payload, len);
flow->protos.ssh.client_signature[len] = '\0';
ndpi_ssh_zap_cr(flow->protos.ssh.client_signature, len);
+
+#ifdef SSH_DEBUG
+ printf("\n[SSH] [client_signature: %s]\n", flow->protos.ssh.client_signature);
+#endif
}
-
+
NDPI_LOG_DBG2(ndpi_struct, "ssh stage 0 passed\n");
flow->l4.tcp.ssh_stage = 1 + packet->packet_direction;
+ flow->guessed_host_protocol_id = flow->guessed_protocol_id = NDPI_PROTOCOL_SSH;
return;
}
- } else if (flow->l4.tcp.ssh_stage == (2 - packet->packet_direction)) {
- if (packet->payload_packet_len > 7 && packet->payload_packet_len < 500
+ } else if(flow->l4.tcp.ssh_stage == (2 - packet->packet_direction)) {
+ if(packet->payload_packet_len > 7 && packet->payload_packet_len < 500
&& memcmp(packet->payload, "SSH-", 4) == 0) {
if(!ndpi_struct->disable_metadata_export) {
int len = ndpi_min(sizeof(flow->protos.ssh.server_signature)-1, packet->payload_packet_len);
+
strncpy(flow->protos.ssh.server_signature, (const char *)packet->payload, len);
flow->protos.ssh.server_signature[len] = '\0';
ndpi_ssh_zap_cr(flow->protos.ssh.server_signature, len);
+
+#ifdef SSH_DEBUG
+ printf("\n[SSH] [server_signature: %s]\n", flow->protos.ssh.server_signature);
+#endif
+
+ NDPI_LOG_DBG2(ndpi_struct, "ssh stage 1 passed\n");
+ flow->l4.tcp.ssh_stage++;;
+ flow->guessed_host_protocol_id = flow->guessed_protocol_id = NDPI_PROTOCOL_SSH;
+ } else {
+ NDPI_LOG_INFO(ndpi_struct, "found ssh\n");
+ ndpi_int_ssh_add_connection(ndpi_struct, flow);
}
-
- NDPI_LOG_INFO(ndpi_struct, "found ssh\n");
-
- ndpi_int_ssh_add_connection(ndpi_struct, flow);
+
+#ifdef SSH_DEBUG
+ printf("\n[SSH] [completed stage: %u]\n", flow->l4.tcp.ssh_stage);
+#endif
+
return;
+ }
+ } else {
+ u_int8_t msgcode = *(packet->payload + 5);
+ ndpi_MD5_CTX ctx;
+
+#ifdef SSH_DEBUG
+ printf("\n[SSH] [stage: %u][msg: %u]\n", flow->l4.tcp.ssh_stage, msgcode);
+#endif
+ if(msgcode == 20 /* key exchange init */) {
+ char *hassh_buf = calloc(packet->payload_packet_len, sizeof(char));
+ u_int i, len;
+
+ if(hassh_buf) {
+ if(flow->l4.tcp.ssh_stage == 3) {
+ u_char fingerprint_client[16];
+
+ len = concat_hash_string(packet, hassh_buf, 1 /* client */);
+
+ ndpi_MD5Init(&ctx);
+ ndpi_MD5Update(&ctx, (const unsigned char *)hassh_buf, len);
+ ndpi_MD5Final(fingerprint_client, &ctx);
+
+#ifdef SSH_DEBUG
+ {
+ printf("\n[SSH] [client][%s][", hassh_buf);
+ for(i=0; i<16; i++) printf("%02X", fingerprint_client[i]);
+ printf("]\n");
+ }
+#endif
+ for(i=0; i<16; i++) sprintf(&flow->protos.ssh.hassh_client[i*2], "%02X", fingerprint_client[i] & 0xFF);
+ flow->protos.ssh.hassh_client[32] = '\0';
+ } else {
+ u_char fingerprint_server[16];
+
+ len = concat_hash_string(packet, hassh_buf, 0 /* server */);
+
+ ndpi_MD5Init(&ctx);
+ ndpi_MD5Update(&ctx, (const unsigned char *)hassh_buf, len);
+ ndpi_MD5Final(fingerprint_server, &ctx);
+
+#ifdef SSH_DEBUG
+ {
+ printf("\n[SSH] [server][%s][", hassh_buf);
+ for(i=0; i<16; i++) printf("%02X", fingerprint_server[i]);
+ printf("]\n");
+ }
+#endif
+
+ for(i=0; i<16; i++) sprintf(&flow->protos.ssh.hassh_server[i*2], "%02X", fingerprint_server[i] & 0xFF);
+ flow->protos.ssh.hassh_server[32] = '\0';
+ }
+
+ free(hassh_buf);
+ }
}
+
+ if(flow->l4.tcp.ssh_stage++ == 4) {
+ NDPI_LOG_INFO(ndpi_struct, "found ssh\n");
+ ndpi_int_ssh_add_connection(ndpi_struct, flow);
+ }
+
+ return;
}
NDPI_LOG_DBG(ndpi_struct, "excluding ssh at stage %d\n", flow->l4.tcp.ssh_stage);
NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SSH);
}
+/* ************************************************************************ */
void init_ssh_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask)
{
diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c
index 202b3d939..8334c667a 100644
--- a/src/lib/protocols/stun.c
+++ b/src/lib/protocols/stun.c
@@ -30,7 +30,9 @@
#define MAX_NUM_STUN_PKTS 8
-// #define DEBUG_STUN 1
+/* #define DEBUG_STUN 1 */
+
+/* #define DEBUG_LRU 1 */
struct stun_packet_header {
u_int16_t msg_type, msg_len;
@@ -38,9 +40,43 @@ struct stun_packet_header {
u_int8_t transaction_id[8];
};
+/* ************************************************************ */
+
+u_int32_t get_stun_lru_key(struct ndpi_flow_struct *flow) {
+ return(flow->packet.iph->saddr + flow->packet.udp->source);
+}
+
+/* ************************************************************ */
+
static void ndpi_int_stun_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
- u_int proto, struct ndpi_flow_struct *flow) {
- ndpi_set_detected_protocol(ndpi_struct, flow, proto, NDPI_PROTOCOL_UNKNOWN);
+ struct ndpi_flow_struct *flow,
+ u_int app_proto, u_int proto) {
+ if(ndpi_struct->stun_cache == NULL)
+ ndpi_struct->stun_cache = ndpi_lru_cache_init(1024);
+
+ if(ndpi_struct->stun_cache
+ && flow->packet.iph
+ && flow->packet.udp
+ && (app_proto != NDPI_PROTOCOL_UNKNOWN)
+ ) /* Cache flow sender info */ {
+ u_int32_t key = get_stun_lru_key(flow);
+ u_int16_t cached_proto;
+
+ if(ndpi_lru_find_cache(ndpi_struct->stun_cache, key, &cached_proto, 0 /* Don't remove it as it can be used for other connections */)) {
+#ifdef DEBUG_LRU
+ printf("[LRU] FOUND %u / %u: no need to cache %u.%u\n", key, cached_proto, proto, app_proto);
+#endif
+ app_proto = cached_proto, proto = NDPI_PROTOCOL_STUN;
+ } else {
+#ifdef DEBUG_LRU
+ printf("[LRU] ADDING %u / %u.%u\n", key, proto, app_proto);
+#endif
+
+ ndpi_lru_add_to_cache(ndpi_struct->stun_cache, key, app_proto);
+ }
+ }
+
+ ndpi_set_detected_protocol(ndpi_struct, flow, app_proto, proto);
}
typedef enum {
@@ -48,6 +84,7 @@ typedef enum {
NDPI_IS_NOT_STUN
} ndpi_int_stun_t;
+/* ************************************************************ */
static int is_google_ip_address(u_int32_t host) {
if(
@@ -59,6 +96,29 @@ static int is_google_ip_address(u_int32_t host) {
return(0);
}
+/* ************************************************************ */
+
+/*
+ WhatsApp
+ 31.13.86.48
+ 31.13.92.50
+ 157.240.20.51
+ 157.240.21.51
+ 185.60.216.51
+
+ Messenger
+ 31.13.86.5
+*/
+
+static int is_messenger_ip_address(u_int32_t host) {
+ if(host == 0x1F0D5605 /* 31.13.86.5 */)
+ return(1);
+ else
+ return(0);
+}
+
+/* ************************************************************ */
+
static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
const u_int8_t * payload,
@@ -77,7 +137,7 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
*is_whatsapp = 0, *is_messenger = 0, *is_duo = 0;
if(payload_length < sizeof(struct stun_packet_header)) {
- /* This looks like an invlid packet */
+ /* This looks like an invalid packet */
if(flow->protos.stun_ssl.stun.num_udp_pkts > 0) {
*is_whatsapp = 1;
@@ -98,18 +158,47 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
if(msg_type > 0x000C)
return(NDPI_IS_NOT_STUN);
+ if(ndpi_struct->stun_cache) {
+ u_int16_t proto;
+ u_int32_t key = get_stun_lru_key(flow);
+
+ if(ndpi_lru_find_cache(ndpi_struct->stun_cache, key, &proto, 0 /* Don't remove it as it can be used for other connections */)) {
+#ifdef DEBUG_LRU
+ printf("[LRU] FOUND %u / %u\n", key, proto);
+#endif
+
+ flow->guessed_host_protocol_id = proto, flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
+ return(NDPI_IS_STUN);
+ } else {
+#ifdef DEBUG_LRU
+ printf("[LRU] NOT FOUND %u\n", key);
+#endif
+ }
+ } else {
+#ifdef DEBUG_LRU
+ printf("[LRU] NO/EMPTY CACHE\n");
+#endif
+ }
+
if(msg_type == 0x01 /* Binding Request */) {
flow->protos.stun_ssl.stun.num_binding_requests++;
- if((msg_len == 0) && (flow->guessed_host_protocol_id == NDPI_PROTOCOL_GOOGLE)) {
+
+ if((msg_len == 0) && (flow->guessed_host_protocol_id == NDPI_PROTOCOL_GOOGLE))
flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO;
- }
+ else
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_STUN;
+
+ flow->protos.stun_ssl.stun.num_udp_pkts++;
+
+ if(msg_len == 0)
+ return(NDPI_IS_NOT_STUN); /* This to keep analyzing STUN instead of giving up */
}
if((msg_len == 0) && (flow->guessed_host_protocol_id == NDPI_PROTOCOL_UNKNOWN)) {
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
return(NDPI_IS_NOT_STUN);
}
-
+
flow->protos.stun_ssl.stun.num_udp_pkts++;
/*
@@ -131,9 +220,20 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
if((payload[0] != 0x80) && ((msg_len+20) > payload_length))
return(NDPI_IS_NOT_STUN);
- else
- flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
-
+ else {
+ switch(flow->guessed_protocol_id) {
+ case NDPI_PROTOCOL_HANGOUT_DUO:
+ case NDPI_PROTOCOL_MESSENGER:
+ case NDPI_PROTOCOL_WHATSAPP_VOICE:
+ /* Don't overwrite the protocol with sub-STUN protocols */
+ break;
+
+ default:
+ flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
+ break;
+ }
+ }
+
if(payload_length == (msg_len+20)) {
if(msg_type <= 0x000b) /* http://www.3cx.com/blog/voip-howto/stun-details/ */ {
u_int offset = 20;
@@ -157,6 +257,10 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
if(x != 0)
len += 4-x;
+#ifdef DEBUG_STUN
+ printf("==> Attribute: %04X\n", attribute);
+#endif
+
switch(attribute) {
case 0x0008: /* Message Integrity */
case 0x0020: /* XOR-MAPPED-ADDRESSES */
@@ -166,6 +270,28 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
/* These are the only messages apparently whatsapp voice can use */
break;
+ case 0x0014: /* Realm */
+ {
+ u_int16_t realm_len = ntohs(*((u_int16_t*)&payload[offset+2]));
+
+ if(flow->host_server_name[0] == '\0') {
+ u_int j, i = (realm_len > sizeof(flow->host_server_name)) ? sizeof(flow->host_server_name) : realm_len;
+ u_int k = offset+4;
+
+ memset(flow->host_server_name, 0, sizeof(flow->host_server_name));
+
+ for(j=0; j<i; j++)
+ flow->host_server_name[j] = payload[k++];
+
+ if(strstr((char*)flow->host_server_name, "google.com") != NULL) {
+ *is_duo = 1;
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO, flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
+ return(NDPI_IS_STUN);
+ }
+ }
+ }
+ break;
+
case 0xC057: /* Messeger */
if(msg_type == 0x0001) {
if((msg_len == 100) || (msg_len == 104)) {
@@ -173,7 +299,12 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
return(NDPI_IS_STUN);
} else if(msg_len == 76) {
*is_duo = 1;
- return(NDPI_IS_STUN);
+
+ if(1) {
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO, flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
+ return(NDPI_IS_NOT_STUN); /* This case is found also with signal traffic */
+ } else
+ return(NDPI_IS_STUN);
}
}
break;
@@ -185,6 +316,9 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
&& (payload[offset+6] == 0x00)
&& (payload[offset+7] == 0x00)) {
/* Either skype for business or "normal" skype with multiparty call */
+#ifdef DEBUG_STUN
+ printf("==> Skype found\n");
+#endif
flow->protos.stun_ssl.stun.is_skype = 1;
return(NDPI_IS_STUN);
}
@@ -201,6 +335,10 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
case 0x0800:
/* printf("====>>>> %04X\n", attribute); */
flow->protos.stun_ssl.stun.is_skype = 1;
+#ifdef DEBUG_STUN
+ printf("==> Skype (2) found\n");
+#endif
+
return(NDPI_IS_STUN);
break;
@@ -213,6 +351,10 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
&& ((payload[offset+7] == 0x02) || (payload[offset+7] == 0x03))
) {
flow->protos.stun_ssl.stun.is_skype = 1;
+#ifdef DEBUG_STUN
+ printf("==> Skype (3) found\n");
+#endif
+
return(NDPI_IS_STUN);
}
break;
@@ -221,7 +363,7 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
can_this_be_whatsapp_voice = 0;
flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO;
break;
-
+
default:
/* This means this STUN packet cannot be confused with whatsapp voice */
#ifdef DEBUG_STUN
@@ -249,15 +391,16 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
udp_stun_found:
if(can_this_be_whatsapp_voice) {
struct ndpi_packet_struct *packet = &flow->packet;
-
+
flow->protos.stun_ssl.stun.num_processed_pkts++;
#ifdef DEBUG_STUN
printf("==>> NDPI_PROTOCOL_WHATSAPP_VOICE\n");
#endif
- if((ntohs(packet->udp->source) == 3478) || (ntohs(packet->udp->dest) == 3478))
- flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_VOICE;
- else
+ if((ntohs(packet->udp->source) == 3478) || (ntohs(packet->udp->dest) == 3478)) {
+ flow->guessed_host_protocol_id = (is_messenger_ip_address(ntohl(packet->iph->saddr)) || is_messenger_ip_address(ntohl(packet->iph->daddr))) ?
+ NDPI_PROTOCOL_MESSENGER : NDPI_PROTOCOL_WHATSAPP_VOICE;
+ } else
flow->guessed_host_protocol_id = (is_google_ip_address(ntohl(packet->iph->saddr)) || is_google_ip_address(ntohl(packet->iph->daddr)))
? NDPI_PROTOCOL_HANGOUT_DUO : NDPI_PROTOCOL_WHATSAPP_VOICE;
return((flow->protos.stun_ssl.stun.num_udp_pkts < MAX_NUM_STUN_PKTS) ? NDPI_IS_NOT_STUN : NDPI_IS_STUN);
@@ -295,23 +438,24 @@ void ndpi_search_stun(struct ndpi_detection_module_struct *ndpi_struct, struct n
if(ndpi_int_check_stun(ndpi_struct, flow, packet->payload + 2,
packet->payload_packet_len - 2,
&is_whatsapp, &is_messenger, &is_duo) == NDPI_IS_STUN) {
- if(flow->guessed_protocol_id == 0) flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
+ if(flow->guessed_protocol_id == NDPI_PROTOCOL_UNKNOWN) flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
if(is_messenger) {
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_MESSENGER, NDPI_PROTOCOL_STUN);
+ ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MESSENGER, NDPI_PROTOCOL_STUN);
return;
} else if(is_duo) {
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_HANGOUT_DUO, NDPI_PROTOCOL_STUN);
+ ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HANGOUT_DUO, NDPI_PROTOCOL_STUN);
return;
} else if(flow->protos.stun_ssl.stun.is_skype) {
NDPI_LOG_INFO(ndpi_struct, "found Skype\n");
if((flow->protos.stun_ssl.stun.num_processed_pkts >= 8) || (flow->protos.stun_ssl.stun.num_binding_requests >= 4))
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE_CALL, NDPI_PROTOCOL_SKYPE);
+ ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE_CALL, NDPI_PROTOCOL_SKYPE);
} else {
NDPI_LOG_INFO(ndpi_struct, "found UDP stun\n"); /* Ummmmm we're in the TCP branch. This code looks bad */
- ndpi_int_stun_add_connection(ndpi_struct,
- is_whatsapp ? (is_whatsapp == 1 ? NDPI_PROTOCOL_WHATSAPP_VOICE : NDPI_PROTOCOL_WHATSAPP_VIDEO) : NDPI_PROTOCOL_STUN, flow);
+ ndpi_int_stun_add_connection(ndpi_struct, flow,
+ is_whatsapp ? (is_whatsapp == 1 ? NDPI_PROTOCOL_WHATSAPP_VOICE : NDPI_PROTOCOL_WHATSAPP_VIDEO) : NDPI_PROTOCOL_STUN,
+ NDPI_PROTOCOL_UNKNOWN);
}
return;
@@ -323,26 +467,25 @@ void ndpi_search_stun(struct ndpi_detection_module_struct *ndpi_struct, struct n
if(ndpi_int_check_stun(ndpi_struct, flow, packet->payload,
packet->payload_packet_len,
&is_whatsapp, &is_messenger, &is_duo) == NDPI_IS_STUN) {
- if(flow->guessed_protocol_id == 0) flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
+ if(flow->guessed_protocol_id == NDPI_PROTOCOL_UNKNOWN) flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
if(is_messenger) {
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_MESSENGER, NDPI_PROTOCOL_STUN);
+ ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MESSENGER, NDPI_PROTOCOL_STUN);
return;
} else if(is_duo) {
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_HANGOUT_DUO, NDPI_PROTOCOL_STUN);
+ ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HANGOUT_DUO, NDPI_PROTOCOL_STUN);
return;
} else if(flow->protos.stun_ssl.stun.is_skype) {
NDPI_LOG_INFO(ndpi_struct, "Found Skype\n");
/* flow->protos.stun_ssl.stun.num_binding_requests < 4) ? NDPI_PROTOCOL_SKYPE_CALL_IN : NDPI_PROTOCOL_SKYPE_CALL_OUT */
if((flow->protos.stun_ssl.stun.num_processed_pkts >= 8) || (flow->protos.stun_ssl.stun.num_binding_requests >= 4))
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE_CALL, NDPI_PROTOCOL_SKYPE);
+ ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE_CALL, NDPI_PROTOCOL_SKYPE);
} else {
NDPI_LOG_INFO(ndpi_struct, "found UDP stun\n");
- ndpi_int_stun_add_connection(ndpi_struct,
+ ndpi_int_stun_add_connection(ndpi_struct, flow,
is_whatsapp ? (is_whatsapp == 1 ? NDPI_PROTOCOL_WHATSAPP_VOICE : NDPI_PROTOCOL_WHATSAPP_VIDEO)
- : NDPI_PROTOCOL_STUN,
- flow);
+ : NDPI_PROTOCOL_STUN, NDPI_PROTOCOL_UNKNOWN);
}
return;
diff --git a/src/lib/protocols/teamspeak.c b/src/lib/protocols/teamspeak.c
index 214a2fe99..170be1d7f 100644
--- a/src/lib/protocols/teamspeak.c
+++ b/src/lib/protocols/teamspeak.c
@@ -35,32 +35,43 @@ void ndpi_search_teamspeak(struct ndpi_detection_module_struct *ndpi_struct, str
struct ndpi_packet_struct *packet = &flow->packet;
NDPI_LOG_DBG(ndpi_struct, "search teamspeak\n");
+
- if (packet->udp != NULL) {
+#ifdef WEAK_DETECTION_CODE_DISABLED
+ if(packet->udp != NULL) {
u_int16_t udport, usport;
+
usport = ntohs(packet->udp->source), udport = ntohs(packet->udp->dest);
+
/* http://www.imfirewall.com/en/protocols/teamSpeak.htm */
- if (((usport == 9987 || udport == 9987) || (usport == 8767 || udport == 8767)) && packet->payload_packet_len >= 20) {
+ if(((usport == 9987 || udport == 9987) || (usport == 8767 || udport == 8767)) && packet->payload_packet_len >= 20) {
NDPI_LOG_INFO(ndpi_struct, "found TEAMSPEAK udp\n");
ndpi_int_teamspeak_add_connection(ndpi_struct, flow);
}
}
- else if (packet->tcp != NULL) {
- u_int16_t tdport, tsport;
- tsport = ntohs(packet->tcp->source), tdport = ntohs(packet->tcp->dest);
- /* https://github.com/Youx/soliloque-server/wiki/Connection-packet */
- if(packet->payload_packet_len >= 20) {
- if (((memcmp(packet->payload, "\xf4\xbe\x03\x00", 4) == 0)) ||
- ((memcmp(packet->payload, "\xf4\xbe\x02\x00", 4) == 0)) ||
+ else
+#endif
+
+ if(packet->tcp != NULL) {
+ u_int16_t tdport, tsport;
+ tsport = ntohs(packet->tcp->source), tdport = ntohs(packet->tcp->dest);
+ /* https://github.com/Youx/soliloque-server/wiki/Connection-packet */
+ if(packet->payload_packet_len >= 20) {
+ if(((memcmp(packet->payload, "\xf4\xbe\x03\x00", 4) == 0)) ||
+ ((memcmp(packet->payload, "\xf4\xbe\x02\x00", 4) == 0)) ||
((memcmp(packet->payload, "\xf4\xbe\x01\x00", 4) == 0))) {
- NDPI_LOG_INFO(ndpi_struct, "found TEAMSPEAK tcp\n");
- ndpi_int_teamspeak_add_connection(ndpi_struct, flow);
- } /* http://www.imfirewall.com/en/protocols/teamSpeak.htm */
- } else if ((tsport == 14534 || tdport == 14534) || (tsport == 51234 || tdport == 51234)) {
- NDPI_LOG_INFO(ndpi_struct, "found TEAMSPEAK\n");
- ndpi_int_teamspeak_add_connection(ndpi_struct, flow);
- }
- }
+ NDPI_LOG_INFO(ndpi_struct, "found TEAMSPEAK tcp\n");
+ ndpi_int_teamspeak_add_connection(ndpi_struct, flow);
+ } /* http://www.imfirewall.com/en/protocols/teamSpeak.htm */
+ }
+#if WEAK_DETECTION_CODE_DISABLED
+ else if((tsport == 14534 || tdport == 14534) || (tsport == 51234 || tdport == 51234)) {
+ NDPI_LOG_INFO(ndpi_struct, "found TEAMSPEAK\n");
+ ndpi_int_teamspeak_add_connection(ndpi_struct, flow);
+ }
+#endif
+ }
+
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
return;
}
diff --git a/src/lib/protocols/ssl.c b/src/lib/protocols/tls.c
index 18e8ca469..d9b7b0962 100644
--- a/src/lib/protocols/ssl.c
+++ b/src/lib/protocols/tls.c
@@ -1,7 +1,7 @@
/*
- * ssl.c
+ * tls.c - SSL/TLS/DTLS dissector
*
- * Copyright (C) 2016-18 - ntop.org
+ * Copyright (C) 2016-19 - ntop.org
*
* This file is part of nDPI, an open source deep packet inspection
* library based on the OpenDPI and PACE technology by ipoque GmbH
@@ -23,13 +23,14 @@
#include "ndpi_protocol_ids.h"
-#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_SSL
+#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_TLS
#include "ndpi_api.h"
+#include "ndpi_md5.h"
-/* #define CERTIFICATE_DEBUG 1 */
+// #define DEBUG_TLS 1
-#define NDPI_MAX_SSL_REQUEST_SIZE 10000
+#define NDPI_MAX_TLS_REQUEST_SIZE 10000
/* Skype.c */
extern u_int8_t is_skype_flow(struct ndpi_detection_module_struct *ndpi_struct,
@@ -37,220 +38,23 @@ extern u_int8_t is_skype_flow(struct ndpi_detection_module_struct *ndpi_struct,
/* **************************************** */
-typedef struct MD5Context {
- uint32_t buf[4];
- uint32_t bits[2];
- unsigned char in[64];
-} MD5_CTX;
-
-/* **************************************** */
-
-static int is_big_endian(void) {
- static const int n = 1;
- return ((char *) &n)[0] == 0;
-}
-
-static void byteReverse(unsigned char *buf, unsigned longs) {
- uint32_t t;
-
- // Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN
- if (is_big_endian()) {
- do {
- t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
- ((unsigned) buf[1] << 8 | buf[0]);
- * (uint32_t *) buf = t;
- buf += 4;
- } while (--longs);
- }
-}
-
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-#define MD5STEP(f, w, x, y, z, data, s) \
- ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
-
-// Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
-// initialization constants.
-static void MD5Init(MD5_CTX *ctx) {
- ctx->buf[0] = 0x67452301;
- ctx->buf[1] = 0xefcdab89;
- ctx->buf[2] = 0x98badcfe;
- ctx->buf[3] = 0x10325476;
-
- ctx->bits[0] = 0;
- ctx->bits[1] = 0;
-}
-
-static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) {
- uint32_t a, b, c, d;
-
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
-
- MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
- MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
- MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-
- MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-
-static void MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len) {
- uint32_t t;
-
- t = ctx->bits[0];
- if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
- ctx->bits[1]++;
- ctx->bits[1] += len >> 29;
-
- t = (t >> 3) & 0x3f;
-
- if (t) {
- unsigned char *p = (unsigned char *) ctx->in + t;
-
- t = 64 - t;
- if (len < t) {
- memcpy(p, buf, len);
- return;
- }
- memcpy(p, buf, t);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- buf += t;
- len -= t;
- }
-
- while (len >= 64) {
- memcpy(ctx->in, buf, 64);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- buf += 64;
- len -= 64;
- }
-
- memcpy(ctx->in, buf, len);
-}
-
-static void MD5Final(unsigned char digest[16], MD5_CTX *ctx) {
- unsigned count;
- unsigned char *p;
- uint32_t *c = (uint32_t*)ctx->in;
-
- count = (ctx->bits[0] >> 3) & 0x3F;
-
- p = ctx->in + count;
- *p++ = 0x80;
- count = 64 - 1 - count;
- if (count < 8) {
- memset(p, 0, count);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- memset(ctx->in, 0, 56);
- } else {
- memset(p, 0, count - 8);
- }
- byteReverse(ctx->in, 14);
-
- c[14] = ctx->bits[0];
- c[15] = ctx->bits[1];
-
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- byteReverse((unsigned char *) ctx->buf, 4);
- memcpy(digest, ctx->buf, 16);
- memset((char *) ctx, 0, sizeof(*ctx));
-}
-
-/* **************************************** */
-
-static u_int32_t ndpi_ssl_refine_master_protocol(struct ndpi_detection_module_struct *ndpi_struct,
- struct ndpi_flow_struct *flow, u_int32_t protocol)
-{
+static u_int32_t ndpi_tls_refine_master_protocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, u_int32_t protocol) {
struct ndpi_packet_struct *packet = &flow->packet;
if(((flow->l4.tcp.ssl_seen_client_cert == 1) && (flow->protos.stun_ssl.ssl.ja3_client[0] != '\0'))
|| ((flow->l4.tcp.ssl_seen_server_cert == 1) && (flow->protos.stun_ssl.ssl.ja3_server[0] != '\0'))
// || (flow->host_server_name[0] != '\0')
)
- protocol = NDPI_PROTOCOL_SSL;
+ protocol = NDPI_PROTOCOL_TLS;
else
- protocol = NDPI_PROTOCOL_SSL_NO_CERT;
+ protocol = NDPI_PROTOCOL_TLS_NO_CERT;
if(packet->tcp != NULL) {
switch(protocol) {
- case NDPI_PROTOCOL_SSL:
- case NDPI_PROTOCOL_SSL_NO_CERT:
+ case NDPI_PROTOCOL_TLS:
+ case NDPI_PROTOCOL_TLS_NO_CERT:
{
/*
In case of SSL there are probably sub-protocols
@@ -273,18 +77,21 @@ static u_int32_t ndpi_ssl_refine_master_protocol(struct ndpi_detection_module_st
return protocol;
}
-static void ndpi_int_ssl_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
- struct ndpi_flow_struct *flow, u_int32_t protocol)
-{
- if((protocol != NDPI_PROTOCOL_SSL)
- && (protocol != NDPI_PROTOCOL_SSL_NO_CERT)) {
+/* **************************************** */
+
+static void ndpi_int_tls_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, u_int32_t protocol) {
+ if((protocol != NDPI_PROTOCOL_TLS)
+ && (protocol != NDPI_PROTOCOL_TLS_NO_CERT)) {
ndpi_set_detected_protocol(ndpi_struct, flow, protocol, NDPI_PROTOCOL_UNKNOWN);
} else {
- protocol = ndpi_ssl_refine_master_protocol(ndpi_struct, flow, protocol);
+ protocol = ndpi_tls_refine_master_protocol(ndpi_struct, flow, protocol);
ndpi_set_detected_protocol(ndpi_struct, flow, protocol, NDPI_PROTOCOL_UNKNOWN);
}
}
+/* **************************************** */
+
/* Can't call libc functions from kernel space, define some stub instead */
#define ndpi_isalpha(ch) (((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z'))
@@ -296,8 +103,9 @@ static void ndpi_int_ssl_add_connection(struct ndpi_detection_module_struct *ndp
((ch) >= '[' && (ch) <= '`') || \
((ch) >= '{' && (ch) <= '~'))
-static void stripCertificateTrailer(char *buffer, int buffer_len) {
+/* **************************************** */
+static void stripCertificateTrailer(char *buffer, int buffer_len) {
int i, is_puny;
// printf("->%s<-\n", buffer);
@@ -346,42 +154,53 @@ static void stripCertificateTrailer(char *buffer, int buffer_len) {
buffer[i] = tolower(buffer[i]);
}
+/* **************************************** */
+
/* https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967 */
#define JA3_STR_LEN 1024
#define MAX_NUM_JA3 128
struct ja3_info {
- u_int16_t ssl_version;
+ u_int16_t tls_version;
u_int16_t num_cipher, cipher[MAX_NUM_JA3];
- u_int16_t num_ssl_extension, ssl_extension[MAX_NUM_JA3];
+ u_int16_t num_tls_extension, tls_extension[MAX_NUM_JA3];
u_int16_t num_elliptic_curve, elliptic_curve[MAX_NUM_JA3];
u_int8_t num_elliptic_curve_point_format, elliptic_curve_point_format[MAX_NUM_JA3];
};
/* **************************************** */
-/* code fixes courtesy of Alexsandro Brahm <alex@digistar.com.br> */
-int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
+int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
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_tls_version = (packet->payload[1] << 8) + packet->payload[2], ja3_str_len;
char ja3_str[JA3_STR_LEN];
- MD5_CTX ctx;
+ ndpi_MD5_CTX ctx;
u_char md5_hash[16];
- flow->protos.stun_ssl.ssl.ssl_version = ssl_version;
+ if(packet->udp) {
+ /* Check if this is DTLS or return */
+ if((packet->payload[1] != 0xfe)
+ || ((packet->payload[2] != 0xff) && (packet->payload[2] != 0xfd))) {
+ NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
+ return(0);
+ }
+ }
+
+ flow->protos.stun_ssl.ssl.ssl_version = pkt_tls_version;
memset(&ja3, 0, sizeof(ja3));
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
{
- u_int16_t ssl_len = (packet->payload[3] << 8) + packet->payload[4];
+ u_int16_t tls_len = (packet->payload[3] << 8) + packet->payload[4];
- printf("SSL Record [version: %u][len: %u]\n", ssl_version, ssl_len);
+ printf("SSL Record [version: 0x%04X][len: %u]\n", pkt_tls_version, tls_len);
}
#endif
@@ -390,9 +209,21 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
Patches courtesy of Denys Fedoryshchenko <nuclearcat@nuclearcat.com>
*/
if(packet->payload[0] == 0x16 /* Handshake */) {
- u_int16_t total_len = (packet->payload[3] << 8) + packet->payload[4] + 5 /* SSL Header */;
- u_int8_t handshake_protocol = packet->payload[5]; /* handshake protocol a bit misleading, it is message type according TLS specs */
+ u_int16_t total_len;
+ u_int8_t handshake_protocol, header_len;
+
+ if(packet->tcp) {
+ header_len = 5; /* SSL Header */
+ handshake_protocol = packet->payload[5]; /* handshake protocol a bit misleading, it is message type according TLS specs */
+ total_len = (packet->payload[3] << 8) + packet->payload[4];
+ } else {
+ header_len = 13; /* DTLS header */
+ handshake_protocol = packet->payload[13];
+ total_len = ntohs(*((u_int16_t*)&packet->payload[11]));
+ }
+ total_len += header_len;
+
memset(buffer, 0, buffer_len);
/* Truncate total len, search at least in incomplete packet */
@@ -401,48 +232,58 @@ 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
+ u_int16_t base_offset = packet->tcp ? 43 : 59;
+
+#ifdef DEBUG_TLS
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 */) {
+ || (handshake_protocol == 0x0b) /* 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]));
+ u_int16_t tls_version;
+ int i;
- ja3.ssl_version = ssl_version;
+ if(packet->tcp)
+ tls_version = ntohs(*((u_int16_t*)&packet->payload[header_len+4]));
+ else
+ tls_version = ntohs(*((u_int16_t*)&packet->payload[header_len+12]));
+
+ ja3.tls_version = tls_version;
if(handshake_protocol == 0x02) {
- u_int16_t offset = 43, extension_len, j;
- u_int8_t session_id_len = packet->payload[43];
+ u_int16_t offset = base_offset, extension_len, j;
+ u_int8_t session_id_len = packet->payload[offset];
-#ifdef CERTIFICATE_DEBUG
- printf("SSL Server Hello [version: 0x%04X]\n", ssl_version);
+#ifdef DEBUG_TLS
+ printf("SSL Server Hello [version: 0x%04X]\n", tls_version);
#endif
/*
The server hello decides about the SSL version of this flow
https://networkengineering.stackexchange.com/questions/55752/why-does-wireshark-show-version-tls-1-2-here-instead-of-tls-1-3
*/
- flow->protos.stun_ssl.ssl.ssl_version = ssl_version;
-
- if(ssl_version < 0x7F15 /* TLS 1.3 lacks of session id */)
- offset += session_id_len+1;
+ flow->protos.stun_ssl.ssl.ssl_version = tls_version;
+ if(packet->udp)
+ offset += 1;
+ else {
+ if(tls_version < 0x7F15 /* TLS 1.3 lacks of session id */)
+ 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 = ndpi_is_safe_ssl_cipher(ja3.cipher[0]);
flow->protos.stun_ssl.ssl.server_cipher = ja3.cipher[0];
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("SSL [server][session_id_len: %u][cipher: %04X]\n", session_id_len, ja3.cipher[0]);
#endif
offset += 2 + 1;
extension_len = ntohs(*((u_int16_t*)&packet->payload[offset]));
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("SSL [server][extension_len: %u]\n", extension_len);
#endif
offset += 2;
@@ -455,17 +296,17 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
id = ntohs(*((u_int16_t*)&packet->payload[offset]));
len = ntohs(*((u_int16_t*)&packet->payload[offset+2]));
- if(ja3.num_ssl_extension < MAX_NUM_JA3)
- ja3.ssl_extension[ja3.num_ssl_extension++] = id;
+ if(ja3.num_tls_extension < MAX_NUM_JA3)
+ ja3.tls_extension[ja3.num_tls_extension++] = id;
-#ifdef CERTIFICATE_DEBUG
- printf("SSL [server][extension_id: %u]\n", id);
+#ifdef DEBUG_TLS
+ printf("SSL [server][extension_id: %u/0x%04X]\n", id, id);
#endif
i += 4 + len, offset += 4 + len;
}
- ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.ssl_version);
+ ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.tls_version);
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]);
@@ -474,26 +315,26 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
/* ********** */
- for(i=0; i<ja3.num_ssl_extension; i++)
- ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", (i > 0) ? "-" : "", ja3.ssl_extension[i]);
+ for(i=0; i<ja3.num_tls_extension; i++)
+ ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", (i > 0) ? "-" : "", ja3.tls_extension[i]);
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("SSL [server] %s\n", ja3_str);
#endif
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("[JA3] Server: %s \n", ja3_str);
#endif
- MD5Init(&ctx);
- MD5Update(&ctx, (const unsigned char *)ja3_str, strlen(ja3_str));
- MD5Final(md5_hash, &ctx);
+ ndpi_MD5Init(&ctx);
+ ndpi_MD5Update(&ctx, (const unsigned char *)ja3_str, strlen(ja3_str));
+ ndpi_MD5Final(md5_hash, &ctx);
for(i=0, j=0; i<16; i++)
j += snprintf(&flow->protos.stun_ssl.ssl.ja3_server[j],
sizeof(flow->protos.stun_ssl.ssl.ja3_server)-j, "%02x", md5_hash[i]);
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("[JA3] Server: %s \n", flow->protos.stun_ssl.ssl.ja3_server);
#endif
@@ -554,28 +395,46 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
}
}
} else if(handshake_protocol == 0x01 /* Client Hello */) {
- u_int offset, base_offset = 43;
+ u_int offset;
- if(base_offset + 2 <= packet->payload_packet_len) {
- u_int16_t session_id_len = packet->payload[base_offset];
- u_int16_t ssl_version = ntohs(*((u_int16_t*)&packet->payload[9]));
+#ifdef DEBUG_TLS
+ printf("[base_offset: %u][payload_packet_len: %u]\n", base_offset, packet->payload_packet_len);
+#endif
- ja3.ssl_version = ssl_version;
+ if(base_offset + 2 <= packet->payload_packet_len) {
+ u_int16_t session_id_len;
+ u_int16_t tls_version;
+ if(packet->tcp)
+ tls_version = ntohs(*((u_int16_t*)&packet->payload[header_len+4]));
+ else
+ tls_version = ntohs(*((u_int16_t*)&packet->payload[header_len+12]));
+
+ session_id_len = packet->payload[base_offset];
+
+ ja3.tls_version = tls_version;
+
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_len, cipher_offset;
-#ifdef CERTIFICATE_DEBUG
- printf("Client SSL [client cipher_len: %u]\n", cipher_len);
+ if(packet->tcp) {
+ cipher_len = packet->payload[session_id_len+base_offset+2] + (packet->payload[session_id_len+base_offset+1] << 8);
+ cipher_offset = base_offset + session_id_len + 3;
+ } else {
+ cipher_len = ntohs(*((u_int16_t*)&packet->payload[base_offset+2]));
+ cipher_offset = base_offset+4;
+ }
+
+#ifdef DEBUG_TLS
+ printf("Client SSL [client cipher_len: %u][tls_version: 0x%04X]\n", cipher_len, tls_version);
#endif
if((cipher_offset+cipher_len) <= total_len) {
for(i=0; i<cipher_len;) {
u_int16_t *id = (u_int16_t*)&packet->payload[cipher_offset+i];
-#ifdef CERTIFICATE_DEBUG
- printf("Client SSL [cipher suite: %u] [%u/%u]\n", ntohs(*id), i, cipher_len);
+#ifdef DEBUG_TLS
+ printf("Client SSL [cipher suite: %u/0x%04X] [%u/%u]\n", ntohs(*id), ntohs(*id), i, cipher_len);
#endif
if((*id == 0) || (packet->payload[cipher_offset+i] != packet->payload[cipher_offset+i+1])) {
/*
@@ -587,7 +446,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
ja3.cipher[ja3.num_cipher++] = ntohs(*id);
else {
invalid_ja3 = 1;
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("Client SSL Invalid cipher %u\n", ja3.num_cipher);
#endif
}
@@ -597,7 +456,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
}
} else {
invalid_ja3 = 1;
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("Client SSL Invalid len %u vs %u\n", (cipher_offset+cipher_len), total_len);
#endif
}
@@ -610,11 +469,11 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
u_int16_t compression_len;
u_int16_t extensions_len;
- offset++;
+ offset += packet->tcp ? 1 : 2;
compression_len = packet->payload[offset];
offset++;
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("Client SSL [compression_len: %u]\n", compression_len);
#endif
@@ -625,7 +484,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
extensions_len = ntohs(*((u_int16_t*)&packet->payload[offset]));
offset += 2;
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("Client SSL [extensions_len: %u]\n", extensions_len);
#endif
@@ -644,19 +503,19 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
extension_len = ntohs(*((u_int16_t*)&packet->payload[offset+extension_offset]));
extension_offset += 2;
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("Client SSL [extension_id: %u][extension_len: %u]\n", extension_id, extension_len);
#endif
if((extension_id == 0) || (packet->payload[extn_off] != packet->payload[extn_off+1])) {
/* Skip GREASE */
- if(ja3.num_ssl_extension < MAX_NUM_JA3)
- ja3.ssl_extension[ja3.num_ssl_extension++] = extension_id;
+ if(ja3.num_tls_extension < MAX_NUM_JA3)
+ ja3.tls_extension[ja3.num_tls_extension++] = extension_id;
else {
invalid_ja3 = 1;
-#ifdef CERTIFICATE_DEBUG
- printf("Client SSL Invalid extensions %u\n", ja3.num_ssl_extension);
+#ifdef DEBUG_TLS
+ printf("Client SSL Invalid extensions %u\n", ja3.num_tls_extension);
#endif
}
}
@@ -676,9 +535,9 @@ 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;
-
-#ifdef CERTIFICATE_DEBUG
+ u_int16_t s_offset = offset+extension_offset + 2;
+
+#ifdef DEBUG_TLS
printf("Client SSL [EllipticCurveGroups: len=%u]\n", extension_len);
#endif
@@ -686,8 +545,8 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
for(i=0; i<extension_len-2;) {
u_int16_t s_group = ntohs(*((u_int16_t*)&packet->payload[s_offset+i]));
-#ifdef CERTIFICATE_DEBUG
- printf("Client SSL [EllipticCurve: %u]\n", s_group);
+#ifdef DEBUG_TLS
+ printf("Client SSL [EllipticCurve: %u/0x%04X]\n", s_group, s_group);
#endif
if((s_group == 0) || (packet->payload[s_offset+i] != packet->payload[s_offset+i+1])) {
/* Skip GREASE */
@@ -695,7 +554,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
ja3.elliptic_curve[ja3.num_elliptic_curve++] = s_group;
else {
invalid_ja3 = 1;
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("Client SSL Invalid num elliptic %u\n", ja3.num_elliptic_curve);
#endif
}
@@ -705,21 +564,21 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
}
} else {
invalid_ja3 = 1;
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("Client SSL Invalid len %u vs %u\n", (s_offset+extension_len-1), total_len);
#endif
}
} else if(extension_id == 11 /* ec_point_formats groups */) {
- u_int16_t i, s_offset = offset+extension_offset + 1;
-
-#ifdef CERTIFICATE_DEBUG
+ u_int16_t s_offset = offset+extension_offset + 1;
+
+#ifdef DEBUG_TLS
printf("Client SSL [EllipticCurveFormat: len=%u]\n", extension_len);
#endif
if((s_offset+extension_len) < total_len) {
for(i=0; i<extension_len-1;i++) {
u_int8_t s_group = packet->payload[s_offset+i];
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("Client SSL [EllipticCurveFormat: %u]\n", s_group);
#endif
@@ -727,14 +586,14 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
ja3.elliptic_curve_point_format[ja3.num_elliptic_curve_point_format++] = s_group;
else {
invalid_ja3 = 1;
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("Client SSL Invalid num elliptic %u\n", ja3.num_elliptic_curve_point_format);
#endif
}
}
} else {
invalid_ja3 = 1;
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("Client SSL Invalid len %u vs %u\n", s_offset+extension_len, total_len);
#endif
}
@@ -742,13 +601,13 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
extension_offset += extension_len;
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("Client SSL [extension_offset/len: %u/%u]\n", extension_offset, extension_len);
#endif
} /* while */
if(!invalid_ja3) {
- ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.ssl_version);
+ ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.tls_version);
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",
@@ -759,9 +618,9 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
/* ********** */
- for(i=0; i<ja3.num_ssl_extension; i++)
+ for(i=0; i<ja3.num_tls_extension; i++)
ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u",
- (i > 0) ? "-" : "", ja3.ssl_extension[i]);
+ (i > 0) ? "-" : "", ja3.tls_extension[i]);
ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ",");
@@ -777,19 +636,20 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u",
(i > 0) ? "-" : "", ja3.elliptic_curve_point_format[i]);
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("[JA3] Client: %s \n", ja3_str);
#endif
-
- MD5Init(&ctx);
- MD5Update(&ctx, (const unsigned char *)ja3_str, strlen(ja3_str));
- MD5Final(md5_hash, &ctx);
+
+ ndpi_MD5Init(&ctx);
+ ndpi_MD5Update(&ctx, (const unsigned char *)ja3_str, strlen(ja3_str));
+ ndpi_MD5Final(md5_hash, &ctx);
for(i=0, j=0; i<16; i++)
j += snprintf(&flow->protos.stun_ssl.ssl.ja3_client[j],
- sizeof(flow->protos.stun_ssl.ssl.ja3_client)-j, "%02x", md5_hash[i]);
+ sizeof(flow->protos.stun_ssl.ssl.ja3_client)-j, "%02x",
+ md5_hash[i]);
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("[JA3] Client: %s \n", flow->protos.stun_ssl.ssl.ja3_client);
#endif
}
@@ -807,6 +667,8 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
return(0); /* Not found */
}
+/* **************************************** */
+
void getSSLorganization(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
char *buffer, int buffer_len) {
@@ -862,7 +724,7 @@ void getSSLorganization(struct ndpi_detection_module_struct *ndpi_struct,
if(is_printable == 1) {
snprintf(flow->protos.stun_ssl.ssl.server_organization,
sizeof(flow->protos.stun_ssl.ssl.server_organization), "%s", buffer);
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
printf("Certificate organization: %s\n", flow->protos.stun_ssl.ssl.server_organization);
#endif
}
@@ -870,20 +732,24 @@ void getSSLorganization(struct ndpi_detection_module_struct *ndpi_struct,
}
}
+/* **************************************** */
-int sslTryAndRetrieveServerCertificate(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+int sslTryAndRetrieveServerCertificate(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &flow->packet;
/* 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));
+ rc = getTLScertificate(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,20 +759,25 @@ 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)
+ if(((packet->ssl_certificate_num_checks >= 3)
&& (flow->l4.tcp.seen_syn)
&& (flow->l4.tcp.seen_syn_ack)
&& (flow->l4.tcp.seen_ack) /* We have seen the 3-way handshake */)
- {
- /* We're done processing extra packets since we've probably checked all possible cert packets */
+ || (flow->protos.stun_ssl.ssl.ja3_server[0] != '\0')
+ ) {
+ /* We're done processing extra packets since we've probably checked all possible cert packets */
return 0;
}
}
+
/* 1 means keep looking for more packets */
return 1;
}
+/* **************************************** */
+
void sslInitExtraPacketProcessing(int caseNum, struct ndpi_flow_struct *flow) {
flow->check_extra_packets = 1;
/* 0 is the case for waiting for the server certificate */
@@ -917,30 +788,33 @@ void sslInitExtraPacketProcessing(int caseNum, struct ndpi_flow_struct *flow) {
}
}
-int sslDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+/* **************************************** */
+
+int tlsDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &flow->packet;
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)) {
+ || (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_TLS)) {
char certificate[64];
int rc;
certificate[0] = '\0';
- rc = getSSLcertificate(ndpi_struct, flow, certificate, sizeof(certificate));
+ rc = getTLScertificate(ndpi_struct, flow, certificate, sizeof(certificate));
packet->ssl_certificate_num_checks++;
if(rc > 0) {
packet->ssl_certificate_detected++;
-#ifdef CERTIFICATE_DEBUG
+#ifdef DEBUG_TLS
NDPI_LOG_DBG2(ndpi_struct, "***** [SSL] %s\n", certificate);
#endif
ndpi_protocol_match_result ret_match;
u_int32_t subproto = ndpi_match_host_subprotocol(ndpi_struct, flow, certificate,
strlen(certificate),
&ret_match,
- NDPI_PROTOCOL_SSL);
+ NDPI_PROTOCOL_TLS);
if(subproto != NDPI_PROTOCOL_UNKNOWN) {
/* If we've detected the subprotocol from client certificate but haven't had a chance
@@ -952,11 +826,11 @@ int sslDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_s
}
ndpi_set_detected_protocol(ndpi_struct, flow, subproto,
- ndpi_ssl_refine_master_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SSL));
+ ndpi_tls_refine_master_protocol(ndpi_struct, flow, NDPI_PROTOCOL_TLS));
return(rc); /* Fix courtesy of Gianluca Costa <g.costa@xplico.org> */
}
- if(ndpi_is_ssl_tor(ndpi_struct, flow, certificate) != 0)
+ if(ndpi_is_tls_tor(ndpi_struct, flow, certificate) != 0)
return(rc);
}
@@ -969,29 +843,30 @@ int sslDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_s
&& (flow->protos.stun_ssl.ssl.server_certificate[0] != '\0'))
/* || ((flow->l4.tcp.ssl_seen_client_cert == 1) && (flow->protos.stun_ssl.ssl.client_certificate[0] != '\0')) */
) {
- ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL);
+ ndpi_int_tls_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TLS);
}
}
}
return(0);
}
-static void ssl_mark_and_payload_search_for_other_protocols(struct ndpi_detection_module_struct
- *ndpi_struct, struct ndpi_flow_struct *flow)
-{
+/* **************************************** */
+
+static void tls_mark_and_payload_search_for_other_protocols(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &flow->packet;
u_int32_t a;
u_int32_t end;
if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_UNENCRYPTED_JABBER) != 0)
- goto check_for_ssl_payload;
+ goto check_for_tls_payload;
if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_OSCAR) != 0)
- goto check_for_ssl_payload;
+ goto check_for_tls_payload;
else
- goto no_check_for_ssl_payload;
+ goto no_check_for_tls_payload;
- check_for_ssl_payload:
+ check_for_tls_payload:
end = packet->payload_packet_len - 20;
for (a = 5; a < end; a++) {
@@ -1000,7 +875,7 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct ndpi_detectio
if(NDPI_COMPARE_PROTOCOL_TO_BITMASK
(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_UNENCRYPTED_JABBER) != 0) {
NDPI_LOG_INFO(ndpi_struct, "found ssl jabber unencrypted\n");
- ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_UNENCRYPTED_JABBER);
+ ndpi_int_tls_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_UNENCRYPTED_JABBER);
return;
}
}
@@ -1027,7 +902,7 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct ndpi_detectio
flow->dst->oscar_last_safe_access_time = packet->tick_timestamp;
}
- ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_OSCAR);
+ ndpi_int_tls_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_OSCAR);
return;
}
}
@@ -1037,31 +912,32 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct ndpi_detectio
(memcmp(&packet->payload[a], "my.screenname.aol.com", 21) == 0
|| memcmp(&packet->payload[a], "sns-static.aolcdn.com", 21) == 0)) {
NDPI_LOG_DBG(ndpi_struct, "found OSCAR SERVER SSL DETECTED\n");
- ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_OSCAR);
+ ndpi_int_tls_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_OSCAR);
return;
}
}
}
- no_check_for_ssl_payload:
+ no_check_for_tls_payload:
if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
NDPI_LOG_DBG(ndpi_struct, "found ssl connection\n");
- sslDetectProtocolFromCertificate(ndpi_struct, flow);
+ tlsDetectProtocolFromCertificate(ndpi_struct, flow);
if(!packet->ssl_certificate_detected
&& (!(flow->l4.tcp.ssl_seen_client_cert && flow->l4.tcp.ssl_seen_server_cert))) {
/* SSL without certificate (Skype, Ultrasurf?) */
NDPI_LOG_INFO(ndpi_struct, "found ssl NO_CERT\n");
- ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL_NO_CERT);
+ ndpi_int_tls_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TLS_NO_CERT);
} else if(packet->ssl_certificate_num_checks >= 3) {
NDPI_LOG_INFO(ndpi_struct, "found ssl\n");
- ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL);
+ ndpi_int_tls_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TLS);
}
}
}
+/* **************************************** */
-static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct *ndpi_struct,
+static u_int8_t ndpi_search_tlsv3_direction1(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &flow->packet;
@@ -1126,7 +1002,7 @@ 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)
&& 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_TLS_REQUEST_SIZE) {
return 1;
}
temp += temp2;
@@ -1137,7 +1013,7 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct
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_TLS_REQUEST_SIZE) {
return 1;
}
temp += temp2;
@@ -1148,7 +1024,7 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct
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_TLS_REQUEST_SIZE) {
return 1;
}
temp += temp2;
@@ -1164,20 +1040,51 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct
return 0;
}
-void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
-{
+/* **************************************** */
+
+void ndpi_search_tls_tcp_udp(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &flow->packet;
u_int8_t ret;
- if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) {
+ if(packet->udp != NULL) {
+ /* DTLS dissector */
+#ifdef DEBUG_TLS
+ int rc = /* sslTryAndRetrieveServerCertificate(...) */
+#endif
+ sslTryAndRetrieveServerCertificate(ndpi_struct, flow);
+
+#ifdef DEBUG_TLS
+ printf("==>> %u [rc: %u][len: %u][%s][version: %u]\n",
+ flow->guessed_host_protocol_id, rc, packet->payload_packet_len, flow->protos.stun_ssl.ssl.ja3_server,
+ flow->protos.stun_ssl.ssl.ssl_version);
+#endif
+
+ if(flow->protos.stun_ssl.ssl.ssl_version != 0) {
+ flow->guessed_protocol_id = NDPI_PROTOCOL_TLS;
+
+ if(flow->protos.stun_ssl.stun.num_udp_pkts > 0) {
+ /* In Signal protocol STUN turns into DTLS... */
+ ndpi_int_tls_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SIGNAL);
+ } else if(flow->protos.stun_ssl.ssl.ja3_server[0] != '\0') {
+ /* Wait the server certificate the bless this flow as TLS */
+ ndpi_int_tls_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TLS);
+ }
+ }
+
+ return;
+ }
+
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_TLS) {
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_DBG2(ndpi_struct,
"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) {
+ tls_mark_and_payload_search_for_other_protocols(ndpi_struct, flow);
+
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_TLS) {
/* still ssl so check another packet */
return;
} else {
@@ -1185,11 +1092,12 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc
return;
}
}
+
return;
}
NDPI_LOG_DBG(ndpi_struct, "search ssl\n");
-
+
/* Check if this is whatsapp first (this proto runs over port 443) */
if((packet->payload_packet_len > 5)
&& ((packet->payload[0] == 'W')
@@ -1206,10 +1114,10 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc
return;
} else {
/* No whatsapp, let's try SSL */
- if(sslDetectProtocolFromCertificate(ndpi_struct, flow) > 0)
+ if(tlsDetectProtocolFromCertificate(ndpi_struct, flow) > 0)
return;
- }
-
+ }
+
if(packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 0) {
NDPI_LOG_DBG2(ndpi_struct, "first ssl packet\n");
// SSLv2 Record
@@ -1234,14 +1142,14 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc
if(packet->payload[0] == 0x17 && packet->payload[1] == 0x03
&& (packet->payload[2] == 0x00 || packet->payload[2] == 0x01 ||
packet->payload[2] == 0x02 || packet->payload[2] == 0x03)) {
- if(packet->payload_packet_len - ntohs(get_u_int16_t(packet->payload, 3)) == 5) {
- NDPI_LOG_DBG2(ndpi_struct, "TLS len match\n");
- flow->l4.tcp.ssl_stage = 1 + packet->packet_direction;
- return;
- }
+ if(packet->payload_packet_len - ntohs(get_u_int16_t(packet->payload, 3)) == 5) {
+ NDPI_LOG_DBG2(ndpi_struct, "TLS len match\n");
+ flow->l4.tcp.ssl_stage = 1 + packet->packet_direction;
+ return;
+ }
}
}
-
+
if(packet->payload_packet_len > 40 &&
flow->l4.tcp.ssl_stage == 1 + packet->packet_direction
&& flow->packet_direction_counter[packet->packet_direction] < 5) {
@@ -1255,20 +1163,20 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc
&& (packet->payload[4] == 0x00 || packet->payload[4] == 0x01 || packet->payload[4] == 0x02)
&& (packet->payload_packet_len - 2) >= packet->payload[1]) {
NDPI_LOG_DBG2(ndpi_struct, "sslv2 server len match\n");
- ssl_mark_and_payload_search_for_other_protocols(ndpi_struct, flow);
+ tls_mark_and_payload_search_for_other_protocols(ndpi_struct, flow);
return;
}
- ret = ndpi_search_sslv3_direction1(ndpi_struct, flow);
+ ret = ndpi_search_tlsv3_direction1(ndpi_struct, flow);
if(ret == 1) {
NDPI_LOG_DBG2(ndpi_struct, "sslv3 server len match\n");
- ssl_mark_and_payload_search_for_other_protocols(ndpi_struct, flow);
+ tls_mark_and_payload_search_for_other_protocols(ndpi_struct, flow);
return;
} else if(ret == 2) {
NDPI_LOG_DBG2(ndpi_struct,
"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) {
+ tls_mark_and_payload_search_for_other_protocols(ndpi_struct, flow);
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_TLS) {
flow->l4.tcp.ssl_stage = 3;
}
return;
@@ -1281,16 +1189,18 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc
}
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
+
return;
}
+/* **************************************** */
-void init_ssl_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask)
-{
- ndpi_set_bitmask_protocol_detection("SSL", ndpi_struct, detection_bitmask, *id,
- NDPI_PROTOCOL_SSL,
- ndpi_search_ssl_tcp,
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+void init_tls_dissector(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask) {
+ ndpi_set_bitmask_protocol_detection("TLS", ndpi_struct, detection_bitmask, *id,
+ NDPI_PROTOCOL_TLS,
+ ndpi_search_tls_tcp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,
SAVE_DETECTION_BITMASK_AS_UNKNOWN,
ADD_TO_DETECTION_BITMASK);
diff --git a/src/lib/protocols/tor.c b/src/lib/protocols/tor.c
index f1c6f586a..3b2dd06c4 100644
--- a/src/lib/protocols/tor.c
+++ b/src/lib/protocols/tor.c
@@ -18,12 +18,12 @@ static void ndpi_int_tor_add_connection(struct ndpi_detection_module_struct
}
-int ndpi_is_ssl_tor(struct ndpi_detection_module_struct *ndpi_struct,
+int ndpi_is_tls_tor(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow, char *certificate) {
int prev_num = 0, numbers_found = 0, num_found = 0, i, len, num_impossible = 0;
char dummy[48], *dot, *name;
-
- if(certificate == NULL)
+
+ if((certificate == NULL) || (certificate[0] == '\0'))
return(0);
else
len = strlen(certificate);
@@ -96,11 +96,13 @@ 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) {
+ if((packet->tcp != NULL)
+ && (!packet->ssl_certificate_detected)) {
+ 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");
diff --git a/src/lib/protocols/yahoo.c b/src/lib/protocols/yahoo.c
index 3be953939..972466dc8 100644
--- a/src/lib/protocols/yahoo.c
+++ b/src/lib/protocols/yahoo.c
@@ -367,7 +367,7 @@ void ndpi_search_yahoo(struct ndpi_detection_module_struct *ndpi_struct, struct
if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN
|| packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP
- || packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) {
+ || packet->detected_protocol_stack[0] == NDPI_PROTOCOL_TLS) {
/* search over TCP */
ndpi_search_yahoo_tcp(ndpi_struct, flow);
}
diff --git a/src/lib/third_party/include/ndpi_md5.h b/src/lib/third_party/include/ndpi_md5.h
new file mode 100644
index 000000000..f7dd9b946
--- /dev/null
+++ b/src/lib/third_party/include/ndpi_md5.h
@@ -0,0 +1,18 @@
+/*
+ Contributed code pasted here to make nDPI self-contained with no
+ external dependencies
+*/
+
+/* **************************************** */
+
+typedef struct ndpi_MD5Context {
+ uint32_t buf[4];
+ uint32_t bits[2];
+ unsigned char in[64];
+} ndpi_MD5_CTX;
+
+/* **************************************** */
+
+extern void ndpi_MD5Init(ndpi_MD5_CTX *ctx);
+extern void ndpi_MD5Update(ndpi_MD5_CTX *ctx, unsigned char const *buf, unsigned len);
+extern void ndpi_MD5Final(unsigned char digest[16], ndpi_MD5_CTX *ctx);
diff --git a/src/lib/third_party/src/ndpi_md5.c b/src/lib/third_party/src/ndpi_md5.c
new file mode 100644
index 000000000..fefe9d65f
--- /dev/null
+++ b/src/lib/third_party/src/ndpi_md5.c
@@ -0,0 +1,204 @@
+/*
+ Contributed code pasted here to make nDPI self-contained with no
+ external dependencies
+*/
+
+#include "ndpi_api.h"
+#include "ndpi_md5.h"
+
+/* **************************************** */
+
+static int is_big_endian(void) {
+ static const int n = 1;
+ return ((char *) &n)[0] == 0;
+}
+
+static void byte_reverse(unsigned char *buf, unsigned longs) {
+ // Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN
+ if (is_big_endian()) {
+ do {
+ u_int32_t t;
+
+ t = (u_int32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+ ((unsigned) buf[1] << 8 | buf[0]);
+ * (u_int32_t *) buf = t;
+ buf += 4;
+ } while (--longs);
+ }
+}
+
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+
+/* **************************************** */
+
+// Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+// initialization constants.
+void ndpi_MD5Init(ndpi_MD5_CTX *ctx) {
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+/* **************************************** */
+
+static void MD5Transform(u_int32_t buf[4], u_int32_t const in[16]) {
+ u_int32_t a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/* **************************************** */
+
+void ndpi_MD5Update(ndpi_MD5_CTX *ctx, unsigned char const *buf, unsigned len) {
+ u_int32_t t;
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = t + ((u_int32_t) len << 3)) < t)
+ ctx->bits[1]++;
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f;
+
+ if (t) {
+ unsigned char *p = (unsigned char *) ctx->in + t;
+
+ t = 64 - t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ byte_reverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (u_int32_t *) ctx->in);
+ buf += t;
+ len -= t;
+ }
+
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ byte_reverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (u_int32_t *) ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ memcpy(ctx->in, buf, len);
+}
+
+/* **************************************** */
+
+void ndpi_MD5Final(unsigned char digest[16], ndpi_MD5_CTX *ctx) {
+ unsigned count;
+ unsigned char *p;
+ u_int32_t *c = (u_int32_t*)ctx->in;
+
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ p = ctx->in + count;
+ *p++ = 0x80;
+ count = 64 - 1 - count;
+ if (count < 8) {
+ memset(p, 0, count);
+ byte_reverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (u_int32_t *) ctx->in);
+ memset(ctx->in, 0, 56);
+ } else {
+ memset(p, 0, count - 8);
+ }
+ byte_reverse(ctx->in, 14);
+
+ c[14] = ctx->bits[0];
+ c[15] = ctx->bits[1];
+
+ MD5Transform(ctx->buf, (u_int32_t *) ctx->in);
+ byte_reverse((unsigned char *) ctx->buf, 4);
+ memcpy(digest, ctx->buf, 16);
+ memset((char *) ctx, 0, sizeof(*ctx));
+}
+