diff --git a/src/include/ndpi_private.h b/src/include/ndpi_private.h index 10a2a064e53..b9f197ad612 100644 --- a/src/include/ndpi_private.h +++ b/src/include/ndpi_private.h @@ -236,6 +236,7 @@ struct ndpi_detection_module_config_struct { int tls_ja3c_fingerprint_enabled; int tls_ja3s_fingerprint_enabled; int tls_ja4c_fingerprint_enabled; + int tls_ja4r_fingerprint_enabled; int tls_subclassification_enabled; int quic_subclassification_enabled; diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 0756e5a24fc..deb8d9624ba 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -1353,7 +1353,7 @@ struct ndpi_flow_struct { struct { char *server_names, *advertised_alpns, *negotiated_alpn, *tls_supported_versions, *issuerDN, *subjectDN; u_int32_t notBefore, notAfter; - char ja3_client[33], ja3_server[33], ja4_client[37]; + char ja3_client[33], ja3_server[33], ja4_client[37], *ja4_client_raw; u_int16_t server_cipher; u_int8_t sha1_certificate_fingerprint[20]; u_int8_t client_hello_processed:1, ch_direction:1, subprotocol_detected:1, server_hello_processed:1, fingerprint_set:1, webrtc:1, _pad:2; diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index db3a83bb983..a61a8e8045d 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -6717,7 +6717,10 @@ void ndpi_free_flow_data(struct ndpi_flow_struct* flow) { if(flow->protos.tls_quic.encrypted_sni.esni) ndpi_free(flow->protos.tls_quic.encrypted_sni.esni); - } + + if(flow->protos.tls_quic.ja4_client_raw) + ndpi_free(flow->protos.tls_quic.ja4_client_raw); + } if(flow->tls_quic.message[0].buffer) ndpi_free(flow->tls_quic.message[0].buffer); @@ -11403,10 +11406,11 @@ static const struct cfg_param { { "tls", "metadata.ja3c_fingerprint", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(tls_ja3c_fingerprint_enabled), NULL }, { "tls", "metadata.ja3s_fingerprint", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(tls_ja3s_fingerprint_enabled), NULL }, { "tls", "metadata.ja4c_fingerprint", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(tls_ja4c_fingerprint_enabled), NULL }, + { "tls", "metadata.ja4r_fingerprint", "disable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(tls_ja4r_fingerprint_enabled), NULL }, { "tls", "subclassification", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(tls_subclassification_enabled), NULL }, { "quic", "subclassification", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(quic_subclassification_enabled), NULL }, - + { "smtp", "tls_dissection", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(smtp_opportunistic_tls_enabled), NULL }, { "imap", "tls_dissection", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(imap_opportunistic_tls_enabled), NULL }, diff --git a/src/lib/protocols/tls.c b/src/lib/protocols/tls.c index a41b2d691d9..b26a57998a2 100644 --- a/src/lib/protocols/tls.c +++ b/src/lib/protocols/tls.c @@ -1658,7 +1658,8 @@ static bool is_grease_version(u_int16_t version) { /* **************************************** */ -static void ndpi_compute_ja4(struct ndpi_flow_struct *flow, +static void ndpi_compute_ja4(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_flow_struct *flow, u_int32_t quic_version, union ja_info *ja) { u_int8_t tmp_str[JA_STR_LEN]; @@ -1670,6 +1671,9 @@ static void ndpi_compute_ja4(struct ndpi_flow_struct *flow, char * const ja_str = &flow->protos.tls_quic.ja4_client[0]; const u_int16_t ja_max_len = sizeof(flow->protos.tls_quic.ja4_client); bool is_dtls = ((flow->l4_proto == IPPROTO_UDP) && (quic_version == 0)) || flow->stun.maybe_dtls; + int ja4_r_len = 0; + char ja4_r[1024]; + /* Compute JA4 TLS/QUIC client @@ -1771,6 +1775,12 @@ static void ndpi_compute_ja4(struct ndpi_flow_struct *flow, if((rc > 0) && (tmp_str_len + rc < JA_STR_LEN)) tmp_str_len += rc; else break; } + ja_str[ja_str_len] = 0; + i = snprintf(&ja4_r[ja4_r_len], sizeof(ja4_r)-ja4_r_len, "%s", ja_str); if(i > 0) ja4_r_len += i; + + tmp_str[tmp_str_len] = 0; + i = snprintf(&ja4_r[ja4_r_len], sizeof(ja4_r)-ja4_r_len, "%s_", tmp_str); if(i > 0) ja4_r_len += i; + ndpi_sha256(tmp_str, tmp_str_len, sha_hash); rc = ndpi_snprintf(&ja_str[ja_str_len], ja_max_len - ja_str_len, @@ -1802,7 +1812,18 @@ static void ndpi_compute_ja4(struct ndpi_flow_struct *flow, #ifdef DEBUG_JA printf("[EXTN] %s [len: %u]\n", tmp_str, tmp_str_len); #endif + + tmp_str[tmp_str_len] = 0; + i = snprintf(&ja4_r[ja4_r_len], sizeof(ja4_r)-ja4_r_len, "%s", tmp_str); if(i > 0) ja4_r_len += i; + if(ndpi_struct->cfg.tls_ja4r_fingerprint_enabled) { + if(flow->protos.tls_quic.ja4_client_raw == NULL) + flow->protos.tls_quic.ja4_client_raw = ndpi_strdup(ja4_r); +#ifdef DEBUG_JA + printf("[JA4_r] %s [len: %u]\n", ja4_r, ja4_r_len); +#endif + } + ndpi_sha256(tmp_str, tmp_str_len, sha_hash); rc = ndpi_snprintf(&ja_str[ja_str_len], ja_max_len - ja_str_len, @@ -1812,6 +1833,7 @@ static void ndpi_compute_ja4(struct ndpi_flow_struct *flow, if((rc > 0) && (ja_str_len + rc < JA_STR_LEN)) ja_str_len += rc; ja_str[36] = 0; + #ifdef DEBUG_JA printf("[JA4] %s [len: %lu]\n", ja_str, strlen(ja_str)); #endif @@ -2901,7 +2923,7 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct, } if(ndpi_struct->cfg.tls_ja4c_fingerprint_enabled) { - ndpi_compute_ja4(flow, quic_version, &ja); + ndpi_compute_ja4(ndpi_struct, flow, quic_version, &ja); } /* End JA3/JA4 */ }