mirror of
https://github.com/vel21ripn/nDPI.git
synced 2026-04-28 06:59:40 +00:00
Reworked TLS dissector to export further metadata (#3066)
* Reworked TLS dissector to give users the ability to )optionnaly) collect and export TLS metadata via "--cfg=tls,metadata.ja_data,1"
This commit is contained in:
parent
712f4bc72a
commit
45e3213d7f
8 changed files with 225 additions and 111 deletions
|
|
@ -363,4 +363,8 @@ static inline uint64_t get_u_int64_t(const uint8_t* X, int O)
|
|||
/* Maximum number of plugins supported by nDPI */
|
||||
#define NDPI_MAX_NUM_PLUGINS 32
|
||||
|
||||
/* JA3/4 Information */
|
||||
#define MAX_NUM_JA 128
|
||||
#define MAX_JA_STRLEN 256
|
||||
|
||||
#endif /* __NDPI_DEFINE_INCLUDE_FILE__ */
|
||||
|
|
|
|||
|
|
@ -297,6 +297,7 @@ struct ndpi_detection_module_config_struct {
|
|||
int tls_ja3s_fingerprint_enabled;
|
||||
int tls_ja4c_fingerprint_enabled;
|
||||
int tls_ja4r_fingerprint_enabled;
|
||||
int tls_ja_data_enabled;
|
||||
int tls_subclassification_enabled;
|
||||
int tls_blocks_analysis_enabled;
|
||||
int quic_subclassification_enabled;
|
||||
|
|
|
|||
|
|
@ -1518,6 +1518,28 @@ typedef struct ndpi_protocol_plugin {
|
|||
|
||||
typedef int (*ProcessExtraPacketsFunc) (struct ndpi_detection_module_struct *, struct ndpi_flow_struct *flow);
|
||||
|
||||
typedef struct {
|
||||
u_int16_t tls_handshake_version;
|
||||
u_int16_t num_ciphers, cipher[MAX_NUM_JA];
|
||||
u_int16_t num_tls_extensions, tls_extension[MAX_NUM_JA];
|
||||
u_int16_t num_elliptic_curve_groups, elliptic_curve_group[MAX_NUM_JA];
|
||||
u_int16_t num_elliptic_curve_point_format, elliptic_curve_point_format[MAX_NUM_JA];
|
||||
u_int16_t num_signature_algorithms, signature_algorithm[MAX_NUM_JA];
|
||||
u_int16_t num_supported_versions, supported_version[MAX_NUM_JA];
|
||||
u_int16_t num_key_share_groups, key_share_group[MAX_NUM_JA];
|
||||
char signature_algorithms_str[MAX_JA_STRLEN], alpn[MAX_JA_STRLEN];
|
||||
char alpn_original_last; /* Store original last character before null terminator */
|
||||
} ndpi_tls_client_info;
|
||||
|
||||
typedef struct {
|
||||
u_int16_t tls_handshake_version;
|
||||
u_int16_t num_ciphers, cipher[MAX_NUM_JA];
|
||||
u_int16_t num_tls_extensions, tls_extension[MAX_NUM_JA];
|
||||
u_int16_t tls_supported_version;
|
||||
u_int16_t num_elliptic_curve_point_format, elliptic_curve_point_format[MAX_NUM_JA];
|
||||
char alpn[MAX_JA_STRLEN];
|
||||
} ndpi_tls_server_info;
|
||||
|
||||
struct ndpi_flow_struct {
|
||||
u_int16_t detected_protocol_stack[NDPI_PROTOCOL_SIZE];
|
||||
struct ndpi_proto_stack protocol_stack;
|
||||
|
|
@ -1693,8 +1715,7 @@ struct ndpi_flow_struct {
|
|||
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,
|
||||
pq_key_share:1, pq_supported_groups:1;
|
||||
server_hello_processed:1, fingerprint_set:1, webrtc:1;
|
||||
|
||||
#ifdef TLS_HANDLE_SIGNATURE_ALGORITMS
|
||||
/* Under #ifdef to save memory for those who do not need them */
|
||||
|
|
@ -1713,6 +1734,10 @@ struct ndpi_flow_struct {
|
|||
|
||||
u_int32_t quic_version;
|
||||
u_int32_t quic_idle_timeout_sec;
|
||||
|
||||
/* Optionally allocated based on nDPI configuration */
|
||||
ndpi_tls_client_info *ja_client;
|
||||
ndpi_tls_server_info *ja_server;
|
||||
} tls_quic; /* Used also by DTLS and POPS/IMAPS/SMTPS/FTPS */
|
||||
|
||||
struct {
|
||||
|
|
@ -1918,11 +1943,11 @@ struct ndpi_flow_struct {
|
|||
|
||||
#if !defined(NDPI_CFFI_PREPROCESSING) && defined(__linux__)
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||
_Static_assert(sizeof(((struct ndpi_flow_struct *)0)->protos) <= 264,
|
||||
"Size of the struct member protocols increased to more than 264 bytes, "
|
||||
_Static_assert(sizeof(((struct ndpi_flow_struct *)0)->protos) <= 328,
|
||||
"Size of the struct member protocols increased to more than 328 bytes, "
|
||||
"please check if this change is necessary.");
|
||||
_Static_assert(sizeof(struct ndpi_flow_struct) <= 1240,
|
||||
"Size of the flow struct increased to more than 1240 bytes, "
|
||||
_Static_assert(sizeof(struct ndpi_flow_struct) <= 1304,
|
||||
"Size of the flow struct increased to more than 1304 bytes, "
|
||||
"please check if this change is necessary.");
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ static const struct cfg_param {
|
|||
{ "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", "metadata.ja_data", "disable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(tls_ja_data_enabled), NULL },
|
||||
{ "tls", "subclassification", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(tls_subclassification_enabled), NULL },
|
||||
{ "tls", "blocks_analysis", "disable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(tls_blocks_analysis_enabled), NULL },
|
||||
|
||||
|
|
|
|||
|
|
@ -7890,6 +7890,12 @@ void ndpi_free_flow_data(struct ndpi_flow_struct* flow) {
|
|||
|
||||
if(flow->protos.tls_quic.ja4_client_raw)
|
||||
ndpi_free(flow->protos.tls_quic.ja4_client_raw);
|
||||
|
||||
if(flow->protos.tls_quic.ja_client)
|
||||
ndpi_free(flow->protos.tls_quic.ja_client);
|
||||
|
||||
if(flow->protos.tls_quic.ja_server)
|
||||
ndpi_free(flow->protos.tls_quic.ja_server);
|
||||
}
|
||||
|
||||
if(flow_is_proto(flow, NDPI_PROTOCOL_SIP)) {
|
||||
|
|
|
|||
|
|
@ -1208,8 +1208,7 @@ void ndpi_serialize_proto(struct ndpi_detection_module_struct *ndpi_struct,
|
|||
|
||||
static void ndpi_tls2json(ndpi_serializer *serializer, struct ndpi_flow_struct *flow, bool is_tls_proto)
|
||||
{
|
||||
if(flow->protos.tls_quic.ssl_version)
|
||||
{
|
||||
if(flow->protos.tls_quic.ssl_version) {
|
||||
char buf[64];
|
||||
char notBefore[32], notAfter[32];
|
||||
struct tm a, b, *before = NULL, *after = NULL;
|
||||
|
|
@ -1220,33 +1219,26 @@ static void ndpi_tls2json(ndpi_serializer *serializer, struct ndpi_flow_struct *
|
|||
ndpi_ssl_version2str(version, sizeof(version), flow->protos.tls_quic.ssl_version, &unknown_tls_version);
|
||||
|
||||
if(flow->protos.tls_quic.notBefore)
|
||||
{
|
||||
before = ndpi_gmtime_r((const time_t *)&flow->protos.tls_quic.notBefore, &a);
|
||||
}
|
||||
if(flow->protos.tls_quic.notAfter)
|
||||
{
|
||||
after = ndpi_gmtime_r((const time_t *)&flow->protos.tls_quic.notAfter, &b);
|
||||
}
|
||||
|
||||
if(!unknown_tls_version)
|
||||
{
|
||||
if(flow->protos.tls_quic.notAfter)
|
||||
after = ndpi_gmtime_r((const time_t *)&flow->protos.tls_quic.notAfter, &b);
|
||||
|
||||
if(!unknown_tls_version) {
|
||||
ndpi_serialize_start_of_block(serializer, "tls");
|
||||
ndpi_serialize_string_string(serializer, "version", version);
|
||||
|
||||
if(flow->protos.tls_quic.server_names)
|
||||
{
|
||||
if(flow->protos.tls_quic.server_names) {
|
||||
ndpi_serialize_string_string(serializer, "server_names",
|
||||
flow->protos.tls_quic.server_names);
|
||||
}
|
||||
|
||||
if(before)
|
||||
{
|
||||
if(before) {
|
||||
strftime(notBefore, sizeof(notBefore), "%Y-%m-%d %H:%M:%S", before);
|
||||
ndpi_serialize_string_string(serializer, "notbefore", notBefore);
|
||||
}
|
||||
|
||||
if(after)
|
||||
{
|
||||
if(after) {
|
||||
strftime(notAfter, sizeof(notAfter), "%Y-%m-%d %H:%M:%S", after);
|
||||
ndpi_serialize_string_string(serializer, "notafter", notAfter);
|
||||
}
|
||||
|
|
@ -1258,30 +1250,22 @@ static void ndpi_tls2json(ndpi_serializer *serializer, struct ndpi_flow_struct *
|
|||
ndpi_cipher2str(flow->protos.tls_quic.server_cipher, unknown_cipher));
|
||||
|
||||
if(flow->protos.tls_quic.issuerDN)
|
||||
{
|
||||
ndpi_serialize_string_string(serializer, "issuerDN", flow->protos.tls_quic.issuerDN);
|
||||
}
|
||||
if(flow->protos.tls_quic.subjectDN)
|
||||
{
|
||||
ndpi_serialize_string_string(serializer, "subjectDN", flow->protos.tls_quic.subjectDN);
|
||||
}
|
||||
if(flow->protos.tls_quic.advertised_alpns)
|
||||
{
|
||||
ndpi_serialize_string_string(serializer, "advertised_alpns", flow->protos.tls_quic.advertised_alpns);
|
||||
}
|
||||
if(flow->protos.tls_quic.negotiated_alpn)
|
||||
{
|
||||
ndpi_serialize_string_string(serializer, "negotiated_alpn", flow->protos.tls_quic.negotiated_alpn);
|
||||
}
|
||||
if(flow->protos.tls_quic.tls_supported_versions)
|
||||
{
|
||||
ndpi_serialize_string_string(serializer, "tls_supported_versions", flow->protos.tls_quic.tls_supported_versions);
|
||||
}
|
||||
|
||||
if(flow->protos.tls_quic.sha1_certificate_fingerprint[0] != '\0')
|
||||
{
|
||||
for(i=0, off=0; i<20; i++)
|
||||
{
|
||||
if(flow->protos.tls_quic.subjectDN)
|
||||
ndpi_serialize_string_string(serializer, "subjectDN", flow->protos.tls_quic.subjectDN);
|
||||
|
||||
if(flow->protos.tls_quic.advertised_alpns)
|
||||
ndpi_serialize_string_string(serializer, "advertised_alpns", flow->protos.tls_quic.advertised_alpns);
|
||||
|
||||
if(flow->protos.tls_quic.negotiated_alpn)
|
||||
ndpi_serialize_string_string(serializer, "negotiated_alpn", flow->protos.tls_quic.negotiated_alpn);
|
||||
|
||||
if(flow->protos.tls_quic.tls_supported_versions)
|
||||
ndpi_serialize_string_string(serializer, "tls_supported_versions", flow->protos.tls_quic.tls_supported_versions);
|
||||
|
||||
if(flow->protos.tls_quic.sha1_certificate_fingerprint[0] != '\0') {
|
||||
for(i=0, off=0; i<20; i++) {
|
||||
int rc = ndpi_snprintf(&buf[off], sizeof(buf)-off,"%s%02X", (i > 0) ? ":" : "",
|
||||
flow->protos.tls_quic.sha1_certificate_fingerprint[i] & 0xFF);
|
||||
|
||||
|
|
@ -1292,13 +1276,120 @@ static void ndpi_tls2json(ndpi_serializer *serializer, struct ndpi_flow_struct *
|
|||
}
|
||||
|
||||
if (is_tls_proto == true)
|
||||
{
|
||||
ndpi_serialize_string_uint32(serializer, "blocks", flow->l4.tcp.tls.num_tls_blocks);
|
||||
}
|
||||
|
||||
#ifdef TLS_HANDLE_SIGNATURE_ALGORITMS
|
||||
ndpi_serialize_string_uint32(serializer, "sig_algs", flow->protos.tls_quic.num_tls_signature_algorithms);
|
||||
#endif
|
||||
|
||||
if(flow->protos.tls_quic.ja_client != NULL) {
|
||||
ndpi_tls_client_info *c = flow->protos.tls_quic.ja_client;
|
||||
u_int16_t i;
|
||||
|
||||
ndpi_serialize_start_of_block(serializer, "client_data");
|
||||
|
||||
if(c->num_ciphers > 0) {
|
||||
ndpi_serialize_start_of_list(serializer, "ciphers");
|
||||
|
||||
for(i=0; i<c->num_ciphers; i++)
|
||||
ndpi_serialize_string_uint32(serializer, "", c->cipher[i]);
|
||||
|
||||
ndpi_serialize_end_of_list(serializer);
|
||||
}
|
||||
|
||||
if(c->num_tls_extensions > 0) {
|
||||
ndpi_serialize_start_of_list(serializer, "tls_extensions");
|
||||
|
||||
for(i=0; i<c->num_tls_extensions; i++)
|
||||
ndpi_serialize_string_uint32(serializer, "", c->tls_extension[i]);
|
||||
|
||||
ndpi_serialize_end_of_list(serializer);
|
||||
}
|
||||
|
||||
if(c->num_elliptic_curve_groups > 0) {
|
||||
ndpi_serialize_start_of_list(serializer, "elliptic_curve_groups");
|
||||
|
||||
for(i=0; i<c->num_elliptic_curve_groups; i++)
|
||||
ndpi_serialize_string_uint32(serializer, "", c->elliptic_curve_group[i]);
|
||||
|
||||
ndpi_serialize_end_of_list(serializer);
|
||||
}
|
||||
|
||||
if(c->num_elliptic_curve_point_format > 0) {
|
||||
ndpi_serialize_start_of_list(serializer, "elliptic_curve_point_format");
|
||||
|
||||
for(i=0; i<c->num_elliptic_curve_point_format; i++)
|
||||
ndpi_serialize_string_uint32(serializer, "", c->elliptic_curve_point_format[i]);
|
||||
|
||||
ndpi_serialize_end_of_list(serializer);
|
||||
}
|
||||
|
||||
if(c->num_signature_algorithms > 0) {
|
||||
ndpi_serialize_start_of_list(serializer, "signature_algorithms");
|
||||
|
||||
for(i=0; i<c->num_signature_algorithms; i++)
|
||||
ndpi_serialize_string_uint32(serializer, "", c->signature_algorithm[i]);
|
||||
|
||||
ndpi_serialize_end_of_list(serializer);
|
||||
}
|
||||
|
||||
if(c->num_key_share_groups > 0) {
|
||||
ndpi_serialize_start_of_list(serializer, "key_share_groups");
|
||||
|
||||
for(i=0; i<c->num_key_share_groups; i++)
|
||||
ndpi_serialize_string_uint32(serializer, "", c->key_share_group[i]);
|
||||
|
||||
ndpi_serialize_end_of_list(serializer);
|
||||
}
|
||||
|
||||
if(c->num_supported_versions > 0) {
|
||||
ndpi_serialize_start_of_list(serializer, "supported_versions");
|
||||
|
||||
for(i=0; i<c->num_supported_versions; i++)
|
||||
ndpi_serialize_string_uint32(serializer, "", c->supported_version[i]);
|
||||
|
||||
ndpi_serialize_end_of_list(serializer);
|
||||
}
|
||||
|
||||
ndpi_serialize_end_of_block(serializer);
|
||||
}
|
||||
|
||||
if(flow->protos.tls_quic.ja_server != NULL) {
|
||||
ndpi_tls_server_info *s = flow->protos.tls_quic.ja_server;
|
||||
u_int16_t i;
|
||||
|
||||
ndpi_serialize_start_of_block(serializer, "server_data");
|
||||
|
||||
if(s->num_ciphers > 0) {
|
||||
ndpi_serialize_start_of_list(serializer, "ciphers");
|
||||
|
||||
for(i=0; i<s->num_ciphers; i++)
|
||||
ndpi_serialize_string_uint32(serializer, "", s->cipher[i]);
|
||||
|
||||
ndpi_serialize_end_of_list(serializer);
|
||||
}
|
||||
|
||||
if(s->num_tls_extensions > 0) {
|
||||
ndpi_serialize_start_of_list(serializer, "tls_extensions");
|
||||
|
||||
for(i=0; i<s->num_tls_extensions; i++)
|
||||
ndpi_serialize_string_uint32(serializer, "", s->tls_extension[i]);
|
||||
|
||||
ndpi_serialize_end_of_list(serializer);
|
||||
}
|
||||
|
||||
if(s->num_elliptic_curve_point_format > 0) {
|
||||
ndpi_serialize_start_of_list(serializer, "elliptic_curve_point_format");
|
||||
|
||||
for(i=0; i<s->num_elliptic_curve_point_format; i++)
|
||||
ndpi_serialize_string_uint32(serializer, "", s->elliptic_curve_point_format[i]);
|
||||
|
||||
ndpi_serialize_end_of_list(serializer);
|
||||
}
|
||||
|
||||
ndpi_serialize_end_of_block(serializer);
|
||||
}
|
||||
|
||||
ndpi_serialize_end_of_block(serializer);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,30 +57,10 @@ static void ndpi_search_tls_wrapper(struct ndpi_detection_module_struct *ndpi_st
|
|||
*/
|
||||
|
||||
#define JA_STR_LEN 1024
|
||||
#define MAX_NUM_JA 128
|
||||
#define MAX_JA_STRLEN 256
|
||||
|
||||
union ja_info {
|
||||
struct {
|
||||
u_int16_t tls_handshake_version;
|
||||
u_int16_t num_ciphers, cipher[MAX_NUM_JA];
|
||||
u_int16_t num_tls_extensions, tls_extension[MAX_NUM_JA];
|
||||
u_int16_t num_elliptic_curve, elliptic_curve[MAX_NUM_JA];
|
||||
u_int16_t num_elliptic_curve_point_format, elliptic_curve_point_format[MAX_NUM_JA];
|
||||
u_int16_t num_signature_algorithms, signature_algorithms[MAX_NUM_JA];
|
||||
u_int16_t num_supported_versions, supported_versions[MAX_NUM_JA];
|
||||
char signature_algorithms_str[MAX_JA_STRLEN], alpn[MAX_JA_STRLEN];
|
||||
char alpn_original_last; /* Store original last character before null terminator */
|
||||
} client;
|
||||
|
||||
struct {
|
||||
u_int16_t tls_handshake_version;
|
||||
u_int16_t num_ciphers, cipher[MAX_NUM_JA];
|
||||
u_int16_t num_tls_extensions, tls_extension[MAX_NUM_JA];
|
||||
u_int16_t tls_supported_version;
|
||||
u_int16_t num_elliptic_curve_point_format, elliptic_curve_point_format[MAX_NUM_JA];
|
||||
char alpn[MAX_JA_STRLEN];
|
||||
} server;
|
||||
union ndpi_ja_info {
|
||||
ndpi_tls_client_info client;
|
||||
ndpi_tls_server_info server;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -2081,7 +2061,7 @@ static bool is_grease_version(u_int16_t version) {
|
|||
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) {
|
||||
union ndpi_ja_info *ja) {
|
||||
u_int8_t tmp_str[JA_STR_LEN];
|
||||
u_int tmp_str_len, num_extn;
|
||||
u_int8_t sha_hash[NDPI_SHA256_BLOCK_SIZE];
|
||||
|
|
@ -2115,9 +2095,9 @@ static void ndpi_compute_ja4(struct ndpi_detection_module_struct *ndpi_struct,
|
|||
ja_str[0] = is_dtls ? 'd' : ((quic_version != 0) ? 'q' : 't');
|
||||
|
||||
for(i=0; i<ja->client.num_supported_versions; i++) {
|
||||
if((!is_grease_version(ja->client.supported_versions[i]))
|
||||
&& (tls_handshake_version < ja->client.supported_versions[i]))
|
||||
tls_handshake_version = ja->client.supported_versions[i];
|
||||
if((!is_grease_version(ja->client.supported_version[i]))
|
||||
&& (tls_handshake_version < ja->client.supported_version[i]))
|
||||
tls_handshake_version = ja->client.supported_version[i];
|
||||
}
|
||||
|
||||
switch(tls_handshake_version) {
|
||||
|
|
@ -2255,7 +2235,7 @@ static void ndpi_compute_ja4(struct ndpi_detection_module_struct *ndpi_struct,
|
|||
|
||||
for(i=0; i<ja->client.num_signature_algorithms; i++) {
|
||||
rc = ndpi_snprintf((char *)&tmp_str[tmp_str_len], JA_STR_LEN-tmp_str_len, "%s%04x",
|
||||
(i > 0) ? "," : "_", ja->client.signature_algorithms[i]);
|
||||
(i > 0) ? "," : "_", ja->client.signature_algorithm[i]);
|
||||
if((rc > 0) && (tmp_str_len + rc < JA_STR_LEN)) tmp_str_len += rc; else break;
|
||||
}
|
||||
|
||||
|
|
@ -2297,7 +2277,7 @@ static void ndpi_compute_ja4(struct ndpi_detection_module_struct *ndpi_struct,
|
|||
int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct,
|
||||
struct ndpi_flow_struct *flow, u_int32_t quic_version) {
|
||||
struct ndpi_packet_struct *packet = &ndpi_struct->packet;
|
||||
union ja_info ja;
|
||||
union ndpi_ja_info ja;
|
||||
u_int8_t invalid_ja = 0;
|
||||
u_int16_t tls_version;
|
||||
u_int32_t i, j;
|
||||
|
|
@ -2341,11 +2321,8 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct,
|
|||
if(handshake_type == 0x02 /* Server Hello */) {
|
||||
int rc;
|
||||
|
||||
ja.server.num_ciphers = 0;
|
||||
ja.server.num_tls_extensions = 0;
|
||||
ja.server.num_elliptic_curve_point_format = 0;
|
||||
ja.server.alpn[0] = '\0';
|
||||
|
||||
memset(&ja.server, 0, sizeof(ja.server));
|
||||
|
||||
ja.server.tls_handshake_version = tls_version;
|
||||
|
||||
#ifdef DEBUG_TLS
|
||||
|
|
@ -2586,21 +2563,23 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct,
|
|||
#ifdef DEBUG_TLS
|
||||
printf("[JA3] Server: %s \n", flow->protos.tls_quic.ja3_server);
|
||||
#endif
|
||||
|
||||
if(ndpi_struct->cfg.tls_ja_data_enabled) {
|
||||
if(flow->protos.tls_quic.ja_server == NULL) {
|
||||
flow->protos.tls_quic.ja_server = ndpi_malloc(sizeof(ndpi_tls_server_info));
|
||||
|
||||
if(flow->protos.tls_quic.ja_server != NULL)
|
||||
memcpy(flow->protos.tls_quic.ja_server, &ja.server, sizeof(ndpi_tls_server_info));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(handshake_type == 0x01 /* Client Hello */) {
|
||||
u_int16_t cipher_len, cipher_offset;
|
||||
u_int8_t cookie_len = 0;
|
||||
|
||||
ja.client.num_ciphers = 0;
|
||||
ja.client.num_tls_extensions = 0;
|
||||
ja.client.num_elliptic_curve = 0;
|
||||
ja.client.num_elliptic_curve_point_format = 0;
|
||||
ja.client.num_signature_algorithms = 0;
|
||||
ja.client.num_supported_versions = 0;
|
||||
ja.client.signature_algorithms_str[0] = '\0';
|
||||
ja.client.alpn[0] = '\0', ja.client.alpn[1] = '\0' /* used by JA4 */;
|
||||
memset(&ja.client, 0, sizeof(ja.client));
|
||||
ja.client.alpn_original_last = '0'; /* Initialize to '0' if no ALPN */
|
||||
|
||||
|
||||
flow->protos.tls_quic.ssl_version = ja.client.tls_handshake_version = tls_version;
|
||||
if(flow->protos.tls_quic.ssl_version < 0x0303) /* < TLSv1.2 */ {
|
||||
if(is_flowrisk_info_enabled(ndpi_struct, NDPI_TLS_OBSOLETE_VERSION)) {
|
||||
|
|
@ -2916,21 +2895,16 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct,
|
|||
#ifdef DEBUG_TLS
|
||||
printf("Client TLS [EllipticCurve: %u/0x%04X]\n", s_group, s_group);
|
||||
#endif
|
||||
switch(s_group) {
|
||||
case 0x11EC: /* X25519MLKEM768 */
|
||||
flow->protos.tls_quic.pq_supported_groups = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if((s_group == 0) || (packet->payload[s_offset+i] != packet->payload[s_offset+i+1])
|
||||
|| ((packet->payload[s_offset+i] & 0xF) != 0xA)) {
|
||||
/* Skip GREASE */
|
||||
if(ja.client.num_elliptic_curve < MAX_NUM_JA)
|
||||
ja.client.elliptic_curve[ja.client.num_elliptic_curve++] = s_group;
|
||||
if(ja.client.num_elliptic_curve_groups < MAX_NUM_JA)
|
||||
ja.client.elliptic_curve_group[ja.client.num_elliptic_curve_groups++] = s_group;
|
||||
else {
|
||||
invalid_ja = 1;
|
||||
#ifdef DEBUG_TLS
|
||||
printf("Client TLS Invalid num elliptic %u\n", ja.client.num_elliptic_curve);
|
||||
printf("Client TLS Invalid num elliptic group %u\n", ja.client.num_elliptic_curve_groups);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -2992,9 +2966,9 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct,
|
|||
}
|
||||
#endif
|
||||
|
||||
for(i=0, id=0; i<tot_signature_algorithms_len && s_offset+i+1<total_len; i += 2) {
|
||||
ja.client.signature_algorithms[id++] = ntohs(*(u_int16_t*)&packet->payload[s_offset+i]);
|
||||
}
|
||||
for(i=0, id=0; i<tot_signature_algorithms_len && s_offset+i+1<total_len; i += 2)
|
||||
ja.client.signature_algorithm[id++] = ntohs(*(u_int16_t*)&packet->payload[s_offset+i]);
|
||||
|
||||
ja.client.num_signature_algorithms = id;
|
||||
|
||||
for(i=0, id=0; i<tot_signature_algorithms_len && s_offset+i+1<total_len; i++) {
|
||||
|
|
@ -3236,7 +3210,7 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct,
|
|||
version_str_len += rc;
|
||||
|
||||
if(ja.client.num_supported_versions < MAX_NUM_JA)
|
||||
ja.client.supported_versions[ja.client.num_supported_versions++] = tls_version;
|
||||
ja.client.supported_version[ja.client.num_supported_versions++] = tls_version;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3355,13 +3329,11 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct,
|
|||
extn_offset,
|
||||
group_id, key_extn_len);
|
||||
#endif
|
||||
|
||||
switch(group_id) {
|
||||
case 0x11EC: /* X25519MLKEM768 */
|
||||
flow->protos.tls_quic.pq_key_share = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(group_id != 0x2a2a /* Skip GREASE */) {
|
||||
if(ja.client.num_key_share_groups < MAX_NUM_JA)
|
||||
ja.client.key_share_group[ja.client.num_key_share_groups++] = group_id;
|
||||
}
|
||||
|
||||
extn_offset += key_extn_len + 4;
|
||||
}
|
||||
}
|
||||
|
|
@ -3384,10 +3356,10 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct,
|
|||
compute_ja4c:
|
||||
if(ndpi_struct->cfg.tls_ja4c_fingerprint_enabled) {
|
||||
ndpi_compute_ja4(ndpi_struct, flow, quic_version, &ja);
|
||||
|
||||
|
||||
if(ndpi_struct->ja4_custom_protos != NULL) {
|
||||
u_int64_t proto_id;
|
||||
|
||||
|
||||
/* This protocol has been defined in protos.txt-like files */
|
||||
if(ndpi_hash_find_entry(ndpi_struct->ja4_custom_protos,
|
||||
flow->protos.tls_quic.ja4_client,
|
||||
|
|
@ -3409,6 +3381,16 @@ compute_ja4c:
|
|||
ndpi_set_risk(ndpi_struct, flow, NDPI_MALICIOUS_FINGERPRINT, flow->protos.tls_quic.ja4_client);
|
||||
}
|
||||
}
|
||||
|
||||
if(ndpi_struct->cfg.tls_ja_data_enabled) {
|
||||
if(flow->protos.tls_quic.ja_client == NULL) {
|
||||
flow->protos.tls_quic.ja_client = ndpi_malloc(sizeof(ndpi_tls_client_info));
|
||||
|
||||
if(flow->protos.tls_quic.ja_client != NULL)
|
||||
memcpy(flow->protos.tls_quic.ja_client, &ja.client, sizeof(ndpi_tls_client_info));
|
||||
}
|
||||
}
|
||||
|
||||
/* End JA4 */
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -293,4 +293,8 @@ static inline u_int64_t get_u_int64_t(const u_int8_t* X, int O)
|
|||
/* Maximum number of plugins supported by nDPI */
|
||||
#define NDPI_MAX_NUM_PLUGINS 32
|
||||
|
||||
/* JA3/4 Information */
|
||||
#define MAX_NUM_JA 128
|
||||
#define MAX_JA_STRLEN 256
|
||||
|
||||
#endif /* __NDPI_DEFINE_INCLUDE_FILE__ */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue