diff options
author | Ivan Nardi <12729895+IvanNardi@users.noreply.github.com> | 2022-10-25 17:06:29 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-25 17:06:29 +0200 |
commit | ca5ffc498873805c07a29c6d8af3e995963c055d (patch) | |
tree | efbc859babc7668069c9576b54439ffe10cc9859 /src/lib/protocols/tls.c | |
parent | 2ed2e5dc7e072d41065a7c04da5db598150c71fa (diff) |
TLS: improve handling of ALPN(s) (#1784)
Tell "Advertised" ALPN list from "Negotiated" ALPN; the former is
extracted from the CH, the latter from the SH.
Add some entries to the known ALPN list.
Fix printing of "TLS Supported Versions" field.
Diffstat (limited to 'src/lib/protocols/tls.c')
-rw-r--r-- | src/lib/protocols/tls.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/src/lib/protocols/tls.c b/src/lib/protocols/tls.c index 869fe504b..fa40070f6 100644 --- a/src/lib/protocols/tls.c +++ b/src/lib/protocols/tls.c @@ -1261,11 +1261,11 @@ static void tls_subclassify_by_alpn(struct ndpi_detection_module_struct *ndpi_st struct ndpi_flow_struct *flow) { /* Right now we have only one rule so we can keep it trivial */ - if (!flow->protos.tls_quic.alpn) + if (!flow->protos.tls_quic.advertised_alpns) return; - if(strlen(flow->protos.tls_quic.alpn) > NDPI_STATICSTRING_LEN("anydesk/") && - strncmp(flow->protos.tls_quic.alpn, "anydesk/", NDPI_STATICSTRING_LEN("anydesk/")) == 0) { + if(strlen(flow->protos.tls_quic.advertised_alpns) > NDPI_STATICSTRING_LEN("anydesk/") && + strncmp(flow->protos.tls_quic.advertised_alpns, "anydesk/", NDPI_STATICSTRING_LEN("anydesk/")) == 0) { #ifdef DEBUG_TLS printf("Matching ANYDESK via alpn\n"); #endif @@ -1278,9 +1278,10 @@ static void tls_subclassify_by_alpn(struct ndpi_detection_module_struct *ndpi_st /* **************************************** */ static void tlsCheckUncommonALPN(struct ndpi_detection_module_struct *ndpi_struct, - struct ndpi_flow_struct *flow) { - char * alpn_start = flow->protos.tls_quic.alpn; + struct ndpi_flow_struct *flow, + char *alpn_start) { char * comma_or_nul = alpn_start; + do { size_t alpn_len; @@ -1555,7 +1556,7 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct, u_int16_t s_offset = offset+4; u_int16_t tot_alpn_len = ntohs(*((u_int16_t*)&packet->payload[s_offset])); char alpn_str[256]; - u_int8_t alpn_str_len = 0, i; + u_int16_t alpn_str_len = 0, i; #ifdef DEBUG_TLS printf("Server TLS [ALPN: block_len=%u/len=%u]\n", extension_len, tot_alpn_len); @@ -1605,13 +1606,18 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct, if(ndpi_normalize_printable_string(alpn_str, alpn_str_len) == 0) ndpi_set_risk(ndpi_struct, flow, NDPI_INVALID_CHARACTERS, alpn_str); - if(flow->protos.tls_quic.alpn == NULL) - flow->protos.tls_quic.alpn = ndpi_strdup(alpn_str); + if(flow->protos.tls_quic.negotiated_alpn == NULL) + flow->protos.tls_quic.negotiated_alpn = ndpi_strdup(alpn_str); - if(flow->protos.tls_quic.alpn != NULL) - tlsCheckUncommonALPN(ndpi_struct, flow); + /* Check ALPN only if not already checked (client-side) */ + if(flow->protos.tls_quic.negotiated_alpn != NULL && + flow->protos.tls_quic.advertised_alpns == NULL) + tlsCheckUncommonALPN(ndpi_struct, flow, flow->protos.tls_quic.negotiated_alpn); - ndpi_snprintf(ja3.server.alpn, sizeof(ja3.server.alpn), "%s", alpn_str); + alpn_str_len = ndpi_min(sizeof(ja3.server.alpn), (size_t)alpn_str_len); + memcpy(ja3.server.alpn, alpn_str, alpn_str_len); + if(alpn_str_len > 0) + ja3.server.alpn[alpn_str_len - 1] = '\0'; /* Replace , with - as in JA3 */ for(i=0; ja3.server.alpn[i] != '\0'; i++) @@ -2164,7 +2170,7 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct, u_int16_t s_offset = offset+extension_offset; u_int16_t tot_alpn_len = ntohs(*((u_int16_t*)&packet->payload[s_offset])); char alpn_str[256]; - u_int8_t alpn_str_len = 0, i; + u_int16_t alpn_str_len = 0, i; #ifdef DEBUG_TLS printf("Client TLS [ALPN: block_len=%u/len=%u]\n", extension_len, tot_alpn_len); @@ -2202,8 +2208,10 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct, #ifdef DEBUG_TLS printf("Client TLS [ALPN: %s][len: %u]\n", alpn_str, alpn_str_len); #endif - if(flow->protos.tls_quic.alpn == NULL) { - flow->protos.tls_quic.alpn = ndpi_strdup(alpn_str); + if(flow->protos.tls_quic.advertised_alpns == NULL) { + flow->protos.tls_quic.advertised_alpns = ndpi_strdup(alpn_str); + + tlsCheckUncommonALPN(ndpi_struct, flow, flow->protos.tls_quic.advertised_alpns); /* Without SNI matching we can try to sub-classify the flow via ALPN. Note that this happens only on very rare cases, not the common ones @@ -2212,7 +2220,10 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct, tls_subclassify_by_alpn(ndpi_struct, flow); } - ndpi_snprintf(ja3.client.alpn, sizeof(ja3.client.alpn), "%s", alpn_str); + alpn_str_len = ndpi_min(sizeof(ja3.client.alpn), (size_t)alpn_str_len); + memcpy(ja3.client.alpn, alpn_str, alpn_str_len); + if(alpn_str_len > 0) + ja3.client.alpn[alpn_str_len - 1] = '\0'; /* Replace , with - as in JA3 */ for(i=0; ja3.client.alpn[i] != '\0'; i++) @@ -2473,7 +2484,7 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct, /* Before returning to the caller we need to make a final check */ if((flow->protos.tls_quic.ssl_version >= 0x0303) /* >= TLSv1.2 */ - && (flow->protos.tls_quic.alpn == NULL) /* No ALPN */) { + && (flow->protos.tls_quic.advertised_alpns == NULL) /* No ALPN */) { ndpi_set_risk(ndpi_struct, flow, NDPI_TLS_NOT_CARRYING_HTTPS, "No ALPN"); } |