aboutsummaryrefslogtreecommitdiff
path: root/src/lib/protocols
diff options
context:
space:
mode:
authorRavi Kerur <ravi.kerur@viasat.com>2019-09-20 10:54:58 -0700
committerRavi Kerur <ravi.kerur@viasat.com>2019-09-20 10:54:58 -0700
commite2e05cd499d9f3c71dbe3ef15a59d3ad1befdd84 (patch)
tree9db7de3d0891cc421a80634bb643458d5e34e57c /src/lib/protocols
parent7e3fd16b0d3945ef6ba2f58c23f54639ea71538c (diff)
parentbdcc6dc173c52d17a1d4b5b7f16e7e4454a91044 (diff)
Merge branch 'dev' of https://github.com/ntop/nDPI into ndpi_icmp
Diffstat (limited to 'src/lib/protocols')
-rw-r--r--src/lib/protocols/line.c32
-rw-r--r--src/lib/protocols/stun.c172
-rw-r--r--src/lib/protocols/tls.c63
3 files changed, 135 insertions, 132 deletions
diff --git a/src/lib/protocols/line.c b/src/lib/protocols/line.c
index 0e624ab7d..b6e676c55 100644
--- a/src/lib/protocols/line.c
+++ b/src/lib/protocols/line.c
@@ -36,31 +36,35 @@ void ndpi_search_line(struct ndpi_detection_module_struct *ndpi_struct, struct n
NDPI_LOG_DBG(ndpi_struct, "search line\n");
- if(packet->iph) {
+ 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((packet->payload_packet_len == 110)
- && (flow->packet.payload[0] == 0xB6) && (flow->packet.payload[1] == 0x18)
- && (flow->packet.payload[2] == 0x00) && (flow->packet.payload[3] == 0x6A)) {
- ndpi_line_report_protocol(ndpi_struct, flow);
- return;
+ if (((ntohl(packet->iph->saddr) & 0xFFFFFF00 /* 255.255.255.0 */) == 0x7DD1FC00) ||
+ ((ntohl(packet->iph->daddr) & 0xFFFFFF00 /* 255.255.255.0 */) == 0x7DD1FC00)) {
+ if ((packet->payload_packet_len == 110) && (flow->packet.payload[0] == 0xB6) &&
+ (flow->packet.payload[1] == 0x18) && (flow->packet.payload[2] == 0x00) &&
+ (flow->packet.payload[3] == 0x6A)) {
+ ndpi_line_report_protocol(ndpi_struct, flow);
+ return;
}
}
}
+ if ((packet->payload_packet_len == 46 && ntohl(get_u_int32_t(packet->payload, 0)) == 0xb6130006) ||
+ (packet->payload_packet_len == 8 && ntohl(get_u_int32_t(packet->payload, 0)) == 0xb6070004) ||
+ (packet->payload_packet_len == 16 && ntohl(get_u_int32_t(packet->payload, 0)) == 0xb609000c)) {
+ ndpi_line_report_protocol(ndpi_struct, flow);
+ return;
+ }
+
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
}
void init_line_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask)
{
- ndpi_set_bitmask_protocol_detection("Line", ndpi_struct, detection_bitmask, *id,
- NDPI_PROTOCOL_LINE,
- ndpi_search_line,
- NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
- SAVE_DETECTION_BITMASK_AS_UNKNOWN,
- ADD_TO_DETECTION_BITMASK);
+ ndpi_set_bitmask_protocol_detection("Line", ndpi_struct, detection_bitmask, *id, NDPI_PROTOCOL_LINE,
+ ndpi_search_line, NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN, ADD_TO_DETECTION_BITMASK);
*id += 1;
}
diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c
index 76a75fb8d..77ddf6ca0 100644
--- a/src/lib/protocols/stun.c
+++ b/src/lib/protocols/stun.c
@@ -41,6 +41,23 @@ struct stun_packet_header {
/* ************************************************************ */
+static u_int8_t is_stun_based_proto(u_int16_t proto) {
+
+ switch(proto) {
+ case NDPI_PROTOCOL_WHATSAPP_CALL:
+ case NDPI_PROTOCOL_MESSENGER:
+ case NDPI_PROTOCOL_HANGOUT_DUO:
+ case NDPI_PROTOCOL_SKYPE_CALL:
+ case NDPI_PROTOCOL_SIGNAL:
+ case NDPI_PROTOCOL_STUN:
+ return(1);
+ }
+
+ return(0);
+}
+
+/* ************************************************************ */
+
u_int32_t get_stun_lru_key(struct ndpi_flow_struct *flow, u_int8_t rev) {
if(rev)
return(flow->packet.iph->daddr + flow->packet.udp->dest);
@@ -52,7 +69,7 @@ u_int32_t get_stun_lru_key(struct ndpi_flow_struct *flow, u_int8_t rev) {
void ndpi_int_stun_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
- u_int app_proto, u_int proto) {
+ u_int proto, u_int app_proto) {
if(ndpi_struct->stun_cache == NULL)
ndpi_struct->stun_cache = ndpi_lru_cache_init(1024);
@@ -71,24 +88,25 @@ void ndpi_int_stun_add_connection(struct ndpi_detection_module_struct *ndpi_stru
#endif
app_proto = cached_proto, proto = NDPI_PROTOCOL_STUN;
} else {
- u_int32_t key1 = get_stun_lru_key(flow, 1);
+ u_int32_t key_rev = get_stun_lru_key(flow, 1);
- if(ndpi_lru_find_cache(ndpi_struct->stun_cache, key1,
+ if(ndpi_lru_find_cache(ndpi_struct->stun_cache, key_rev,
&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", key1, cached_proto, proto, app_proto);
+ printf("[LRU] FOUND %u / %u: no need to cache %u.%u\n", key_rev, cached_proto, proto, app_proto);
#endif
app_proto = cached_proto, proto = NDPI_PROTOCOL_STUN;
} else {
if(app_proto != NDPI_PROTOCOL_STUN) {
/* No sense to ass STUN, but only subprotocols */
-
+
#ifdef DEBUG_LRU
printf("[LRU] ADDING %u / %u.%u [%u -> %u]\n", key, proto, app_proto,
ntohs(flow->packet.udp->source), ntohs(flow->packet.udp->dest));
#endif
-
+
ndpi_lru_add_to_cache(ndpi_struct->stun_cache, key, app_proto);
+ ndpi_lru_add_to_cache(ndpi_struct->stun_cache, key_rev, app_proto);
}
}
}
@@ -140,11 +158,7 @@ static int is_messenger_ip_address(u_int32_t host) {
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,
- const u_int16_t payload_length,
- u_int8_t *is_whatsapp,
- u_int8_t *is_messenger,
- u_int8_t *is_duo
- ) {
+ const u_int16_t payload_length) {
u_int16_t msg_type, msg_len;
struct stun_packet_header *h = (struct stun_packet_header*)payload;
u_int8_t can_this_be_whatsapp_voice = 1;
@@ -152,15 +166,13 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
/* STUN over TCP does not look good */
if(flow->packet.tcp) return(NDPI_IS_NOT_STUN);
- *is_whatsapp = 0, *is_messenger = 0, *is_duo = 0;
-
if(payload_length >= 512) {
return(NDPI_IS_NOT_STUN);
} else if(payload_length < sizeof(struct stun_packet_header)) {
/* This looks like an invalid packet */
if(flow->protos.stun_ssl.stun.num_udp_pkts > 0) {
- *is_whatsapp = 1;
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
return(NDPI_IS_STUN); /* This is WhatsApp Voice */
} else
return(NDPI_IS_NOT_STUN);
@@ -179,6 +191,19 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
#ifdef DEBUG_STUN
printf("[STUN] msg_type = %04X\n", msg_type);
#endif
+
+ if(is_stun_based_proto(flow->guessed_host_protocol_id)) {
+ /*
+ In this case we have the detected the typical STUN pattern
+ of modern protocols where the flow starts as STUN and becomes
+ something else that has nothing to do with STUN anymore
+ */
+ ndpi_int_stun_add_connection(ndpi_struct, flow,
+ flow->guessed_protocol_id,
+ flow->guessed_host_protocol_id);
+ return(NDPI_IS_STUN);
+ }
+
return(NDPI_IS_NOT_STUN);
}
@@ -214,21 +239,6 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
flow->guessed_host_protocol_id = proto, flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
- switch(proto) {
- case NDPI_PROTOCOL_WHATSAPP:
- *is_whatsapp = 1;
- break;
- case NDPI_PROTOCOL_MESSENGER:
- *is_messenger = 1;
- break;
- case NDPI_PROTOCOL_HANGOUT_DUO:
- *is_duo = 1;
- break;
- case NDPI_PROTOCOL_SKYPE_CALL:
- flow->protos.stun_ssl.stun.is_skype = 1;
- break;
- }
-
return(NDPI_IS_STUN);
} else {
#ifdef DEBUG_LRU
@@ -247,10 +257,10 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
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->guessed_protocol_id = NDPI_PROTOCOL_STUN;
if(msg_len == 0) {
- flow->protos.stun_ssl.stun.num_udp_pkts++;
+ /* flow->protos.stun_ssl.stun.num_udp_pkts++; */
return(NDPI_IS_NOT_STUN); /* This to keep analyzing STUN instead of giving up */
}
}
@@ -270,12 +280,12 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
if(((payload[0] == 0x80)
&& (payload_length < 512)
&& ((msg_len+20) <= payload_length)) /* WhatsApp Voice */) {
- *is_whatsapp = 1;
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
return(NDPI_IS_STUN); /* This is WhatsApp Voice */
} else if((payload[0] == 0x90)
&& (((msg_len+11) == payload_length) /* WhatsApp Video */
|| (flow->protos.stun_ssl.stun.num_binding_requests >= 4))) {
- *is_whatsapp = 2;
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
return(NDPI_IS_STUN); /* This is WhatsApp Video */
}
@@ -285,7 +295,7 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
switch(flow->guessed_protocol_id) {
case NDPI_PROTOCOL_HANGOUT_DUO:
case NDPI_PROTOCOL_MESSENGER:
- case NDPI_PROTOCOL_WHATSAPP_VOICE:
+ case NDPI_PROTOCOL_WHATSAPP_CALL:
/* Don't overwrite the protocol with sub-STUN protocols */
break;
@@ -323,8 +333,8 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
#endif
switch(attribute) {
- case 0x0008: /* Message Integrity */
- case 0x0020: /* XOR-MAPPED-ADDRESSES */
+ // case 0x0008: /* Message Integrity */
+ // case 0x0020: /* XOR-MAPPED-ADDRESSES */
case 0x4000:
case 0x4001:
case 0x4002:
@@ -349,7 +359,6 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
#endif
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);
} else if(strstr((char*)flow->host_server_name, "whispersystems.org") != NULL) {
@@ -363,12 +372,10 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
case 0xC057: /* Messeger */
if(msg_type == 0x0001) {
if((msg_len == 100) || (msg_len == 104)) {
- *is_messenger = 1;
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_MESSENGER, flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
return(NDPI_IS_STUN);
} else if(msg_len == 76) {
#if 0
- *is_duo = 1;
-
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 */
@@ -390,7 +397,6 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
printf("==> Skype found\n");
#endif
flow->guessed_protocol_id = NDPI_PROTOCOL_SKYPE_CALL;
- flow->protos.stun_ssl.stun.is_skype = 1;
return(NDPI_IS_STUN);
}
break;
@@ -411,7 +417,6 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
#endif
flow->guessed_protocol_id = NDPI_PROTOCOL_SKYPE_CALL;
- flow->protos.stun_ssl.stun.is_skype = 1;
return(NDPI_IS_STUN);
break;
@@ -424,7 +429,6 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
&& ((payload[offset+7] == 0x02) || (payload[offset+7] == 0x03))
) {
flow->guessed_protocol_id = NDPI_PROTOCOL_SKYPE_CALL;
- flow->protos.stun_ssl.stun.is_skype = 1;
#ifdef DEBUG_STUN
printf("==> Skype (3) found\n");
#endif
@@ -451,13 +455,13 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
}
goto udp_stun_found;
} else if(msg_type == 0x0800) {
- *is_whatsapp = 1;
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
return(NDPI_IS_STUN); /* This is WhatsApp */
}
}
if((flow->protos.stun_ssl.stun.num_udp_pkts > 0) && (msg_type <= 0x00FF)) {
- *is_whatsapp = 1;
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
return(NDPI_IS_STUN); /* This is WhatsApp Voice */
} else
return(NDPI_IS_NOT_STUN);
@@ -466,23 +470,25 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
if(can_this_be_whatsapp_voice) {
struct ndpi_packet_struct *packet = &flow->packet;
int rc;
-
+
flow->protos.stun_ssl.stun.num_processed_pkts++;
#ifdef DEBUG_STUN
- printf("==>> NDPI_PROTOCOL_WHATSAPP_VOICE\n");
+ printf("==>> NDPI_PROTOCOL_WHATSAPP_CALL\n");
#endif
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;
+ NDPI_PROTOCOL_MESSENGER : NDPI_PROTOCOL_WHATSAPP_CALL;
} 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;
+ ? NDPI_PROTOCOL_HANGOUT_DUO : NDPI_PROTOCOL_WHATSAPP_CALL;
rc = (flow->protos.stun_ssl.stun.num_udp_pkts < MAX_NUM_STUN_PKTS) ? NDPI_IS_NOT_STUN : NDPI_IS_STUN;
if(rc == NDPI_IS_STUN)
- ndpi_int_stun_add_connection(ndpi_struct, flow, flow->guessed_host_protocol_id, NDPI_IS_STUN);
+ ndpi_int_stun_add_connection(ndpi_struct, flow,
+ NDPI_IS_STUN,
+ flow->guessed_host_protocol_id);
return(rc);
} else {
@@ -498,7 +504,6 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
void ndpi_search_stun(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
{
struct ndpi_packet_struct *packet = &flow->packet;
- u_int8_t is_whatsapp = 0, is_messenger = 0, is_duo = 0;
NDPI_LOG_DBG(ndpi_struct, "search stun\n");
@@ -517,64 +522,27 @@ void ndpi_search_stun(struct ndpi_detection_module_struct *ndpi_struct, struct n
* improved by checking only the STUN packet of given length */
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 == NDPI_PROTOCOL_UNKNOWN) flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
-
- if(is_messenger) {
- ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MESSENGER, NDPI_PROTOCOL_STUN);
- return;
- } else if(is_duo) {
- ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HANGOUT_DUO, NDPI_PROTOCOL_STUN);
- return;
- } else if(flow->guessed_host_protocol_id == NDPI_PROTOCOL_SIGNAL) {
- ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SIGNAL, NDPI_PROTOCOL_STUN);
- return;
- } else if(flow->protos.stun_ssl.stun.is_skype || (flow->guessed_host_protocol_id = NDPI_PROTOCOL_SKYPE_CALL)) {
- 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_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, flow,
- is_whatsapp ? (is_whatsapp == 1 ? NDPI_PROTOCOL_WHATSAPP_VOICE : NDPI_PROTOCOL_WHATSAPP_VIDEO) : NDPI_PROTOCOL_STUN,
- NDPI_PROTOCOL_UNKNOWN);
- }
-
- return;
+ packet->payload_packet_len - 2) == NDPI_IS_STUN) {
+ goto udp_stun_match;
}
}
}
/* UDP */
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 == NDPI_PROTOCOL_UNKNOWN) flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
-
- if(is_messenger) {
- ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MESSENGER, NDPI_PROTOCOL_STUN);
- return;
- } else if(is_duo) {
- ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HANGOUT_DUO, NDPI_PROTOCOL_STUN);
- return;
- } else if(flow->guessed_host_protocol_id == NDPI_PROTOCOL_SIGNAL) {
- ndpi_int_stun_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SIGNAL, 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_udp_pkts >= 6) || (flow->protos.stun_ssl.stun.num_binding_requests >= 3))
- 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, flow,
- is_whatsapp ? (is_whatsapp == 1 ? NDPI_PROTOCOL_WHATSAPP_VOICE : NDPI_PROTOCOL_WHATSAPP_VIDEO)
- : NDPI_PROTOCOL_STUN, NDPI_PROTOCOL_UNKNOWN);
- }
+ packet->payload_packet_len) == NDPI_IS_STUN) {
+ udp_stun_match:
+ if(flow->guessed_protocol_id == NDPI_PROTOCOL_UNKNOWN)
+ flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
+ if(flow->guessed_host_protocol_id == NDPI_PROTOCOL_UNKNOWN) {
+ flow->guessed_host_protocol_id = flow->guessed_protocol_id;
+ flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
+ }
+
+ ndpi_int_stun_add_connection(ndpi_struct, flow,
+ flow->guessed_protocol_id,
+ flow->guessed_host_protocol_id);
return;
}
diff --git a/src/lib/protocols/tls.c b/src/lib/protocols/tls.c
index 8a4d0c3ac..f63da2067 100644
--- a/src/lib/protocols/tls.c
+++ b/src/lib/protocols/tls.c
@@ -31,7 +31,7 @@
extern char *strptime(const char *s, const char *format, struct tm *tm);
-// #define DEBUG_TLS 1
+/* #define DEBUG_TLS 1 */
#define DEBUG_FINGERPRINT 1
@@ -176,7 +176,7 @@ static void stripCertificateTrailer(char *buffer, int buffer_len) {
#define MAX_NUM_JA3 128
struct ja3_info {
- u_int16_t tls_version;
+ u_int16_t tls_handshake_version;
u_int16_t num_cipher, cipher[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];
@@ -263,7 +263,7 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct,
else
tls_version = ntohs(*((u_int16_t*)&packet->payload[header_len+12]));
- ja3.tls_version = tls_version;
+ ja3.tls_handshake_version = tls_version;
if(handshake_protocol == 0x02) {
u_int16_t offset = base_offset, extension_len, j;
@@ -291,36 +291,49 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct,
flow->protos.stun_ssl.ssl.server_cipher = ja3.cipher[0];
#ifdef DEBUG_TLS
- printf("SSL [server][session_id_len: %u][cipher: %04X]\n", session_id_len, ja3.cipher[0]);
+ printf("TLS [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 DEBUG_TLS
- printf("SSL [server][extension_len: %u]\n", extension_len);
+ printf("TLS [server][extension_len: %u]\n", extension_len);
#endif
offset += 2;
for(i=0; i<extension_len; ) {
- u_int16_t id, len;
+ u_int16_t extension_id, extension_len;
if(offset >= (packet->payload_packet_len+4)) break;
- id = ntohs(*((u_int16_t*)&packet->payload[offset]));
- len = ntohs(*((u_int16_t*)&packet->payload[offset+2]));
+ extension_id = ntohs(*((u_int16_t*)&packet->payload[offset]));
+ extension_len = ntohs(*((u_int16_t*)&packet->payload[offset+2]));
if(ja3.num_tls_extension < MAX_NUM_JA3)
- ja3.tls_extension[ja3.num_tls_extension++] = id;
+ ja3.tls_extension[ja3.num_tls_extension++] = extension_id;
#ifdef DEBUG_TLS
- printf("SSL [server][extension_id: %u/0x%04X]\n", id, id);
+ printf("TLS [server][extension_id: %u/0x%04X][len: %u]\n",
+ extension_id, extension_id, extension_len);
#endif
- i += 4 + len, offset += 4 + len;
+ if(extension_id == 43 /* supported versions */) {
+ if(extension_len >= 2) {
+ u_int16_t tls_version = ntohs(*((u_int16_t*)&packet->payload[offset+4]));
+
+#ifdef DEBUG_TLS
+ printf("TLS [server] [TLS version: 0x%04X]\n", tls_version);
+#endif
+
+ flow->protos.stun_ssl.ssl.ssl_version = tls_version;
+ }
+ }
+
+ i += 4 + extension_len, offset += 4 + extension_len;
}
- ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.tls_version);
+ ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.tls_handshake_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]);
@@ -333,7 +346,7 @@ int getTLScertificate(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.tls_extension[i]);
#ifdef DEBUG_TLS
- printf("SSL [server] %s\n", ja3_str);
+ printf("TLS [server] %s\n", ja3_str);
#endif
#ifdef DEBUG_TLS
@@ -426,7 +439,7 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct,
session_id_len = packet->payload[base_offset];
- ja3.tls_version = tls_version;
+ ja3.tls_handshake_version = tls_version;
if((session_id_len+base_offset+2) <= total_len) {
u_int16_t cipher_len, cipher_offset;
@@ -533,7 +546,7 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct,
#endif
}
}
-
+
if(extension_id == 0 /* server name */) {
u_int16_t len;
@@ -611,6 +624,20 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct,
printf("Client SSL Invalid len %u vs %u\n", s_offset+extension_len, total_len);
#endif
}
+ } else if(extension_id == 43 /* supported versions */) {
+ u_int8_t version_len = packet->payload[offset+4];
+
+ if(version_len == (extension_len-1)) {
+#ifdef DEBUG_TLS
+ u_int8_t j;
+
+ for(j=0; j<version_len; j += 2) {
+ u_int16_t tls_version = ntohs(*((u_int16_t*)&packet->payload[offset+5+j]));
+
+ printf("Client SSL [TLS version: 0x%04X]\n", tls_version);
+ }
+#endif
+ }
}
extension_offset += extension_len;
@@ -621,7 +648,8 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct,
} /* while */
if(!invalid_ja3) {
- ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.tls_version);
+ compute_ja3c:
+ ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.tls_handshake_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",
@@ -670,6 +698,9 @@ int getTLScertificate(struct ndpi_detection_module_struct *ndpi_struct,
return(2 /* Client Certificate */);
}
+ } else if(offset == total_len) {
+ /* SSL does not have extensions etc */
+ goto compute_ja3c;
}
}
}