diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/ndpi_protocol_ids.h | 10 | ||||
-rw-r--r-- | src/include/ndpi_protocols.h | 2 | ||||
-rw-r--r-- | src/include/ndpi_typedefs.h | 15 | ||||
-rw-r--r-- | src/lib/Makefile.am | 2 | ||||
-rw-r--r-- | src/lib/ndpi_content_match.c.inc | 75 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 28 | ||||
-rw-r--r-- | src/lib/protocols/eaq.c | 73 | ||||
-rw-r--r-- | src/lib/protocols/kakaotalk_voice.c | 59 | ||||
-rw-r--r-- | src/lib/protocols/rtcp.c | 15 | ||||
-rw-r--r-- | src/lib/protocols/ssl.c | 145 |
10 files changed, 346 insertions, 78 deletions
diff --git a/src/include/ndpi_protocol_ids.h b/src/include/ndpi_protocol_ids.h index 29578b043..717db6136 100644 --- a/src/include/ndpi_protocol_ids.h +++ b/src/include/ndpi_protocol_ids.h @@ -236,9 +236,15 @@ #define NDPI_SERVICE_VIBER NDPI_PROTOCOL_VIBER /* Tomasz Bujlow <tomasz@skatnet.dk> */ #define NDPI_SERVICE_YAHOO NDPI_PROTOCOL_YAHOO /* Tomasz Bujlow <tomasz@skatnet.dk> */ #define NDPI_SERVICE_PANDORA 187 +#define NDPI_PROTOCOL_EAQ 190 +#define NDPI_SERVICE_MEU 191 +#define NDPI_SERVICE_TORCEDOR 192 +#define NDPI_SERVICE_KAKAOTALK 193 /* KakaoTalk Chat (no voice call) */ +#define NDPI_SERVICE_KAKAOTALK_VOICE 194 /* KakaoTalk Voice */ +#define NDPI_SERVICE_TWITCH 195 /* Edoardo Dominici <edoaramis@gmail.com> */ -/* UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE (NDPI_PROTOCOL_WHATSAPP_VOICE) */ -#define NDPI_LAST_IMPLEMENTED_PROTOCOL 189 +/* UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE */ +#define NDPI_LAST_IMPLEMENTED_PROTOCOL 195 #define NDPI_MAX_SUPPORTED_PROTOCOLS (NDPI_LAST_IMPLEMENTED_PROTOCOL + 1) #define NDPI_MAX_NUM_CUSTOM_PROTOCOLS (NDPI_NUM_BITS-NDPI_LAST_IMPLEMENTED_PROTOCOL) diff --git a/src/include/ndpi_protocols.h b/src/include/ndpi_protocols.h index 4fc0516d8..691118309 100644 --- a/src/include/ndpi_protocols.h +++ b/src/include/ndpi_protocols.h @@ -178,5 +178,7 @@ void ndpi_search_twitter(struct ndpi_detection_module_struct *ndpi_struct, struc void ndpi_search_vhua(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); void ndpi_search_telegram(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); void ndpi_search_quic(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); +void ndpi_search_eaq(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); +void ndpi_search_kakaotalk_voice(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); #endif /* __NDPI_PROTOCOLS_INCLUDE_FILE__ */ diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index a75b7c4cb..e4883d92e 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -373,23 +373,18 @@ struct ndpi_flow_tcp_struct { #ifdef NDPI_PROTOCOL_MAIL_IMAP u_int32_t mail_imap_stage:3; #endif - #ifdef NDPI_PROTOCOL_SKYPE u_int8_t skype_packet_id; #endif - #ifdef NDPI_PROTOCOL_CITRIX u_int8_t citrix_packet_id; #endif - #ifdef NDPI_PROTOCOL_LOTUS_NOTES u_int8_t lotus_notes_packet_id; #endif - #ifdef NDPI_PROTOCOL_TEAMVIEWER u_int8_t teamviewer_stage; #endif - #ifdef NDPI_PROTOCOL_ZMQ u_int8_t prev_zmq_pkt_len; u_char prev_zmq_pkt[10]; @@ -439,6 +434,10 @@ struct ndpi_flow_udp_struct { #ifdef NDPI_PROTOCOL_TEAMVIEWER u_int8_t teamviewer_stage; #endif +#ifdef NDPI_PROTOCOL_EAQ + u_int8_t eaq_pkt_id; + u_int32_t eaq_sequence; +#endif } #if !defined(WIN32) __attribute__ ((__packed__)) @@ -619,8 +618,10 @@ typedef struct ndpi_detection_module_struct { u_int ndpi_num_custom_protocols; /* HTTP/DNS/HTTPS host matching */ - ndpi_automa host_automa, content_automa, bigrams_automa, impossible_bigrams_automa; - + ndpi_automa host_automa, /* Used for DNS/HTTPS */ + content_automa, /* Used for HTTP subprotocol_detection */ + subprotocol_automa, /* Used for HTTP subprotocol_detection */ + bigrams_automa, impossible_bigrams_automa; /* TOR */ /* IP-based protocol detection */ void *protocols_ptree; diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 86aeb6c68..5cebcdff1 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -39,6 +39,7 @@ libndpi_la_SOURCES = ndpi_content_match.c.inc \ protocols/dns.c \ protocols/dofus.c \ protocols/dropbox.c \ + protocols/eaq.c \ protocols/edonkey.c \ protocols/fasttrack.c \ protocols/fiesta.c \ @@ -59,6 +60,7 @@ libndpi_la_SOURCES = ndpi_content_match.c.inc \ protocols/ipp.c \ protocols/irc.c \ protocols/jabber.c \ + protocols/kakaotalk_voice.c \ protocols/kerberos.c \ protocols/kontiki.c \ protocols/ldap.c \ diff --git a/src/lib/ndpi_content_match.c.inc b/src/lib/ndpi_content_match.c.inc index 1a75240a9..805984898 100644 --- a/src/lib/ndpi_content_match.c.inc +++ b/src/lib/ndpi_content_match.c.inc @@ -7214,6 +7214,74 @@ static ndpi_network host_protocol_list[] = { { 0xDF1273E5, 32, NDPI_PROTOCOL_TOR }, { 0xDF85F4CA, 32, NDPI_PROTOCOL_TOR }, { 0xDFE57B41, 32, NDPI_PROTOCOL_TOR }, + +/* + Twitch ingestion servers : + https://api.twitch.tv/kraken/ingests + Edoardo Dominici edoaramis@gmail.com +*/ +{ 0xB92ACC5D, 32, NDPI_SERVICE_TWITCH }, +{ 0xB92ACC92, 32, NDPI_SERVICE_TWITCH }, +{ 0xB92ACCA4, 32, NDPI_SERVICE_TWITCH }, +{ 0xB92ACCCD, 32, NDPI_SERVICE_TWITCH }, +{ 0xB92ACC30, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FE15, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FE19, 32, NDPI_SERVICE_TWITCH }, +{ 0xBCACD305, 32, NDPI_SERVICE_TWITCH }, +{ 0xC0104616, 32, NDPI_SERVICE_TWITCH }, +{ 0xC010461D, 32, NDPI_SERVICE_TWITCH }, +{ 0xC0104650, 32, NDPI_SERVICE_TWITCH }, +{ 0xC0104651, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FEA3, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FE87, 32, NDPI_SERVICE_TWITCH }, +{ 0xB92ACD85, 32, NDPI_SERVICE_TWITCH }, +{ 0xB92ACDA4, 32, NDPI_SERVICE_TWITCH }, +{ 0xC010419A, 32, NDPI_SERVICE_TWITCH }, +{ 0xC01041AD, 32, NDPI_SERVICE_TWITCH }, +{ 0xC0104172, 32, NDPI_SERVICE_TWITCH }, +{ 0xB92ACD68, 32, NDPI_SERVICE_TWITCH }, +{ 0xB92ACD55, 32, NDPI_SERVICE_TWITCH }, +{ 0xC0104219, 32, NDPI_SERVICE_TWITCH }, +{ 0xC010421A, 32, NDPI_SERVICE_TWITCH }, +{ 0xC010421B, 32, NDPI_SERVICE_TWITCH }, +{ 0xBCACD205, 32, NDPI_SERVICE_TWITCH }, +{ 0xBCACCB05, 32, NDPI_SERVICE_TWITCH }, +{ 0xC010413C, 32, NDPI_SERVICE_TWITCH }, +{ 0xC010413D, 32, NDPI_SERVICE_TWITCH }, +{ 0xC010413E, 32, NDPI_SERVICE_TWITCH }, +{ 0xBCACD105, 32, NDPI_SERVICE_TWITCH }, +{ 0xBCACD005, 32, NDPI_SERVICE_TWITCH }, +{ 0xBCACCA05, 32, NDPI_SERVICE_TWITCH }, +{ 0xB92ACD06, 32, NDPI_SERVICE_TWITCH }, +{ 0xB92ACD14, 32, NDPI_SERVICE_TWITCH }, +{ 0xB92ACCF3, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709F9C7, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709F9C9, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709F9CB, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FBA4, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FBA6, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FBAA, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FBB1, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FBE8, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FBE9, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FBEA, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FBEB, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FBFB, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FBFC, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FBFD, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FBFE, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FF4B, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709FF4C, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709F974, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709F976, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709F978, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709F97D, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709F985, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709F986, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709F987, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709F98C, 32, NDPI_SERVICE_TWITCH }, +{ 0xC709F9C5, 32, NDPI_SERVICE_TWITCH }, + { 0x0, 0, 0 } }; @@ -7295,6 +7363,12 @@ ndpi_protocol_match host_match[] = { { ".spotify.", "Spotify", NDPI_PROTOCOL_SPOTIFY, NDPI_PROTOCOL_FUN }, { ".pandora.com", "Pandora", NDPI_SERVICE_PANDORA, NDPI_PROTOCOL_FUN }, { ".torproject.org", "Tor", NDPI_PROTOCOL_TOR, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS }, + { "appmeutim.tim.com.br", "Meu", NDPI_SERVICE_MEU, NDPI_PROTOCOL_ACCEPTABLE }, + { ".timtorcedor.com.br", "Torcedor", NDPI_SERVICE_TORCEDOR, NDPI_PROTOCOL_ACCEPTABLE }, + { ".kakao.com", "KakaoTalk", NDPI_SERVICE_KAKAOTALK, NDPI_PROTOCOL_FUN }, + { "ttvnw.net", "Twitch", NDPI_SERVICE_TWITCH, NDPI_PROTOCOL_FUN }, + { "static-cdn.jtvnw.net", "Twitch", NDPI_SERVICE_TWITCH, NDPI_PROTOCOL_FUN }, + { "www-cdn.jtvnw.net", "Twitch", NDPI_SERVICE_TWITCH, NDPI_PROTOCOL_FUN }, { NULL, 0 } }; @@ -7339,6 +7413,7 @@ ndpi_protocol_match content_match[] = { { "audio/webm", NULL, NDPI_CONTENT_WEBM, NDPI_PROTOCOL_FUN }, { "video/webm", NULL, NDPI_CONTENT_WEBM, NDPI_PROTOCOL_FUN }, { "application/x-rtsp-tunnelled", NULL, NDPI_PROTOCOL_RTSP, NDPI_PROTOCOL_FUN }, + { "application/vnd.apple.mpegurl", NULL, NDPI_SERVICE_TWITCH, NDPI_PROTOCOL_FUN }, { NULL, 0 } }; diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index 5724b2522..a8d5dfc5f 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -1466,6 +1466,16 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp no_master, "Quic", ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 443, 80, 0, 0, 0) /* UDP */); + ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_EAQ, + no_master, + no_master, "EAQ", + ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, + ndpi_build_default_ports(ports_b, 6000, 0, 0, 0, 0) /* UDP */); + ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_SERVICE_KAKAOTALK_VOICE, + no_master, + no_master, "KakaoTalk_Voice", + ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, + ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); custom_master[0] = NDPI_PROTOCOL_HTTP, custom_master[1] = NDPI_PROTOCOL_UNKNOWN; custom_master1[0] = NDPI_PROTOCOL_DNS, custom_master1[1] = NDPI_PROTOCOL_UNKNOWN; @@ -3562,6 +3572,24 @@ void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *n ADD_TO_DETECTION_BITMASK); #endif +#ifdef NDPI_PROTOCOL_EAQ + ndpi_set_bitmask_protocol_detection("EAQ", ndpi_struct, detection_bitmask, a++, + NDPI_PROTOCOL_EAQ, + ndpi_search_eaq, + NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD, + SAVE_DETECTION_BITMASK_AS_UNKNOWN, + ADD_TO_DETECTION_BITMASK); +#endif + +#ifdef NDPI_SERVICE_KAKAOTALK_VOICE + ndpi_set_bitmask_protocol_detection("KakaoTalk_Voice", ndpi_struct, detection_bitmask, a++, + NDPI_SERVICE_KAKAOTALK_VOICE, + ndpi_search_kakaotalk_voice, + NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD, + SAVE_DETECTION_BITMASK_AS_UNKNOWN, + ADD_TO_DETECTION_BITMASK); +#endif + ndpi_struct->callback_buffer_size = a; NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG, diff --git a/src/lib/protocols/eaq.c b/src/lib/protocols/eaq.c new file mode 100644 index 000000000..1cdcc8f2b --- /dev/null +++ b/src/lib/protocols/eaq.c @@ -0,0 +1,73 @@ +/* + * eaq.c + * + * Copyright (C) 2015 - ntop.org + * + * This module is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This module is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License. + * If not, see <http://www.gnu.org/licenses/>. + * + */ + + +/* + EAQ: Entitade Aferidora da Qualidade de Banda Larga + + http://www.brasilbandalarga.com.br + */ +#include "ndpi_api.h" + +#define EAQ_DEFAULT_PORT 6000 +#define EAQ_DEFAULT_SIZE 16 + +#ifdef NDPI_PROTOCOL_EAQ +static void ndpi_int_eaq_add_connection(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_flow_struct *flow) { + ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_EAQ, NDPI_REAL_PROTOCOL); +} + + +void ndpi_search_eaq(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { + struct ndpi_packet_struct *packet = &flow->packet; + u_int16_t sport = ntohs(packet->udp->source), dport = ntohs(packet->udp->dest); + unsigned char *vers; + int ver_offs; + + if((packet->payload_packet_len != EAQ_DEFAULT_SIZE) + || ((sport != EAQ_DEFAULT_PORT) && (dport != EAQ_DEFAULT_PORT))) { + exclude_eaq: + NDPI_LOG(NDPI_PROTOCOL_EAQ, ndpi_struct, NDPI_LOG_DEBUG, "Exclude eaq.\n"); + NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_EAQ); + return; + } + + if(packet->udp != NULL) { + u_int32_t seq = (packet->payload[0] * 1000) + (packet->payload[1] * 100) + (packet->payload[2] * 10) + packet->payload[3]; + + if(flow->l4.udp.eaq_pkt_id == 0) + flow->l4.udp.eaq_sequence = seq; + else { + if((flow->l4.udp.eaq_sequence == seq) || ((flow->l4.udp.eaq_sequence+1) == seq)) { + ; /* Looks good */ + } else + goto exclude_eaq; + } + + if(++flow->l4.udp.eaq_pkt_id == 4) { + /* We have collected enough packets so we assume it's EAQ */ + NDPI_LOG(NDPI_PROTOCOL_EAQ, ndpi_struct, NDPI_LOG_DEBUG, "found eaq.\n"); + ndpi_int_eaq_add_connection(ndpi_struct, flow); + } + } else + goto exclude_eaq; +} +#endif diff --git a/src/lib/protocols/kakaotalk_voice.c b/src/lib/protocols/kakaotalk_voice.c new file mode 100644 index 000000000..dfda5c849 --- /dev/null +++ b/src/lib/protocols/kakaotalk_voice.c @@ -0,0 +1,59 @@ +/* + * kakaotalk_voice.c + * + * Copyright (C) 2015 - ntop.org + * + * This module is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This module is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License. + * If not, see <http://www.gnu.org/licenses/>. + * + */ + + +/* + KakaoTalk (call only) + + http://www.kakao.com/services/talk/voices +*/ +#include "ndpi_api.h" + + +#ifdef NDPI_SERVICE_KAKAOTALK_VOICE +void ndpi_search_kakaotalk_voice(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { + struct ndpi_packet_struct *packet = &flow->packet; + unsigned char *vers; + int ver_offs; + + if(packet->udp != NULL) { + if((packet->payload[0] == 0x81) + || (packet->payload[1] == 0xC8) + || (packet->payload[2] == 0x00) + || (packet->payload[3] == 0x0C)) { + /* Looks good so far */ + + /* + inetnum: 1.201.0.0 - 1.201.255.255 + netname: KINXINC-KR + */ + + if(((ntohl(packet->iph->saddr) & 0xFFFF0000 /* 255.255.0.0 */) == 0x01C90000 /* 1.201.0.0/16 */) + || ((ntohl(packet->iph->daddr) & 0xFFFF0000 /* 255.255.0.0 */) == 0x01C90000 /* 1.201.0.0/16 */)) { + ndpi_int_add_connection(ndpi_struct, flow, NDPI_SERVICE_KAKAOTALK_VOICE, NDPI_REAL_PROTOCOL); + return; + } + } + } + + NDPI_LOG(NDPI_PROTOCOL_KAKAOTALK_VOICE, ndpi_struct, NDPI_LOG_DEBUG, "Exclude kakaotalk_voice.\n"); + NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_SERVICE_KAKAOTALK_VOICE); +} +#endif diff --git a/src/lib/protocols/rtcp.c b/src/lib/protocols/rtcp.c index 02875648a..f618261dd 100644 --- a/src/lib/protocols/rtcp.c +++ b/src/lib/protocols/rtcp.c @@ -35,6 +35,19 @@ void ndpi_search_rtcp(struct ndpi_detection_module_struct *ndpi_struct, struct n ndpi_int_rtcp_add_connection(ndpi_struct, flow); } } else if(packet->udp != NULL) { + /* Let's check first the RTCP packet length */ + u_int16_t len, offset = 0, rtcp_section_len; + + while(offset < packet->payload_packet_len) { + len = packet->payload[2+offset] * 256 + packet->payload[2+offset+1]; + rtcp_section_len = (len + 1) * 4; + + if((offset+rtcp_section_len) > packet->payload_packet_len) + goto exclude_rtcp; + else + offset += rtcp_section_len; + } + sport = ntohs(packet->udp->source), dport = ntohs(packet->udp->dest); NDPI_LOG(NDPI_PROTOCOL_RTCP, ndpi_struct, NDPI_LOG_DEBUG, "calculating dport over udp.\n"); if(((packet->payload_packet_len >= 28 || packet->payload_packet_len <= 1200) && @@ -45,6 +58,8 @@ void ndpi_search_rtcp(struct ndpi_detection_module_struct *ndpi_struct, struct n ndpi_int_rtcp_add_connection(ndpi_struct, flow); } } else { + exclude_rtcp: + NDPI_LOG(NDPI_PROTOCOL_RTCP, ndpi_struct, NDPI_LOG_DEBUG, "exclude RTCP.\n"); NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_RTCP); } diff --git a/src/lib/protocols/ssl.c b/src/lib/protocols/ssl.c index c61c039c1..f4b70ed62 100644 --- a/src/lib/protocols/ssl.c +++ b/src/lib/protocols/ssl.c @@ -25,7 +25,7 @@ #include "ndpi_api.h" -// #define CERTIFICATE_DEBUG 1 +/* #define CERTIFICATE_DEBUG 1 */ #ifdef NDPI_PROTOCOL_SSL @@ -134,6 +134,14 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, char *buffer, int buffer_len) { struct ndpi_packet_struct *packet = &flow->packet; +#ifdef CERTIFICATE_DEBUG + { + static u_int8_t id = 0; + + printf("-> [%u] %02X\n", ++id, packet->payload[0] & 0xFF); + } +#endif + /* Nothing matched so far: let's decode the certificate with some heuristics Patches courtesy of Denys Fedoryshchenko <nuclearcat@nuclearcat.com> @@ -145,7 +153,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, memset(buffer, 0, buffer_len); /* Truncate total len, search at least in incomplete packet */ - if (total_len > packet->payload_packet_len) + if(total_len > packet->payload_packet_len) total_len = packet->payload_packet_len; /* At least "magic" 3 bytes, null for string end, otherwise no need to waste cpu cycles */ @@ -282,38 +290,41 @@ int sslDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_s if(!packet->iph /* IPv4 */) return(-1); - if((packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) - || (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL)) { - char certificate[64]; - int rc; + if((packet->payload_packet_len > 9) + && (packet->payload[0] == 0x16 /* consider only specific SSL packets (handshake) */)) { + if((packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) + || (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL)) { + char certificate[64]; + int rc; - certificate[0] = '\0'; - rc = getSSLcertificate(ndpi_struct, flow, certificate, sizeof(certificate)); - packet->ssl_certificate_num_checks++; + certificate[0] = '\0'; + rc = getSSLcertificate(ndpi_struct, flow, certificate, sizeof(certificate)); + packet->ssl_certificate_num_checks++; - if(rc > 0) { - packet->ssl_certificate_detected++; + if(rc > 0) { + packet->ssl_certificate_detected++; #ifdef CERTIFICATE_DEBUG - printf("***** [SSL] %s\n", certificate); + printf("***** [SSL] %s\n", certificate); #endif - if(ndpi_match_string_subprotocol(ndpi_struct, flow, certificate, strlen(certificate)) != NDPI_PROTOCOL_UNKNOWN) - return(rc); /* Fix courtesy of Gianluca Costa <g.costa@xplico.org> */ + if(ndpi_match_string_subprotocol(ndpi_struct, flow, certificate, strlen(certificate)) != NDPI_PROTOCOL_UNKNOWN) + return(rc); /* Fix courtesy of Gianluca Costa <g.costa@xplico.org> */ #ifdef NDPI_PROTOCOL_TOR - if(ndpi_is_ssl_tor(ndpi_struct, flow, certificate) != 0) - return(rc); + if(ndpi_is_ssl_tor(ndpi_struct, flow, certificate) != 0) + return(rc); #endif - } + } - if(((packet->ssl_certificate_num_checks >= 2) - && flow->l4.tcp.seen_syn - && flow->l4.tcp.seen_syn_ack - && flow->l4.tcp.seen_ack /* We have seen the 3-way handshake */) - || (flow->protos.ssl.server_certificate[0] != '\0') - || (flow->protos.ssl.client_certificate[0] != '\0') - ) - ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL); + if(((packet->ssl_certificate_num_checks >= 2) + && flow->l4.tcp.seen_syn + && flow->l4.tcp.seen_syn_ack + && flow->l4.tcp.seen_ack /* We have seen the 3-way handshake */) + || (flow->protos.ssl.server_certificate[0] != '\0') + || (flow->protos.ssl.client_certificate[0] != '\0') + ) + ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL); + } } return(0); @@ -330,11 +341,11 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct u_int32_t a; u_int32_t end; #if defined(NDPI_PROTOCOL_UNENCRYPED_JABBER) - if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_UNENCRYPED_JABBER) != 0) + if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_UNENCRYPED_JABBER) != 0) goto check_for_ssl_payload; #endif #if defined(NDPI_PROTOCOL_OSCAR) - if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_OSCAR) != 0) + if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_OSCAR) != 0) goto check_for_ssl_payload; #endif goto no_check_for_ssl_payload; @@ -343,10 +354,10 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct end = packet->payload_packet_len - 20; for (a = 5; a < end; a++) { #ifdef NDPI_PROTOCOL_UNENCRYPED_JABBER - if (packet->payload[a] == 't') { - if (memcmp(&packet->payload[a], "talk.google.com", 15) == 0) { + if(packet->payload[a] == 't') { + if(memcmp(&packet->payload[a], "talk.google.com", 15) == 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "ssl jabber packet match\n"); - if (NDPI_COMPARE_PROTOCOL_TO_BITMASK + if(NDPI_COMPARE_PROTOCOL_TO_BITMASK (ndpi_struct->detection_bitmask, NDPI_PROTOCOL_UNENCRYPED_JABBER) != 0) { ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_UNENCRYPED_JABBER); return; @@ -355,9 +366,9 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct } #endif #ifdef NDPI_PROTOCOL_OSCAR - if (packet->payload[a] == 'A' || packet->payload[a] == 'k' || packet->payload[a] == 'c' + if(packet->payload[a] == 'A' || packet->payload[a] == 'k' || packet->payload[a] == 'c' || packet->payload[a] == 'h') { - if (((a + 19) < packet->payload_packet_len && memcmp(&packet->payload[a], "America Online Inc.", 19) == 0) + if(((a + 19) < packet->payload_packet_len && memcmp(&packet->payload[a], "America Online Inc.", 19) == 0) // || (end - c > 3 memcmp (&packet->payload[c],"AOL", 3) == 0 ) // || (end - c > 7 && memcmp (&packet->payload[c], "AOL LLC", 7) == 0) || ((a + 15) < packet->payload_packet_len && memcmp(&packet->payload[a], "kdc.uas.aol.com", 15) == 0) @@ -370,7 +381,7 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct && memcmp(&packet->payload[a], "http://pki-info.aol.com/AOLMSPKI", 32) == 0)) { NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR SERVER SSL DETECTED\n"); - if (flow->dst != NULL && packet->payload_packet_len > 75) { + if(flow->dst != NULL && packet->payload_packet_len > 75) { memcpy(flow->dst->oscar_ssl_session_id, &packet->payload[44], 32); flow->dst->oscar_ssl_session_id[32] = '\0'; flow->dst->oscar_last_safe_access_time = packet->tick_timestamp; @@ -381,8 +392,8 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct } } - if (packet->payload[a] == 'm' || packet->payload[a] == 's') { - if ((a + 21) < packet->payload_packet_len && + if(packet->payload[a] == 'm' || packet->payload[a] == 's') { + if((a + 21) < packet->payload_packet_len && (memcmp(&packet->payload[a], "my.screenname.aol.com", 21) == 0 || memcmp(&packet->payload[a], "sns-static.aolcdn.com", 21) == 0)) { NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR SERVER SSL DETECTED\n"); @@ -418,7 +429,7 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct // struct ndpi_id_struct *dst=flow->dst; - if ((packet->payload_packet_len >= 5) + if((packet->payload_packet_len >= 5) && (packet->payload[0] == 0x16) && (packet->payload[1] == 0x03) && ((packet->payload[2] == 0x00) @@ -429,17 +440,17 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct u_int32_t temp; NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "search sslv3\n"); // SSLv3 Record - if (packet->payload_packet_len >= 1300) { + if(packet->payload_packet_len >= 1300) { return 1; } temp = ntohs(get_u_int16_t(packet->payload, 3)) + 5; NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "temp = %u.\n", temp); - if (packet->payload_packet_len == temp + if(packet->payload_packet_len == temp || (temp < packet->payload_packet_len && packet->payload_packet_len > 500)) { return 1; } - if (packet->payload_packet_len < temp && temp < 5000 && packet->payload_packet_len > 9) { + if(packet->payload_packet_len < temp && temp < 5000 && packet->payload_packet_len > 9) { /* the server hello may be split into small packets */ u_int32_t cert_start; @@ -451,14 +462,14 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "suspected start of certificate: %u\n", cert_start); - if (cert_start < packet->payload_packet_len && packet->payload[cert_start] == 0x0b) { + if(cert_start < packet->payload_packet_len && packet->payload[cert_start] == 0x0b) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "found 0x0b at suspected start of certificate block\n"); return 2; } } - if ((packet->payload_packet_len > temp && packet->payload_packet_len > 100) && packet->payload_packet_len > 9) { + if((packet->payload_packet_len > temp && packet->payload_packet_len > 100) && packet->payload_packet_len > 9) { /* the server hello may be split into small packets and the certificate has its own SSL Record * so temp contains only the length for the first ServerHello block */ u_int32_t cert_start; @@ -471,7 +482,7 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "suspected start of certificate: %u\n", cert_start); - if (cert_start < packet->payload_packet_len && packet->payload[cert_start] == 0x0b) { + if(cert_start < packet->payload_packet_len && packet->payload[cert_start] == 0x0b) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "found 0x0b at suspected start of certificate block\n"); return 2; @@ -479,49 +490,45 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct } - if (packet->payload_packet_len >= temp + 5 && (packet->payload[temp] == 0x14 || packet->payload[temp] == 0x16) + if(packet->payload_packet_len >= temp + 5 && (packet->payload[temp] == 0x14 || packet->payload[temp] == 0x16) && packet->payload[temp + 1] == 0x03) { u_int32_t temp2 = ntohs(get_u_int16_t(packet->payload, temp + 3)) + 5; - if (temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) { + if(temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) { return 1; } temp += temp2; NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "temp = %u.\n", temp); - if (packet->payload_packet_len == temp) { + if(packet->payload_packet_len == temp) { return 1; } - if (packet->payload_packet_len >= temp + 5 && + if(packet->payload_packet_len >= temp + 5 && packet->payload[temp] == 0x16 && packet->payload[temp + 1] == 0x03) { temp2 = ntohs(get_u_int16_t(packet->payload, temp + 3)) + 5; - if (temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) { + if(temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) { return 1; } temp += temp2; NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "temp = %u.\n", temp); - if (packet->payload_packet_len == temp) { + if(packet->payload_packet_len == temp) { return 1; } - if (packet->payload_packet_len >= temp + 5 && + if(packet->payload_packet_len >= temp + 5 && packet->payload[temp] == 0x16 && packet->payload[temp + 1] == 0x03) { temp2 = ntohs(get_u_int16_t(packet->payload, temp + 3)) + 5; - if (temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) { + if(temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) { return 1; } temp += temp2; NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "temp = %u.\n", temp); - if (temp == packet->payload_packet_len) { + if(temp == packet->payload_packet_len) { return 1; } } - } - - } - } - return 0; + return 0; } void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) @@ -533,15 +540,15 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc u_int8_t ret; - if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) { - if (flow->l4.tcp.ssl_stage == 3 && packet->payload_packet_len > 20 && flow->packet_counter < 5) { + if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) { + if(flow->l4.tcp.ssl_stage == 3 && packet->payload_packet_len > 20 && flow->packet_counter < 5) { /* this should only happen, when we detected SSL with a packet that had parts of the certificate in subsequent packets * so go on checking for certificate patterns for a couple more packets */ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "ssl flow but check another packet for patterns\n"); ssl_mark_and_payload_search_for_other_protocols(ndpi_struct, flow); - if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) { + if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) { /* still ssl so check another packet */ return; } else { @@ -571,10 +578,10 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc } } - if (packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 0) { + if(packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 0) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "first ssl packet\n"); // SSLv2 Record - if (packet->payload[2] == 0x01 && packet->payload[3] == 0x03 + if(packet->payload[2] == 0x01 && packet->payload[3] == 0x03 && (packet->payload[4] == 0x00 || packet->payload[4] == 0x01 || packet->payload[4] == 0x02) && (packet->payload_packet_len - packet->payload[1] == 2)) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "sslv2 len match\n"); @@ -582,7 +589,7 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc return; } - if (packet->payload[0] == 0x16 && packet->payload[1] == 0x03 + if(packet->payload[0] == 0x16 && packet->payload[1] == 0x03 && (packet->payload[2] == 0x00 || packet->payload[2] == 0x01 || packet->payload[2] == 0x02) && (packet->payload_packet_len - ntohs(get_u_int16_t(packet->payload, 3)) == 5)) { // SSLv3 Record @@ -592,16 +599,16 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc } } - if (packet->payload_packet_len > 40 && + if(packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 1 + packet->packet_direction && flow->packet_direction_counter[packet->packet_direction] < 5) { return; } - if (packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 2 - packet->packet_direction) { + if(packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 2 - packet->packet_direction) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "second ssl packet\n"); // SSLv2 Record - if (packet->payload[2] == 0x01 && packet->payload[3] == 0x03 + if(packet->payload[2] == 0x01 && packet->payload[3] == 0x03 && (packet->payload[4] == 0x00 || packet->payload[4] == 0x01 || packet->payload[4] == 0x02) && (packet->payload_packet_len - 2) >= packet->payload[1]) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "sslv2 server len match\n"); @@ -610,21 +617,21 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc } ret = ndpi_search_sslv3_direction1(ndpi_struct, flow); - if (ret == 1) { + if(ret == 1) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "sslv3 server len match\n"); ssl_mark_and_payload_search_for_other_protocols(ndpi_struct, flow); return; - } else if (ret == 2) { + } else if(ret == 2) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "sslv3 server len match with split packet -> check some more packets for SSL patterns\n"); ssl_mark_and_payload_search_for_other_protocols(ndpi_struct, flow); - if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) { + if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) { flow->l4.tcp.ssl_stage = 3; } return; } - if (packet->payload_packet_len > 40 && flow->packet_direction_counter[packet->packet_direction] < 5) { + if(packet->payload_packet_len > 40 && flow->packet_direction_counter[packet->packet_direction] < 5) { NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "need next packet\n"); return; } |