diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/Makefile.am | 1 | ||||
-rw-r--r-- | src/include/ndpi_typedefs.h | 4 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 6 | ||||
-rw-r--r-- | src/lib/ndpi_utils.c | 13 | ||||
-rw-r--r-- | src/lib/protocols/tls.c | 100 |
5 files changed, 106 insertions, 18 deletions
diff --git a/src/include/Makefile.am b/src/include/Makefile.am index 47fcbd224..db4e40f35 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -1,3 +1,4 @@ +p plibrary_includedir=$(includedir)/libndpi-@VERSION@/libndpi library_include_HEADERS = ndpi_api.h \ diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index b7bff5b85..ca1da4ff2 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -1196,8 +1196,8 @@ struct ndpi_flow_struct { struct { struct { u_int16_t ssl_version, server_names_len; - char client_requested_server_name[64], *server_names, server_organization[64], - *alpn, *tls_supported_versions; + char client_requested_server_name[64], *server_names, + *alpn, *tls_supported_versions, *issuerDN, *subjectDN; u_int32_t notBefore, notAfter; char ja3_client[33], ja3_server[33]; u_int16_t server_cipher; diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index ed2d5995b..db5e14778 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -5976,6 +5976,12 @@ void ndpi_free_flow(struct ndpi_flow_struct *flow) { if(flow->protos.stun_ssl.ssl.tls_supported_versions) ndpi_free(flow->protos.stun_ssl.ssl.tls_supported_versions); + if(flow->protos.stun_ssl.ssl.issuerDN) + ndpi_free(flow->protos.stun_ssl.ssl.issuerDN); + + if(flow->protos.stun_ssl.ssl.subjectDN) + ndpi_free(flow->protos.stun_ssl.ssl.subjectDN); + if(flow->l4.tcp.tls.srv_cert_fingerprint_ctx) ndpi_free(flow->l4.tcp.tls.srv_cert_fingerprint_ctx); } diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c index 7f6d6f9f6..db5394eb0 100644 --- a/src/lib/ndpi_utils.c +++ b/src/lib/ndpi_utils.c @@ -1099,7 +1099,6 @@ int ndpi_flow2json(struct ndpi_detection_module_struct *ndpi_struct, flow->protos.stun_ssl.ssl.client_requested_server_name); if(flow->protos.stun_ssl.ssl.server_names) ndpi_serialize_string_string(serializer, "server_names", flow->protos.stun_ssl.ssl.server_names); - ndpi_serialize_string_string(serializer, "issuer", flow->protos.stun_ssl.ssl.server_organization); if(before) { strftime(notBefore, sizeof(notBefore), "%F %T", before); @@ -1115,6 +1114,18 @@ int ndpi_flow2json(struct ndpi_detection_module_struct *ndpi_struct, ndpi_serialize_string_uint32(serializer, "unsafe_cipher", flow->protos.stun_ssl.ssl.server_unsafe_cipher); ndpi_serialize_string_string(serializer, "cipher", ndpi_cipher2str(flow->protos.stun_ssl.ssl.server_cipher)); + if(flow->protos.stun_ssl.ssl.issuerDN) + ndpi_serialize_string_string(serializer, "issuerDN", flow->protos.stun_ssl.ssl.issuerDN); + + if(flow->protos.stun_ssl.ssl.subjectDN) + ndpi_serialize_string_string(serializer, "issuerDN", flow->protos.stun_ssl.ssl.subjectDN); + + if(flow->protos.stun_ssl.ssl.alpn) + ndpi_serialize_string_string(serializer, "alpn", flow->protos.stun_ssl.ssl.alpn); + + if(flow->protos.stun_ssl.ssl.tls_supported_versions) + ndpi_serialize_string_string(serializer, "tls_supported_versions", flow->protos.stun_ssl.ssl.tls_supported_versions); + if(flow->l4.tcp.tls.sha1_certificate_fingerprint[0] != '\0') { for(i=0, off=0; i<20; i++) { int rc = snprintf(&buf[off], sizeof(buf)-off,"%s%02X", (i > 0) ? ":" : "", diff --git a/src/lib/protocols/tls.c b/src/lib/protocols/tls.c index 184f64e65..171d7c489 100644 --- a/src/lib/protocols/tls.c +++ b/src/lib/protocols/tls.c @@ -188,17 +188,20 @@ static void cleanupServerName(char *buffer, int buffer_len) { 1: OK */ static int extractRDNSequence(struct ndpi_packet_struct *packet, - u_int offset, char *buffer, u_int buffer_len) { + u_int offset, char *buffer, u_int buffer_len, + char *rdnSeqBuf, u_int *rdnSeqBuf_offset, + u_int rdnSeqBuf_len, + const char *label) { u_int8_t str_len = packet->payload[offset+4], is_printable = 1; char *str; u_int len, j; - + // packet is truncated... further inspection is not needed if((offset+4+str_len) >= packet->payload_packet_len) return(-1); str = (char*)&packet->payload[offset+5]; - + len = (u_int)ndpi_min(str_len, buffer_len-1); strncpy(buffer, str, len); buffer[len] = '\0'; @@ -211,6 +214,16 @@ static int extractRDNSequence(struct ndpi_packet_struct *packet, } } + if(is_printable) { + int rc = snprintf(&rdnSeqBuf[*rdnSeqBuf_offset], + rdnSeqBuf_len-(*rdnSeqBuf_offset), + "%s%s=%s", (*rdnSeqBuf_offset > 0) ? ", " : "", + label, buffer); + + if(rc > 0) + (*rdnSeqBuf_offset) += rc; + } + return(is_printable); } @@ -222,7 +235,8 @@ static void processCertificateElements(struct ndpi_detection_module_struct *ndpi u_int16_t p_offset, u_int16_t certificate_len) { struct ndpi_packet_struct *packet = &flow->packet; u_int num_found = 0, i; - char buffer[64] = { '\0' }; + char buffer[64] = { '\0' }, rdnSeqBuf[1024] = { '\0' }; + u_int rdn_len = 0; #ifdef DEBUG_TLS printf("[TLS] %s() [offset: %u][certificate_len: %u]\n", __FUNCTION__, p_offset, certificate_len); @@ -230,32 +244,81 @@ static void processCertificateElements(struct ndpi_detection_module_struct *ndpi /* Check after handshake protocol header (5 bytes) and message header (4 bytes) */ for(i = p_offset; i < certificate_len; i++) { - /* Organization OID: 2.5.4.10 */ - if((packet->payload[i] == 0x55) && (packet->payload[i+1] == 0x04) && (packet->payload[i+2] == 0x0a)) { - int rc = extractRDNSequence(packet, i, buffer, sizeof(buffer)); + /* + See https://www.ibm.com/support/knowledgecenter/SSFKSJ_7.5.0/com.ibm.mq.sec.doc/q009860_.htm + for X.509 certificate labels + */ + if((packet->payload[i] == 0x55) && (packet->payload[i+1] == 0x04) && (packet->payload[i+2] == 0x03)) { + /* Common Name */ + int rc = extractRDNSequence(packet, i, buffer, sizeof(buffer), rdnSeqBuf, &rdn_len, sizeof(rdnSeqBuf), "CN"); + if(rc == -1) break; + +#ifdef DEBUG_TLS + printf("[TLS] %s() [%s][%s: %s]\n", __FUNCTION__, (num_found == 0) ? "Subject" : "Issuer", "Common Name", buffer); +#endif + } else if((packet->payload[i] == 0x55) && (packet->payload[i+1] == 0x04) && (packet->payload[i+2] == 0x06)) { + /* Country */ + int rc = extractRDNSequence(packet, i, buffer, sizeof(buffer), rdnSeqBuf, &rdn_len, sizeof(rdnSeqBuf), "C"); + if(rc == -1) break; + +#ifdef DEBUG_TLS + printf("[TLS] %s() [%s][%s: %s]\n", __FUNCTION__, (num_found == 0) ? "Subject" : "Issuer", "Country", buffer); +#endif + } else if((packet->payload[i] == 0x55) && (packet->payload[i+1] == 0x04) && (packet->payload[i+2] == 0x07)) { + /* Locality */ + int rc = extractRDNSequence(packet, i, buffer, sizeof(buffer), rdnSeqBuf, &rdn_len, sizeof(rdnSeqBuf), "L"); + if(rc == -1) break; +#ifdef DEBUG_TLS + printf("[TLS] %s() [%s][%s: %s]\n", __FUNCTION__, (num_found == 0) ? "Subject" : "Issuer", "Locality", buffer); +#endif + } else if((packet->payload[i] == 0x55) && (packet->payload[i+1] == 0x04) && (packet->payload[i+2] == 0x08)) { + /* State or Province */ + int rc = extractRDNSequence(packet, i, buffer, sizeof(buffer), rdnSeqBuf, &rdn_len, sizeof(rdnSeqBuf), "ST"); if(rc == -1) break; - num_found++; - /* what we want is subject certificate, so we bypass the issuer certificate */ - if(num_found != 2) continue; +#ifdef DEBUG_TLS + printf("[TLS] %s() [%s][%s: %s]\n", __FUNCTION__, (num_found == 0) ? "Subject" : "Issuer", "State or Province", buffer); +#endif + } else if((packet->payload[i] == 0x55) && (packet->payload[i+1] == 0x04) && (packet->payload[i+2] == 0x0a)) { + /* Organization Name */ + int rc = extractRDNSequence(packet, i, buffer, sizeof(buffer), rdnSeqBuf, &rdn_len, sizeof(rdnSeqBuf), "O"); + if(rc == -1) break; - if(rc == 1) { - snprintf(flow->protos.stun_ssl.ssl.server_organization, - sizeof(flow->protos.stun_ssl.ssl.server_organization), "%s", buffer); #ifdef DEBUG_TLS - printf("Certificate organization: %s\n", flow->protos.stun_ssl.ssl.server_organization); + printf("[TLS] %s() [%s][%s: %s]\n", __FUNCTION__, (num_found == 0) ? "Subject" : "Issuer", "Organization Name", buffer); +#endif + + } else if((packet->payload[i] == 0x55) && (packet->payload[i+1] == 0x04) && (packet->payload[i+2] == 0x0b)) { + /* Organization Unit */ + int rc = extractRDNSequence(packet, i, buffer, sizeof(buffer), rdnSeqBuf, &rdn_len, sizeof(rdnSeqBuf), "OU"); + if(rc == -1) break; + +#ifdef DEBUG_TLS + printf("[TLS] %s() [%s][%s: %s]\n", __FUNCTION__, (num_found == 0) ? "Subject" : "Issuer", "Organization Unit", buffer); #endif - } } else if((packet->payload[i] == 0x30) && (packet->payload[i+1] == 0x1e) && (packet->payload[i+2] == 0x17)) { /* Certificate Validity */ u_int8_t len = packet->payload[i+3]; u_int offset = i+4; + if(num_found == 0) { + num_found++; + +#ifdef DEBUG_TLS + printf("[TLS] %s() IssuerDN [%s]\n", __FUNCTION__, rdnSeqBuf); +#endif + + if(rdn_len) flow->protos.stun_ssl.ssl.issuerDN = strdup(rdnSeqBuf); + rdn_len = 0; /* Reset buffer */ + } + if((offset+len) < packet->payload_packet_len) { char utcDate[32]; #ifdef DEBUG_TLS + u_int j; + printf("[CERTIFICATE] notBefore [len: %u][", len); for(j=0; j<len; j++) printf("%c", packet->payload[i+4+j]); printf("]\n"); @@ -287,6 +350,8 @@ static void processCertificateElements(struct ndpi_detection_module_struct *ndpi if((offset+len) < packet->payload_packet_len) { #ifdef DEBUG_TLS + u_int j; + printf("[CERTIFICATE] notAfter [len: %u][", len); for(j=0; j<len; j++) printf("%c", packet->payload[offset+j]); printf("]\n"); @@ -383,6 +448,11 @@ static void processCertificateElements(struct ndpi_detection_module_struct *ndpi } /* while */ } } + + if(rdn_len) flow->protos.stun_ssl.ssl.subjectDN = strdup(rdnSeqBuf); +#if DEBUG_TLS + printf("[TLS] %s() SubjectDN [%s]\n", __FUNCTION__, rdnSeqBuf); +#endif } /* **************************************** */ |