aboutsummaryrefslogtreecommitdiff
path: root/src/lib/protocols
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/protocols')
-rw-r--r--src/lib/protocols/bittorrent.c24
-rw-r--r--src/lib/protocols/http.c225
-rw-r--r--src/lib/protocols/kerberos.c46
-rw-r--r--src/lib/protocols/spotify.c2
-rw-r--r--src/lib/protocols/stun.c2
-rw-r--r--src/lib/protocols/tls.c185
6 files changed, 330 insertions, 154 deletions
diff --git a/src/lib/protocols/bittorrent.c b/src/lib/protocols/bittorrent.c
index f1c62d431..9f7620558 100644
--- a/src/lib/protocols/bittorrent.c
+++ b/src/lib/protocols/bittorrent.c
@@ -43,7 +43,7 @@ struct ndpi_utp_hdr {
u_int16_t sequence_nr, ack_nr;
};
-static u_int8_t is_utp_pkt(const u_int8_t *payload, u_int payload_len) {
+static u_int8_t is_utpv1_pkt(const u_int8_t *payload, u_int payload_len) {
struct ndpi_utp_hdr *h = (struct ndpi_utp_hdr*)payload;
if(payload_len < sizeof(struct ndpi_utp_hdr)) return(0);
@@ -52,6 +52,9 @@ static u_int8_t is_utp_pkt(const u_int8_t *payload, u_int payload_len) {
if(h->next_extension > 2) return(0);
if(ntohl(h->window_size) > 65565) return(0);
+ if((h->window_size == 0) && (payload_len != sizeof(struct ndpi_utp_hdr)))
+ return(0);
+
return(1);
}
@@ -433,14 +436,10 @@ void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, st
u_int8_t v0_extension = packet->payload[17];
u_int8_t v0_flags = packet->payload[18];
- /* Check if this is protocol v1 */
- u_int8_t v1_version = packet->payload[0];
- u_int8_t v1_extension = packet->payload[1];
- u_int32_t v1_window_size = *((u_int32_t*)&packet->payload[12]);
-
- if(is_utp_pkt(packet->payload, packet->payload_packet_len))
+ if(is_utpv1_pkt(packet->payload, packet->payload_packet_len)) {
+ bt_proto = ndpi_strnstr((const char *)&packet->payload[20], "BitTorrent protocol", packet->payload_packet_len-20);
goto bittorrent_found;
- else if((packet->payload[0]== 0x60)
+ } else if((packet->payload[0]== 0x60)
&& (packet->payload[1]== 0x0)
&& (packet->payload[2]== 0x0)
&& (packet->payload[3]== 0x0)
@@ -448,14 +447,7 @@ void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, st
/* Heuristic */
bt_proto = ndpi_strnstr((const char *)&packet->payload[20], "BitTorrent protocol", packet->payload_packet_len-20);
goto bittorrent_found;
- /* CSGO/DOTA conflict */
- } else if(flow->packet_counter > 8 && ((v1_version & 0x0f) == 1)
- && ((v1_version >> 4) < 5 /* ST_NUM_STATES */)
- && (v1_extension < 3 /* EXT_NUM_EXT */)
- && (v1_window_size < 32768 /* 32k */)
- ) {
- bt_proto = ndpi_strnstr((const char *)&packet->payload[20], "BitTorrent protocol", packet->payload_packet_len-20);
- goto bittorrent_found;
+ /* CSGO/DOTA conflict */
} else if((v0_flags < 6 /* ST_NUM_STATES */) && (v0_extension < 3 /* EXT_NUM_EXT */)) {
u_int32_t ts = ntohl(*((u_int32_t*)&(packet->payload[4])));
u_int32_t now;
diff --git a/src/lib/protocols/http.c b/src/lib/protocols/http.c
index abd422007..7b83b91e7 100644
--- a/src/lib/protocols/http.c
+++ b/src/lib/protocols/http.c
@@ -28,20 +28,16 @@
#include "ndpi_api.h"
#include <stdlib.h>
-static const char* binary_file_mimes[] = {
- "exe",
- "vnd.ms-cab-compressed",
- "vnd.microsoft.portable-executable"
- "x-msdownload",
- "x-dosexec",
- NULL
-};
+static const char* binary_file_mimes_e[] = { "exe", NULL };
+static const char* binary_file_mimes_v[] = { "vnd.ms-cab-compressed", "vnd.microsoft.portable-executable", NULL };
+static const char* binary_file_mimes_x[] = { "x-msdownload", "x-dosexec", NULL };
+#define ATTACHMENT_LEN 3
static const char* binary_file_ext[] = {
- ".exe",
- ".msi",
- ".cab",
- NULL
+ "exe",
+ "msi",
+ "cab",
+ NULL
};
static void ndpi_search_http_tcp(struct ndpi_detection_module_struct *ndpi_struct,
@@ -49,7 +45,7 @@ static void ndpi_search_http_tcp(struct ndpi_detection_module_struct *ndpi_struc
/* *********************************************** */
-static void ndpi_analyze_content_signature(struct ndpi_flow_struct *flow) {
+static void ndpi_analyze_content_signature(struct ndpi_flow_struct *flow) {
if((flow->initial_binary_bytes_len >= 2) && (flow->initial_binary_bytes[0] == 0x4D) && (flow->initial_binary_bytes[1] == 0x5A))
NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER); /* Win executable */
else if((flow->initial_binary_bytes_len >= 4) && (flow->initial_binary_bytes[0] == 0x7F) && (flow->initial_binary_bytes[1] == 'E')
@@ -65,7 +61,7 @@ static void ndpi_analyze_content_signature(struct ndpi_flow_struct *flow) {
NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER); /* Unix script (e.g. #!/bin/sh) */
else if(flow->initial_binary_bytes_len >= 8) {
u_int8_t exec_pattern[] = { 0x64, 0x65, 0x78, 0x0A, 0x30, 0x33, 0x35, 0x00 };
-
+
if(memcmp(flow->initial_binary_bytes, exec_pattern, 8) == 0)
NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER); /* Dalvik Executable (Android) */
}
@@ -85,7 +81,7 @@ static int ndpi_search_http_tcp_again(struct ndpi_detection_module_struct *ndpi_
&& (flow->http.response_status_code != 0)
) {
/* stop extra processing */
-
+
if(flow->initial_binary_bytes_len) ndpi_analyze_content_signature(flow);
flow->extra_packets_func = NULL; /* We're good now */
return(0);
@@ -106,47 +102,69 @@ static ndpi_protocol_category_t ndpi_http_check_content(struct ndpi_detection_mo
u_int app_len = sizeof("application");
if(packet->content_line.len > app_len) {
- const char *app = (const char *)&packet->content_line.ptr[app_len];
- u_int app_len_avail = packet->content_line.len-app_len;
-
- if(ndpi_strncasestr(app, "mpeg", app_len_avail) != NULL) {
+ const char *app = (const char *)&packet->content_line.ptr[app_len];
+ u_int app_len_avail = packet->content_line.len-app_len;
+
+ if(strncasecmp(app, "mpeg", app_len_avail) == 0) {
flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_STREAMING;
return(flow->category);
- } else {
- for (int i = 0; binary_file_mimes[i] != NULL; i++) {
- if (ndpi_strncasestr(app, binary_file_mimes[i], app_len_avail) != NULL) {
- flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT;
- NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER);
- NDPI_LOG_INFO(ndpi_struct, "found executable HTTP transfer");
- return(flow->category);
- }
- }
+ } else if(app_len_avail > 3) {
+ const char** cmp_mimes = NULL;
+
+ switch(app[0]) {
+ case 'e': cmp_mimes = binary_file_mimes_e; break;
+ case 'v': cmp_mimes = binary_file_mimes_v; break;
+ case 'x': cmp_mimes = binary_file_mimes_x; break;
+ }
+
+ if(cmp_mimes != NULL) {
+ u_int8_t i;
+
+ for(i = 0; cmp_mimes[i] != NULL; i++) {
+ if(strncasecmp(app, cmp_mimes[i], app_len_avail) == 0) {
+ flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT;
+ NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER);
+ NDPI_LOG_INFO(ndpi_struct, "found executable HTTP transfer");
+ return(flow->category);
+ }
+ }
+ }
}
}
/* check for attachment */
- if (packet->content_disposition_line.len > 0) {
- uint8_t attachment_len = sizeof("attachment; filename");
- if (packet->content_disposition_line.len > attachment_len) {
- uint8_t filename_len = packet->content_disposition_line.len - attachment_len;
- for (int i = 0; binary_file_ext[i] != NULL; i++) {
- if (ndpi_strncasestr((const char*)&packet->content_disposition_line.ptr[attachment_len],
- binary_file_ext[i], filename_len)) {
- flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT;
- NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER);
- NDPI_LOG_INFO(ndpi_struct, "found executable HTTP transfer");
- return(flow->category);
- }
+ if (packet->content_disposition_line.len > 0) {
+ u_int8_t attachment_len = sizeof("attachment; filename");
+
+ if(packet->content_disposition_line.len > attachment_len) {
+ u_int8_t filename_len = packet->content_disposition_line.len - attachment_len;
+
+ if(filename_len > ATTACHMENT_LEN) {
+ attachment_len += filename_len-ATTACHMENT_LEN-1;
+
+ if((attachment_len+ATTACHMENT_LEN) <= packet->content_disposition_line.len) {
+ for(int i = 0; binary_file_ext[i] != NULL; i++) {
+ /* Use memcmp in case content-disposition contains binary data */
+ if(memcmp((const char*)&packet->content_disposition_line.ptr[attachment_len],
+ binary_file_ext[i], ATTACHMENT_LEN) == 0) {
+ flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT;
+ NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER);
+ NDPI_LOG_INFO(ndpi_struct, "found executable HTTP transfer");
+ return(flow->category);
+ }
+ }
+ }
+ }
}
}
- }
+
switch(packet->content_line.ptr[0]) {
case 'a':
if(strncasecmp((const char *)packet->content_line.ptr, "audio",
ndpi_min(packet->content_line.len, 5)) == 0)
flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_MEDIA;
break;
-
+
case 'v':
if(strncasecmp((const char *)packet->content_line.ptr, "video",
ndpi_min(packet->content_line.len, 5)) == 0)
@@ -178,7 +196,6 @@ static void ndpi_int_http_add_connection(struct ndpi_detection_module_struct *nd
if((flow->guessed_host_protocol_id == NDPI_PROTOCOL_UNKNOWN) || (http_protocol != NDPI_PROTOCOL_HTTP))
flow->guessed_host_protocol_id = http_protocol;
- category = ndpi_http_check_content(ndpi_struct, flow);
ndpi_int_reset_protocol(flow);
ndpi_set_detected_protocol(ndpi_struct, flow, flow->guessed_host_protocol_id, NDPI_PROTOCOL_HTTP);
@@ -186,7 +203,7 @@ static void ndpi_int_http_add_connection(struct ndpi_detection_module_struct *nd
flow->check_extra_packets = 1;
flow->max_extra_packets_to_check = 5;
flow->extra_packets_func = ndpi_search_http_tcp_again;
- flow->http_detected = 1, flow->guessed_category = flow->category = category;
+ flow->http_detected = 1;
}
/* ************************************************************* */
@@ -220,7 +237,7 @@ static void setHttpUserAgent(struct ndpi_detection_module_struct *ndpi_struct,
* https://github.com/ua-parser/uap-core/blob/master/regexes.yaml */
snprintf((char*)flow->protos.http.detected_os,
- sizeof(flow->protos.http.detected_os), "%s", ua);
+ sizeof(flow->protos.http.detected_os), "%s", ua);
}
/* ************************************************************* */
@@ -232,7 +249,7 @@ static void ndpi_http_parse_subprotocol(struct ndpi_detection_module_struct *ndp
if(double_col) double_col[0] = '\0';
- ndpi_match_hostname_protocol(ndpi_struct, flow, NDPI_PROTOCOL_HTTP,
+ ndpi_match_hostname_protocol(ndpi_struct, flow, NDPI_PROTOCOL_HTTP,
(char *)flow->host_server_name,
strlen((const char *)flow->host_server_name));
}
@@ -246,7 +263,7 @@ static void ndpi_check_user_agent(struct ndpi_detection_module_struct *ndpi_stru
if((!ua) || (ua[0] == '\0')) return;
// printf("[%s:%d] ==> '%s'\n", __FILE__, __LINE__, ua);
-
+
if((strlen(ua) < 4)
|| (!strcmp(ua, "test"))
|| (!strcmp(ua, "<?"))
@@ -262,13 +279,13 @@ static void ndpi_check_numeric_ip(struct ndpi_detection_module_struct *ndpi_stru
char *ip, u_int ip_len) {
char buf[22];
struct in_addr ip_addr;
-
+
strncpy(buf, ip, ip_len);
buf[ip_len] = '\0';
ip_addr.s_addr = inet_addr(buf);
if(strcmp(inet_ntoa(ip_addr), buf) == 0) {
- NDPI_SET_BIT(flow->risk, NDPI_HTTP_NUMERIC_IP_HOST);
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_NUMERIC_IP_HOST);
}
}
@@ -301,9 +318,9 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
int len = packet->http_url_name.len + packet->host_line.len + 1;
if(isdigit(packet->host_line.ptr[0])
- && (packet->host_line.len < 21))
+ && (packet->host_line.len < 21))
ndpi_check_numeric_ip(ndpi_struct, flow, (char*)packet->host_line.ptr, packet->host_line.len);
-
+
flow->http.url = ndpi_malloc(len);
if(flow->http.url) {
strncpy(flow->http.url, (char*)packet->host_line.ptr, packet->host_line.len);
@@ -352,7 +369,7 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
strncpy(ua, (const char *)packet->user_agent_line.ptr, mlen);
ua[mlen] = '\0';
-
+
if(strncmp(ua, "Mozilla", 7) == 0) {
char *parent = strchr(ua, '(');
@@ -517,7 +534,8 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
strncpy(flow->http.content_type, (char*)packet->content_line.ptr,
packet->content_line.len);
flow->http.content_type[packet->content_line.len] = '\0';
- }
+
+ flow->guessed_category = flow->category = ndpi_http_check_content(ndpi_struct, flow);}
}
if(flow->http_detected) {
@@ -595,6 +613,106 @@ static void http_bitmask_exclude_other(struct ndpi_flow_struct *flow)
NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_XBOX);
}
+/* *********************************************************************************************** */
+
+/* Trick to speed-up detection */
+static const char* suspicious_http_header_keys_A[] = { "Arch", NULL};
+static const char* suspicious_http_header_keys_C[] = { "Cores", NULL};
+static const char* suspicious_http_header_keys_M[] = { "Mem", NULL};
+static const char* suspicious_http_header_keys_O[] = { "Os", "Osname", "Osversion", NULL};
+static const char* suspicious_http_header_keys_R[] = { "Root", NULL};
+static const char* suspicious_http_header_keys_S[] = { "S", NULL};
+static const char* suspicious_http_header_keys_T[] = { "TLS_version", NULL};
+static const char* suspicious_http_header_keys_U[] = { "Uuid", NULL};
+static const char* suspicious_http_header_keys_X[] = { "X-Hire-Me", NULL};
+
+static int is_a_suspicious_header(const char* suspicious_headers[], struct ndpi_int_one_line_struct packet_line){
+ int i;
+ unsigned int header_len;
+ const u_int8_t* header_limit;
+
+ if((header_limit = memchr(packet_line.ptr, ':', packet_line.len))) {
+ header_len = header_limit - packet_line.ptr;
+ for(i=0; suspicious_headers[i] != NULL; i++){
+ if(!strncasecmp((const char*) packet_line.ptr,
+ suspicious_headers[i], header_len))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* *********************************************************************************************** */
+
+static void ndpi_check_http_header(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
+ u_int32_t i;
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ for(i=0; (i < packet->parsed_lines)
+ && (packet->line[i].ptr != NULL)
+ && (packet->line[i].len > 0); i++) {
+ switch(packet->line[i].ptr[0]){
+ case 'A':
+ if(is_a_suspicious_header(suspicious_http_header_keys_A, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'C':
+ if(is_a_suspicious_header(suspicious_http_header_keys_C, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'M':
+ if(is_a_suspicious_header(suspicious_http_header_keys_M, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'O':
+ if(is_a_suspicious_header(suspicious_http_header_keys_O, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'R':
+ if(is_a_suspicious_header(suspicious_http_header_keys_R, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'S':
+ if(is_a_suspicious_header(suspicious_http_header_keys_S, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'T':
+ if(is_a_suspicious_header(suspicious_http_header_keys_T, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'U':
+ if(is_a_suspicious_header(suspicious_http_header_keys_U, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'X':
+ if(is_a_suspicious_header(suspicious_http_header_keys_X, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+
+ break;
+ }
+ }
+}
+
/*************************************************************************************************/
static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct,
@@ -694,6 +812,7 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
"Filename HTTP found: %d, we look for line info..\n", filename_start);
ndpi_parse_packet_line_info(ndpi_struct, flow);
+ ndpi_check_http_header(ndpi_struct, flow);
if(packet->parsed_lines <= 1) {
NDPI_LOG_DBG2(ndpi_struct,
diff --git a/src/lib/protocols/kerberos.c b/src/lib/protocols/kerberos.c
index ff16545f5..f4c1a175a 100644
--- a/src/lib/protocols/kerberos.c
+++ b/src/lib/protocols/kerberos.c
@@ -202,11 +202,13 @@ void ndpi_search_kerberos(struct ndpi_detection_module_struct *ndpi_struct,
if(body_offset < packet->payload_packet_len) {
- u_int16_t name_offset;
-
- name_offset = body_offset + 13;
- for(i=0; i<20; i++) if(packet->payload[name_offset] != 0x1b) name_offset++; /* ASN.1 */
-
+ u_int16_t name_offset = body_offset + 13;
+
+ for(i=0; (i<20) && (name_offset < packet->payload_packet_len); i++) {
+ if(packet->payload[name_offset] != 0x1b)
+ name_offset++; /* ASN.1 */
+ }
+
#ifdef KERBEROS_DEBUG
printf("name_offset=%u [%02X %02X] [byte 0 must be 0x1b]\n", name_offset, packet->payload[name_offset], packet->payload[name_offset+1]);
#endif
@@ -256,30 +258,38 @@ void ndpi_search_kerberos(struct ndpi_detection_module_struct *ndpi_struct,
} else
snprintf(flow->protos.kerberos.username, sizeof(flow->protos.kerberos.username), "%s", cname_str);
- for(i=0; i<14; i++) if(packet->payload[realm_offset] != 0x1b) realm_offset++; /* ASN.1 */
+ for(i=0; (i < 14) && (realm_offset < packet->payload_packet_len); i++) {
+ if(packet->payload[realm_offset] != 0x1b)
+ realm_offset++; /* ASN.1 */
+ }
+
#ifdef KERBEROS_DEBUG
- printf("realm_offset=%u [%02X %02X] [byte 0 must be 0x1b]\n", realm_offset, packet->payload[realm_offset], packet->payload[realm_offset+1]);
+ printf("realm_offset=%u [%02X %02X] [byte 0 must be 0x1b]\n", realm_offset,
+ packet->payload[realm_offset], packet->payload[realm_offset+1]);
#endif
+
realm_offset += 1;
//if(num_cname == 2) realm_offset++;
- realm_len = packet->payload[realm_offset];
+ if(realm_offset < packet->payload_packet_len) {
+ realm_len = packet->payload[realm_offset];
- if((realm_offset+realm_len) < packet->payload_packet_len) {
- char realm_str[48];
+ if((realm_offset+realm_len) < packet->payload_packet_len) {
+ char realm_str[48];
- if(realm_len > sizeof(realm_str)-1)
- realm_len = sizeof(realm_str)-1;
+ if(realm_len > sizeof(realm_str)-1)
+ realm_len = sizeof(realm_str)-1;
- realm_offset += 1;
+ realm_offset += 1;
- strncpy(realm_str, (char*)&packet->payload[realm_offset], realm_len);
- realm_str[realm_len] = '\0';
- for(i=0; i<realm_len; i++) realm_str[i] = tolower(realm_str[i]);
+ strncpy(realm_str, (char*)&packet->payload[realm_offset], realm_len);
+ realm_str[realm_len] = '\0';
+ for(i=0; i<realm_len; i++) realm_str[i] = tolower(realm_str[i]);
#ifdef KERBEROS_DEBUG
- printf("[AS-REQ][Kerberos Realm][len: %u][%s]\n", realm_len, realm_str);
+ printf("[AS-REQ][Kerberos Realm][len: %u][%s]\n", realm_len, realm_str);
#endif
- snprintf(flow->protos.kerberos.domain, sizeof(flow->protos.kerberos.domain), "%s", realm_str);
+ snprintf(flow->protos.kerberos.domain, sizeof(flow->protos.kerberos.domain), "%s", realm_str);
+ }
}
}
}
diff --git a/src/lib/protocols/spotify.c b/src/lib/protocols/spotify.c
index a180a1ea7..d66109016 100644
--- a/src/lib/protocols/spotify.c
+++ b/src/lib/protocols/spotify.c
@@ -47,7 +47,7 @@ static void ndpi_check_spotify(struct ndpi_detection_module_struct *ndpi_struct,
if((packet->udp->source == spotify_port)
&& (packet->udp->dest == spotify_port)) {
- if(payload_len > 2) {
+ if(payload_len >= 7) {
if(memcmp(packet->payload, "SpotUdp", 7) == 0) {
NDPI_LOG_INFO(ndpi_struct, "found spotify udp dissector\n");
ndpi_int_spotify_add_connection(ndpi_struct, flow, 0);
diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c
index fd783d099..87d090daf 100644
--- a/src/lib/protocols/stun.c
+++ b/src/lib/protocols/stun.c
@@ -161,7 +161,7 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
/* This looks like an invalid packet */
if(flow->protos.stun_ssl.stun.num_udp_pkts > 0) {
- flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
+ // flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
return(NDPI_IS_STUN);
} else
return(NDPI_IS_NOT_STUN);
diff --git a/src/lib/protocols/tls.c b/src/lib/protocols/tls.c
index 62b2e3cf8..222fa480d 100644
--- a/src/lib/protocols/tls.c
+++ b/src/lib/protocols/tls.c
@@ -34,13 +34,13 @@ extern char *strptime(const char *s, const char *format, struct tm *tm);
extern int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow);
-// #define DEBUG_TLS_MEMORY 1
-// #define DEBUG_TLS 1
-
+// #define DEBUG_TLS_MEMORY 1
+// #define DEBUG_TLS 1
// #define DEBUG_CERTIFICATE_HASH
-/* #define DEBUG_FINGERPRINT 1 */
+/* #define DEBUG_FINGERPRINT 1 */
+/* #define DEBUG_ENCRYPTED_SNI 1 */
/*
NOTE
@@ -390,77 +390,83 @@ static void processCertificateElements(struct ndpi_detection_module_struct *ndpi
i += 3 /* skip the initial patten 55 1D 11 */;
i++; /* skip the first type, 0x04 == BIT STRING, and jump to it's length */
- i += (packet->payload[i] & 0x80) ? (packet->payload[i] & 0x7F) : 0; /* skip BIT STRING length */
- i += 2; /* skip the second type, 0x30 == SEQUENCE, and jump to it's length */
- i += (packet->payload[i] & 0x80) ? (packet->payload[i] & 0x7F) : 0; /* skip SEQUENCE length */
- i++;
-
- while(i < packet->payload_packet_len) {
- if(packet->payload[i] == 0x82) {
- if((i < (packet->payload_packet_len - 1))
- && ((i + packet->payload[i + 1] + 2) < packet->payload_packet_len)) {
- u_int8_t len = packet->payload[i + 1];
- char dNSName[256];
-
- i += 2;
-
- /* The check "len > sizeof(dNSName) - 1" will be always false. If we add it,
- the compiler is smart enough to detect it and throws a warning */
- if(len == 0 /* Looks something went wrong */)
- break;
+ if(i < packet->payload_packet_len) {
+ i += (packet->payload[i] & 0x80) ? (packet->payload[i] & 0x7F) : 0; /* skip BIT STRING length */
+ if(i < packet->payload_packet_len) {
+ i += 2; /* skip the second type, 0x30 == SEQUENCE, and jump to it's length */
+ if(i < packet->payload_packet_len) {
+ i += (packet->payload[i] & 0x80) ? (packet->payload[i] & 0x7F) : 0; /* skip SEQUENCE length */
+ i++;
+
+ while(i < packet->payload_packet_len) {
+ if(packet->payload[i] == 0x82) {
+ if((i < (packet->payload_packet_len - 1))
+ && ((i + packet->payload[i + 1] + 2) < packet->payload_packet_len)) {
+ u_int8_t len = packet->payload[i + 1];
+ char dNSName[256];
+
+ i += 2;
+
+ /* The check "len > sizeof(dNSName) - 1" will be always false. If we add it,
+ the compiler is smart enough to detect it and throws a warning */
+ if(len == 0 /* Looks something went wrong */)
+ break;
- strncpy(dNSName, (const char*)&packet->payload[i], len);
- dNSName[len] = '\0';
+ strncpy(dNSName, (const char*)&packet->payload[i], len);
+ dNSName[len] = '\0';
- cleanupServerName(dNSName, len);
+ cleanupServerName(dNSName, len);
#if DEBUG_TLS
- printf("[TLS] dNSName %s [%s]\n", dNSName, flow->protos.stun_ssl.ssl.client_requested_server_name);
+ printf("[TLS] dNSName %s [%s]\n", dNSName, flow->protos.stun_ssl.ssl.client_requested_server_name);
#endif
- if(matched_name == 0) {
- if((dNSName[0] == '*') && strstr(flow->protos.stun_ssl.ssl.client_requested_server_name, &dNSName[1]))
- matched_name = 1;
- else if(strcmp(flow->protos.stun_ssl.ssl.client_requested_server_name, dNSName) == 0)
- matched_name = 1;
- }
+ if(matched_name == 0) {
+ if((dNSName[0] == '*') && strstr(flow->protos.stun_ssl.ssl.client_requested_server_name, &dNSName[1]))
+ matched_name = 1;
+ else if(strcmp(flow->protos.stun_ssl.ssl.client_requested_server_name, dNSName) == 0)
+ matched_name = 1;
+ }
- if(flow->protos.stun_ssl.ssl.server_names == NULL)
- flow->protos.stun_ssl.ssl.server_names = ndpi_strdup(dNSName),
- flow->protos.stun_ssl.ssl.server_names_len = strlen(dNSName);
- else {
- u_int16_t dNSName_len = strlen(dNSName);
- u_int16_t newstr_len = flow->protos.stun_ssl.ssl.server_names_len + dNSName_len + 1;
- char *newstr = (char*)ndpi_realloc(flow->protos.stun_ssl.ssl.server_names,
- flow->protos.stun_ssl.ssl.server_names_len+1, newstr_len+1);
-
- if(newstr) {
- flow->protos.stun_ssl.ssl.server_names = newstr;
- flow->protos.stun_ssl.ssl.server_names[flow->protos.stun_ssl.ssl.server_names_len] = ',';
- strncpy(&flow->protos.stun_ssl.ssl.server_names[flow->protos.stun_ssl.ssl.server_names_len+1],
- dNSName, dNSName_len+1);
- flow->protos.stun_ssl.ssl.server_names[newstr_len] = '\0';
- flow->protos.stun_ssl.ssl.server_names_len = newstr_len;
- }
- }
+ if(flow->protos.stun_ssl.ssl.server_names == NULL)
+ flow->protos.stun_ssl.ssl.server_names = ndpi_strdup(dNSName),
+ flow->protos.stun_ssl.ssl.server_names_len = strlen(dNSName);
+ else {
+ u_int16_t dNSName_len = strlen(dNSName);
+ u_int16_t newstr_len = flow->protos.stun_ssl.ssl.server_names_len + dNSName_len + 1;
+ char *newstr = (char*)ndpi_realloc(flow->protos.stun_ssl.ssl.server_names,
+ flow->protos.stun_ssl.ssl.server_names_len+1, newstr_len+1);
+
+ if(newstr) {
+ flow->protos.stun_ssl.ssl.server_names = newstr;
+ flow->protos.stun_ssl.ssl.server_names[flow->protos.stun_ssl.ssl.server_names_len] = ',';
+ strncpy(&flow->protos.stun_ssl.ssl.server_names[flow->protos.stun_ssl.ssl.server_names_len+1],
+ dNSName, dNSName_len+1);
+ flow->protos.stun_ssl.ssl.server_names[newstr_len] = '\0';
+ flow->protos.stun_ssl.ssl.server_names_len = newstr_len;
+ }
+ }
- if(!flow->l4.tcp.tls.subprotocol_detected)
- if(ndpi_match_hostname_protocol(ndpi_struct, flow, NDPI_PROTOCOL_TLS, dNSName, len))
- flow->l4.tcp.tls.subprotocol_detected = 1;
+ if(!flow->l4.tcp.tls.subprotocol_detected)
+ if(ndpi_match_hostname_protocol(ndpi_struct, flow, NDPI_PROTOCOL_TLS, dNSName, len))
+ flow->l4.tcp.tls.subprotocol_detected = 1;
- i += len;
- } else {
+ i += len;
+ } else {
#if DEBUG_TLS
- printf("[TLS] Leftover %u bytes", packet->payload_packet_len - i);
+ printf("[TLS] Leftover %u bytes", packet->payload_packet_len - i);
#endif
- break;
+ break;
+ }
+ } else {
+ break;
+ }
+ } /* while */
+
+ if(!matched_name)
+ NDPI_SET_BIT(flow->risk, NDPI_TLS_CERTIFICATE_MISMATCH); /* Certificate mismatch */
}
- } else {
- break;
}
- } /* while */
-
- if(!matched_name)
- NDPI_SET_BIT(flow->risk, NDPI_TLS_CERTIFICATE_MISMATCH); /* Certificate mismatch */
+ }
}
}
@@ -1252,10 +1258,59 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct,
if(flow->protos.stun_ssl.ssl.tls_supported_versions == NULL)
flow->protos.stun_ssl.ssl.tls_supported_versions = ndpi_strdup(version_str);
}
-
+ } else if(extension_id == 65486 /* encrypted server name */) {
+ /*
+ - https://tools.ietf.org/html/draft-ietf-tls-esni-06
+ - https://blog.cloudflare.com/encrypted-sni/
+ */
+ u_int16_t e_offset = offset+extension_offset;
+ u_int16_t initial_offset = e_offset;
+ u_int16_t e_sni_len, cipher_suite = ntohs(*((u_int16_t*)&packet->payload[e_offset]));
+
+ flow->protos.stun_ssl.ssl.encrypted_sni.cipher_suite = cipher_suite;
+
+ e_offset += 2; /* Cipher suite len */
+
+ /* Key Share Entry */
+ e_offset += 2; /* Group */
+ e_offset += ntohs(*((u_int16_t*)&packet->payload[e_offset])) + 2; /* Lenght */
+
+ if((e_offset+4) < packet->payload_packet_len) {
+ /* Record Digest */
+ e_offset += ntohs(*((u_int16_t*)&packet->payload[e_offset])) + 2; /* Lenght */
+
+ if((e_offset+4) < packet->payload_packet_len) {
+ e_sni_len = ntohs(*((u_int16_t*)&packet->payload[e_offset]));
+ e_offset += 2;
+
+ if((e_offset+e_sni_len-extension_len-initial_offset) >= 0) {
+#ifdef DEBUG_ENCRYPTED_SNI
+ printf("Client SSL [Encrypted Server Name len: %u]\n", e_sni_len);
+#endif
+
+ if(flow->protos.stun_ssl.ssl.encrypted_sni.esni == NULL) {
+ flow->protos.stun_ssl.ssl.encrypted_sni.esni = (char*)ndpi_malloc(e_sni_len*2+1);
+
+ if(flow->protos.stun_ssl.ssl.encrypted_sni.esni) {
+ u_int16_t i, off;
+
+ for(i=e_offset, off=0; i<(e_offset+e_sni_len); i++) {
+ int rc = sprintf(&flow->protos.stun_ssl.ssl.encrypted_sni.esni[off], "%02X", packet->payload[i] & 0XFF);
+
+ if(rc <= 0) {
+ flow->protos.stun_ssl.ssl.encrypted_sni.esni[off] = '\0';
+ break;
+ } else
+ off += rc;
+ }
+ }
+ }
+ }
+ }
+ }
}
- extension_offset += extension_len;
+ extension_offset += extension_len; /* Move to the next extension */
#ifdef DEBUG_TLS
printf("Client SSL [extension_offset/len: %u/%u]\n", extension_offset, extension_len);