diff options
Diffstat (limited to 'src/lib/protocols')
-rw-r--r-- | src/lib/protocols/bittorrent.c | 243 | ||||
-rw-r--r-- | src/lib/protocols/dhcp.c | 30 | ||||
-rw-r--r-- | src/lib/protocols/dns.c | 61 | ||||
-rw-r--r-- | src/lib/protocols/http.c | 29 | ||||
-rw-r--r-- | src/lib/protocols/sip.c | 10 | ||||
-rw-r--r-- | src/lib/protocols/socks4.c | 96 | ||||
-rw-r--r-- | src/lib/protocols/socks45.c | 155 | ||||
-rw-r--r-- | src/lib/protocols/socks5.c | 92 | ||||
-rw-r--r-- | src/lib/protocols/ssl.c | 42 | ||||
-rw-r--r-- | src/lib/protocols/stun.c | 16 | ||||
-rw-r--r-- | src/lib/protocols/tcp_udp.c | 10 | ||||
-rw-r--r-- | src/lib/protocols/tor.c | 2 | ||||
-rw-r--r-- | src/lib/protocols/veohtv.c | 130 |
13 files changed, 395 insertions, 521 deletions
diff --git a/src/lib/protocols/bittorrent.c b/src/lib/protocols/bittorrent.c index 99420b85e..8213d3b45 100644 --- a/src/lib/protocols/bittorrent.c +++ b/src/lib/protocols/bittorrent.c @@ -25,15 +25,53 @@ #include "ndpi_protocols.h" #ifdef NDPI_PROTOCOL_BITTORRENT -#define NDPI_PROTOCOL_UNSAFE_DETECTION 0 -#define NDPI_PROTOCOL_SAFE_DETECTION 1 +#define NDPI_PROTOCOL_UNSAFE_DETECTION 0 +#define NDPI_PROTOCOL_SAFE_DETECTION 1 + +#define NDPI_PROTOCOL_PLAIN_DETECTION 0 +#define NDPI_PROTOCOL_WEBSEED_DETECTION 2 + + +struct ndpi_utp_hdr { + u_int8_t h_version:4, h_type:4, next_extension; + u_int16_t connection_id; + u_int32_t ts_usec, tdiff_usec, window_size; + u_int16_t sequence_nr, ack_nr; +}; + +static u_int8_t is_utp_pkt(const u_int8_t *payload, u_int payload_len) { + struct ndpi_utp_hdr *h = (struct ndpi_utp_hdr*)payload; + + if(payload_len < sizeof(struct ndpi_utp_hdr)) return(0); + if(h->h_version != 1) return(0); + if(h->h_type > 4) return(0); + if(h->next_extension > 2) return(0); + if(ntohl(h->window_size) > 65565) return(0); + + return(1); +} -#define NDPI_PROTOCOL_PLAIN_DETECTION 0 -#define NDPI_PROTOCOL_WEBSEED_DETECTION 2 static void ndpi_add_connection_as_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, + int bt_offset, int check_hash, const u_int8_t save_detection, const u_int8_t encrypted_connection/* , */ /* ndpi_protocol_type_t protocol_type */) { + if(check_hash) { + const char *bt_hash = NULL; /* 20 bytes long */ + const char *peer_id = NULL; /* 20 bytes long */ + + if(bt_offset == -1) { + const char *bt_magic = ndpi_strnstr((const char *)flow->packet.payload, + "BitTorrent protocol", flow->packet.payload_packet_len); + + if(bt_magic) + bt_hash = &bt_magic[19], peer_id = &bt_magic[39]; + } else + bt_hash = (const char*)&flow->packet.payload[28], peer_id = (const char*)&flow->packet.payload[48]; + + if(bt_hash) memcpy(flow->bittorent_hash, bt_hash, 20); + } + ndpi_int_change_protocol(ndpi_struct, flow, NDPI_PROTOCOL_BITTORRENT, NDPI_PROTOCOL_UNKNOWN); } @@ -43,61 +81,57 @@ static u_int8_t ndpi_int_search_bittorrent_tcp_zero(struct ndpi_detection_module struct ndpi_packet_struct *packet = &flow->packet; u_int16_t a = 0; - if (packet->payload_packet_len == 1 && packet->payload[0] == 0x13) { + if(packet->payload_packet_len == 1 && packet->payload[0] == 0x13) { /* reset stage back to 0 so we will see the next packet here too */ flow->bittorrent_stage = 0; return 0; } - if (flow->packet_counter == 2 && packet->payload_packet_len > 20) { - if (memcmp(&packet->payload[0], "BitTorrent protocol", 19) == 0) { + if(flow->packet_counter == 2 && packet->payload_packet_len > 20) { + if(memcmp(&packet->payload[0], "BitTorrent protocol", 19) == 0) { NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "BT: plain BitTorrent protocol detected\n"); - ndpi_add_connection_as_bittorrent(ndpi_struct, flow, + ndpi_add_connection_as_bittorrent(ndpi_struct, flow, 19, 1, NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION/* , */ /* NDPI_REAL_PROTOCOL */); return 1; } } - - if (packet->payload_packet_len > 20) { + if(packet->payload_packet_len > 20) { /* test for match 0x13+"BitTorrent protocol" */ - if (packet->payload[0] == 0x13) { - if (memcmp(&packet->payload[1], "BitTorrent protocol", 19) == 0) { - NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, - ndpi_struct, NDPI_LOG_TRACE, "BT: plain BitTorrent protocol detected\n"); - ndpi_add_connection_as_bittorrent(ndpi_struct, flow, - NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION/* , */ - /* NDPI_REAL_PROTOCOL */); + if(packet->payload[0] == 0x13) { + if(memcmp(&packet->payload[1], "BitTorrent protocol", 19) == 0) { + NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "BT: plain BitTorrent protocol detected\n"); + ndpi_add_connection_as_bittorrent(ndpi_struct, flow, 20, 1, + NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); return 1; } } } - if (packet->payload_packet_len > 23 && memcmp(packet->payload, "GET /webseed?info_hash=", 23) == 0) { + if(packet->payload_packet_len > 23 && memcmp(packet->payload, "GET /webseed?info_hash=", 23) == 0) { NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "BT: plain webseed BitTorrent protocol detected\n"); - ndpi_add_connection_as_bittorrent(ndpi_struct, flow, - NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION/* , */ - /* NDPI_CORRELATED_PROTOCOL */); + ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, + NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION); return 1; } /* seen Azureus as server for webseed, possibly other servers existing, to implement */ /* is Server: hypertracker Bittorrent? */ /* no asymmetric detection possible for answer of pattern "GET /data?fid=". */ - if (packet->payload_packet_len > 60 + if(packet->payload_packet_len > 60 && memcmp(packet->payload, "GET /data?fid=", 14) == 0 && memcmp(&packet->payload[54], "&size=", 6) == 0) { NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "BT: plain Bitcomet persistent seed protocol detected\n"); - ndpi_add_connection_as_bittorrent(ndpi_struct, flow, + ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION/* , */ /* NDPI_CORRELATED_PROTOCOL */); return 1; } - if (packet->payload_packet_len > 90 && (memcmp(packet->payload, "GET ", 4) == 0 + if(packet->payload_packet_len > 90 && (memcmp(packet->payload, "GET ", 4) == 0 || memcmp(packet->payload, "POST ", 5) == 0)) { const u_int8_t *ptr = &packet->payload[4]; u_int16_t len = packet->payload_packet_len - 4; @@ -107,32 +141,30 @@ static u_int8_t ndpi_int_search_bittorrent_tcp_zero(struct ndpi_detection_module /* parse complete get packet here into line structure elements */ ndpi_parse_packet_line_info(ndpi_struct, flow); /* answer to this pattern is HTTP....Server: hypertracker */ - if (packet->user_agent_line.ptr != NULL + if(packet->user_agent_line.ptr != NULL && ((packet->user_agent_line.len > 8 && memcmp(packet->user_agent_line.ptr, "Azureus ", 8) == 0) || (packet->user_agent_line.len >= 10 && memcmp(packet->user_agent_line.ptr, "BitTorrent", 10) == 0) || (packet->user_agent_line.len >= 11 && memcmp(packet->user_agent_line.ptr, "BTWebClient", 11) == 0))) { NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "Azureus /Bittorrent user agent line detected\n"); - ndpi_add_connection_as_bittorrent(ndpi_struct, flow, - NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION/* , */ - /* NDPI_CORRELATED_PROTOCOL */); + ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, + NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION); return 1; } - if (packet->user_agent_line.ptr != NULL - && (packet->user_agent_line.len >= 9 && memcmp(packet->user_agent_line.ptr, "Shareaza ", 9) == 0) - && (packet->parsed_lines > 8 && packet->line[8].ptr != 0 - && packet->line[8].len >= 9 && memcmp(packet->line[8].ptr, "X-Queue: ", 9) == 0)) { + if(packet->user_agent_line.ptr != NULL + && (packet->user_agent_line.len >= 9 && memcmp(packet->user_agent_line.ptr, "Shareaza ", 9) == 0) + && (packet->parsed_lines > 8 && packet->line[8].ptr != 0 + && packet->line[8].len >= 9 && memcmp(packet->line[8].ptr, "X-Queue: ", 9) == 0)) { NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "Bittorrent Shareaza detected.\n"); - ndpi_add_connection_as_bittorrent(ndpi_struct, flow, - NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION/* , */ - /* NDPI_CORRELATED_PROTOCOL */); + ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, + NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION); return 1; } /* this is a self built client, not possible to catch asymmetrically */ - if ((packet->parsed_lines == 10 || (packet->parsed_lines == 11 && packet->line[11].len == 0)) + if((packet->parsed_lines == 10 || (packet->parsed_lines == 11 && packet->line[11].len == 0)) && packet->user_agent_line.ptr != NULL && packet->user_agent_line.len > 12 && memcmp(packet->user_agent_line.ptr, "Mozilla/4.0 ", @@ -160,15 +192,13 @@ static u_int8_t ndpi_int_search_bittorrent_tcp_zero(struct ndpi_detection_module && packet->line[8].len > 22 && memcmp(packet->line[8].ptr, "Cache-Control: no-cache", 23) == 0) { NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "Bitcomet LTS detected\n"); - ndpi_add_connection_as_bittorrent(ndpi_struct, flow, - NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION/* , */ - /* NDPI_CORRELATED_PROTOCOL */); + ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, + NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); return 1; - } /* FlashGet pattern */ - if (packet->parsed_lines == 8 + if(packet->parsed_lines == 8 && packet->user_agent_line.ptr != NULL && packet->user_agent_line.len > (sizeof("Mozilla/4.0 (compatible; MSIE 6.0;") - 1) && memcmp(packet->user_agent_line.ptr, "Mozilla/4.0 (compatible; MSIE 6.0;", @@ -187,13 +217,12 @@ static u_int8_t ndpi_int_search_bittorrent_tcp_zero(struct ndpi_detection_module && packet->line[6].len > 21 && memcmp(packet->line[6].ptr, "Connection: Keep-Alive", 22) == 0) { NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "FlashGet detected\n"); - ndpi_add_connection_as_bittorrent(ndpi_struct, flow, - NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION/* , */ - /* NDPI_CORRELATED_PROTOCOL */); + ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, + NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); return 1; - } - if (packet->parsed_lines == 7 + + if(packet->parsed_lines == 7 && packet->user_agent_line.ptr != NULL && packet->user_agent_line.len > (sizeof("Mozilla/4.0 (compatible; MSIE 6.0;") - 1) && memcmp(packet->user_agent_line.ptr, "Mozilla/4.0 (compatible; MSIE 6.0;", @@ -209,19 +238,17 @@ static u_int8_t ndpi_int_search_bittorrent_tcp_zero(struct ndpi_detection_module && packet->line[5].len > 21 && memcmp(packet->line[5].ptr, "Connection: Keep-Alive", 22) == 0) { NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "FlashGet detected\n"); - ndpi_add_connection_as_bittorrent(ndpi_struct, flow, - NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION/* , */ - /* NDPI_CORRELATED_PROTOCOL */); + ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, + NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); return 1; - } /* answer to this pattern is not possible to implement asymmetrically */ while (1) { - if (len < 50 || ptr[0] == 0x0d) { + if(len < 50 || ptr[0] == 0x0d) { goto ndpi_end_bt_tracker_check; } - if (memcmp(ptr, "info_hash=", 10) == 0) { + if(memcmp(ptr, "info_hash=", 10) == 0) { break; } len--; @@ -237,40 +264,40 @@ static u_int8_t ndpi_int_search_bittorrent_tcp_zero(struct ndpi_detection_module /* parse bt hash */ for (a = 0; a < 20; a++) { - if (len < 3) { + if(len < 3) { goto ndpi_end_bt_tracker_check; } - if (*ptr == '%') { + if(*ptr == '%') { u_int8_t x1 = 0xFF; u_int8_t x2 = 0xFF; - if (ptr[1] >= '0' && ptr[1] <= '9') { + if(ptr[1] >= '0' && ptr[1] <= '9') { x1 = ptr[1] - '0'; } - if (ptr[1] >= 'a' && ptr[1] <= 'f') { + if(ptr[1] >= 'a' && ptr[1] <= 'f') { x1 = 10 + ptr[1] - 'a'; } - if (ptr[1] >= 'A' && ptr[1] <= 'F') { + if(ptr[1] >= 'A' && ptr[1] <= 'F') { x1 = 10 + ptr[1] - 'A'; } - if (ptr[2] >= '0' && ptr[2] <= '9') { + if(ptr[2] >= '0' && ptr[2] <= '9') { x2 = ptr[2] - '0'; } - if (ptr[2] >= 'a' && ptr[2] <= 'f') { + if(ptr[2] >= 'a' && ptr[2] <= 'f') { x2 = 10 + ptr[2] - 'a'; } - if (ptr[2] >= 'A' && ptr[2] <= 'F') { + if(ptr[2] >= 'A' && ptr[2] <= 'F') { x2 = 10 + ptr[2] - 'A'; } - if (x1 == 0xFF || x2 == 0xFF) { + if(x1 == 0xFF || x2 == 0xFF) { goto ndpi_end_bt_tracker_check; } ptr += 3; len -= 3; - } else if (*ptr >= 32 && *ptr < 127) { + } else if(*ptr >= 32 && *ptr < 127) { ptr++; len--; } else { @@ -280,15 +307,14 @@ static u_int8_t ndpi_int_search_bittorrent_tcp_zero(struct ndpi_detection_module NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, " BT stat: tracker info hash parsed\n"); - ndpi_add_connection_as_bittorrent(ndpi_struct, flow, - NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION/* , */ - /* NDPI_CORRELATED_PROTOCOL */); + ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, + NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); return 1; } ndpi_end_bt_tracker_check: - if (packet->payload_packet_len == 80) { + if(packet->payload_packet_len == 80) { /* Warez 80 Bytes Packet * +----------------+---------------+-----------------+-----------------+ * |20 BytesPattern | 32 Bytes Value| 12 BytesPattern | 16 Bytes Data | @@ -306,30 +332,28 @@ static u_int8_t ndpi_int_search_bittorrent_tcp_zero(struct ndpi_detection_module }; /* did not see this pattern anywhere */ - if ((memcmp(&packet->payload[0], pattern_20_bytes, 20) == 0) + if((memcmp(&packet->payload[0], pattern_20_bytes, 20) == 0) && (memcmp(&packet->payload[52], pattern_12_bytes, 12) == 0)) { NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "BT: Warez - Plain BitTorrent protocol detected\n"); - ndpi_add_connection_as_bittorrent(ndpi_struct, flow, - NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION/* , */ - /* NDPI_REAL_PROTOCOL */); + ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, + NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); return 1; } } - else if (packet->payload_packet_len > 50) { - if (memcmp(packet->payload, "GET", 3) == 0) { + else if(packet->payload_packet_len > 50) { + if(memcmp(packet->payload, "GET", 3) == 0) { ndpi_parse_packet_line_info(ndpi_struct, flow); /* haven't fount this pattern anywhere */ - if (packet->host_line.ptr != NULL + if(packet->host_line.ptr != NULL && packet->host_line.len >= 9 && memcmp(packet->host_line.ptr, "ip2p.com:", 9) == 0) { NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "BT: Warez - Plain BitTorrent protocol detected due to Host: ip2p.com: pattern\n"); - ndpi_add_connection_as_bittorrent(ndpi_struct, flow, - NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION/* , */ - /* NDPI_CORRELATED_PROTOCOL */); + ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, + NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION); return 1; } } @@ -341,17 +365,16 @@ static u_int8_t ndpi_int_search_bittorrent_tcp_zero(struct ndpi_detection_module /*Search for BitTorrent commands*/ static void ndpi_int_search_bittorrent_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { - struct ndpi_packet_struct *packet = &flow->packet; - if (packet->payload_packet_len == 0) { + if(packet->payload_packet_len == 0) { return; } - if (flow->bittorrent_stage == 0 && packet->payload_packet_len != 0) { + if(flow->bittorrent_stage == 0 && packet->payload_packet_len != 0) { /* exclude stage 0 detection from next run */ flow->bittorrent_stage = 1; - if (ndpi_int_search_bittorrent_tcp_zero(ndpi_struct, flow) != 0) { + if(ndpi_int_search_bittorrent_tcp_zero(ndpi_struct, flow) != 0) { NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_DEBUG, "stage 0 has detected something, returning\n"); return; @@ -367,6 +390,7 @@ void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, st { struct ndpi_packet_struct *packet = &flow->packet; int no_bittorrent = 0; + char *bt_proto = NULL; /* This is broadcast */ if(packet->iph @@ -378,10 +402,10 @@ void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, st return; } - if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_BITTORRENT) { + if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_BITTORRENT) { /* check for tcp retransmission here */ - if ((packet->tcp != NULL) + if((packet->tcp != NULL) && (packet->tcp_retransmission == 0 || packet->num_retried_bytes)) { ndpi_int_search_bittorrent_tcp(ndpi_struct, flow); } @@ -400,9 +424,8 @@ void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, st if(packet->payload_packet_len >= 23 /* min header size */) { if(strncmp((const char*)packet->payload, bt_search, strlen(bt_search)) == 0) { - ndpi_add_connection_as_bittorrent(ndpi_struct, flow, - NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION/* , */ - /* NDPI_REAL_PROTOCOL */); + ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 1, + NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); return; } else { /* Check if this is protocol v0 */ @@ -414,27 +437,31 @@ void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, st u_int8_t v1_extension = packet->payload[1]; u_int32_t v1_window_size = *((u_int32_t*)&packet->payload[12]); - if((packet->payload[0]== 0x60) + if(is_utp_pkt(packet->payload, packet->payload_packet_len)) + goto bittorrent_found; + else if((packet->payload[0]== 0x60) && (packet->payload[1]== 0x0) && (packet->payload[2]== 0x0) && (packet->payload[3]== 0x0) && (packet->payload[4]== 0x0)) { /* Heuristic */ + bt_proto = ndpi_strnstr((const char *)&packet->payload[20], "BitTorrent protocol", packet->payload_packet_len-20); goto bittorrent_found; } else if(((v1_version & 0x0f) == 1) && ((v1_version >> 4) < 5 /* ST_NUM_STATES */) && (v1_extension < 3 /* EXT_NUM_EXT */) && (v1_window_size < 32768 /* 32k */) ) { + bt_proto = ndpi_strnstr((const char *)&packet->payload[20], "BitTorrent protocol", packet->payload_packet_len-20); goto bittorrent_found; - } else if((v0_flags < 6 /* ST_NUM_STATES */) - && (v0_extension < 3 /* EXT_NUM_EXT */)) { + } else if((v0_flags < 6 /* ST_NUM_STATES */) && (v0_extension < 3 /* EXT_NUM_EXT */)) { u_int32_t ts = ntohl(*((u_int32_t*)&(packet->payload[4]))); u_int32_t now; now = (u_int32_t)time(NULL); if((ts < (now+86400)) && (ts > (now-86400))) { + bt_proto = ndpi_strnstr((const char *)&packet->payload[20], "BitTorrent protocol", packet->payload_packet_len-20); goto bittorrent_found; } } @@ -444,24 +471,28 @@ void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, st flow->bittorrent_stage++; if(flow->bittorrent_stage < 10) { - if(packet->payload_packet_len > 19 /* min size */) { - if(ndpi_strnstr((const char *)packet->payload, ":target20:", packet->payload_packet_len) - || ndpi_strnstr((const char *)packet->payload, ":find_node1:", packet->payload_packet_len) - || ndpi_strnstr((const char *)packet->payload, "d1:ad2:id20:", packet->payload_packet_len) - || ndpi_strnstr((const char *)packet->payload, ":info_hash20:", packet->payload_packet_len) - || ndpi_strnstr((const char *)packet->payload, ":filter64", packet->payload_packet_len) - || ndpi_strnstr((const char *)packet->payload, "d1:rd2:id20:", packet->payload_packet_len) - || ndpi_strnstr((const char *)packet->payload, "BitTorrent protocol", packet->payload_packet_len) - ) { - bittorrent_found: - NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, - ndpi_struct, NDPI_LOG_TRACE, "BT: plain BitTorrent protocol detected\n"); - ndpi_add_connection_as_bittorrent(ndpi_struct, flow, - NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION/* , */ - /* NDPI_REAL_PROTOCOL */); - return; - } - } + /* We have detected bittorrent but we need to wait until we get a hash */ + + if(packet->payload_packet_len > 19 /* min size */) { + if(ndpi_strnstr((const char *)packet->payload, ":target20:", packet->payload_packet_len) + || ndpi_strnstr((const char *)packet->payload, ":find_node1:", packet->payload_packet_len) + || ndpi_strnstr((const char *)packet->payload, "d1:ad2:id20:", packet->payload_packet_len) + || ndpi_strnstr((const char *)packet->payload, ":info_hash20:", packet->payload_packet_len) + || ndpi_strnstr((const char *)packet->payload, ":filter64", packet->payload_packet_len) + || ndpi_strnstr((const char *)packet->payload, "d1:rd2:id20:", packet->payload_packet_len) + || (bt_proto = ndpi_strnstr((const char *)packet->payload, "BitTorrent protocol", packet->payload_packet_len)) + ) { + bittorrent_found: + if(bt_proto && (packet->payload_packet_len > 47)) + memcpy(flow->bittorent_hash, &bt_proto[27], 20); + + NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, + ndpi_struct, NDPI_LOG_TRACE, "BT: plain BitTorrent protocol detected\n"); + ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 0, + NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION); + return; + } + } return; } diff --git a/src/lib/protocols/dhcp.c b/src/lib/protocols/dhcp.c index cb78c9429..8ffc04d51 100644 --- a/src/lib/protocols/dhcp.c +++ b/src/lib/protocols/dhcp.c @@ -35,27 +35,27 @@ static void ndpi_int_dhcp_add_connection(struct ndpi_detection_module_struct *nd void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { - struct ndpi_packet_struct *packet = &flow->packet; + struct ndpi_packet_struct *packet = &flow->packet; -// struct ndpi_id_struct *src=ndpi_struct->src; -// struct ndpi_id_struct *dst=ndpi_struct->dst; + // struct ndpi_id_struct *src=ndpi_struct->src; + // struct ndpi_id_struct *dst=ndpi_struct->dst; - /* this detection also works for asymmetric dhcp traffic */ + /* this detection also works for asymmetric dhcp traffic */ - /*check standard DHCP 0.0.0.0:68 -> 255.255.255.255:67 */ - if (packet->payload_packet_len >= 244 && (packet->udp->source == htons(67) - || packet->udp->source == htons(68)) - && (packet->udp->dest == htons(67) || packet->udp->dest == htons(68)) - && get_u_int32_t(packet->payload, 236) == htonl(0x63825363) - && get_u_int16_t(packet->payload, 240) == htons(0x3501)) { + /*check standard DHCP 0.0.0.0:68 -> 255.255.255.255:67 */ + if (packet->payload_packet_len >= 244 && (packet->udp->source == htons(67) + || packet->udp->source == htons(68)) + && (packet->udp->dest == htons(67) || packet->udp->dest == htons(68)) + && get_u_int32_t(packet->payload, 236) == htonl(0x63825363) + && get_u_int16_t(packet->payload, 240) == htons(0x3501)) { - NDPI_LOG(NDPI_PROTOCOL_DHCP, ndpi_struct, NDPI_LOG_DEBUG, "DHCP request\n"); + NDPI_LOG(NDPI_PROTOCOL_DHCP, ndpi_struct, NDPI_LOG_DEBUG, "DHCP request\n"); - ndpi_int_dhcp_add_connection(ndpi_struct, flow); - return; - } + ndpi_int_dhcp_add_connection(ndpi_struct, flow); + return; + } - NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DHCP); + NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DHCP); } diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c index 8749f4d5e..c975465ea 100644 --- a/src/lib/protocols/dns.c +++ b/src/lib/protocols/dns.c @@ -60,43 +60,46 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd if((s_port == 53 || d_port == 53 || d_port == 5355) && (flow->packet.payload_packet_len > sizeof(struct ndpi_dns_packet_header))) { - struct ndpi_dns_packet_header *dns_header = (struct ndpi_dns_packet_header*) &flow->packet.payload[x]; + struct ndpi_dns_packet_header dns_header; int invalid = 0; - dns_header->tr_id = ntohs(dns_header->tr_id); - dns_header->flags = ntohs(dns_header->flags); - dns_header->num_queries = ntohs(dns_header->num_queries); - dns_header->num_answers = ntohs(dns_header->num_answers); - dns_header->authority_rrs = ntohs(dns_header->authority_rrs); - dns_header->additional_rrs = ntohs(dns_header->additional_rrs); + memcpy(&dns_header, (struct ndpi_dns_packet_header*) &flow->packet.payload[x], sizeof(struct ndpi_dns_packet_header)); + dns_header.tr_id = ntohs(dns_header.tr_id); + dns_header.flags = ntohs(dns_header.flags); + dns_header.num_queries = ntohs(dns_header.num_queries); + dns_header.num_answers = ntohs(dns_header.num_answers); + dns_header.authority_rrs = ntohs(dns_header.authority_rrs); + dns_header.additional_rrs = ntohs(dns_header.additional_rrs); /* 0x0000 QUERY */ - if((dns_header->flags & FLAGS_MASK) == 0x0000) + if((dns_header.flags & FLAGS_MASK) == 0x0000) is_query = 1; /* 0x8000 RESPONSE */ - else if((dns_header->flags & FLAGS_MASK) != 0x8000) + else if((dns_header.flags & FLAGS_MASK) != 0x8000) is_query = 0; else invalid = 1; - if(is_query) { - /* DNS Request */ - if((dns_header->num_queries > 0) && (dns_header->num_queries <= NDPI_MAX_DNS_REQUESTS) - && (((dns_header->flags & 0x2800) == 0x2800 /* Dynamic DNS Update */) - || ((dns_header->num_answers == 0) && (dns_header->authority_rrs == 0)))) { - /* This is a good query */ - } else - invalid = 1; - } else { - /* DNS Reply */ - if((dns_header->num_queries > 0) && (dns_header->num_queries <= NDPI_MAX_DNS_REQUESTS) /* Don't assume that num_queries must be zero */ - && (((dns_header->num_answers > 0) && (dns_header->num_answers <= NDPI_MAX_DNS_REQUESTS)) - || ((dns_header->authority_rrs > 0) && (dns_header->authority_rrs <= NDPI_MAX_DNS_REQUESTS)) - || ((dns_header->additional_rrs > 0) && (dns_header->additional_rrs <= NDPI_MAX_DNS_REQUESTS))) - ) { - /* This is a good reply */ - } else - invalid = 1; + if(!invalid) { + if(is_query) { + /* DNS Request */ + if((dns_header.num_queries > 0) && (dns_header.num_queries <= NDPI_MAX_DNS_REQUESTS) + && (((dns_header.flags & 0x2800) == 0x2800 /* Dynamic DNS Update */) + || ((dns_header.num_answers == 0) && (dns_header.authority_rrs == 0)))) { + /* This is a good query */ + } else + invalid = 1; + } else { + /* DNS Reply */ + if((dns_header.num_queries > 0) && (dns_header.num_queries <= NDPI_MAX_DNS_REQUESTS) /* Don't assume that num_queries must be zero */ + && (((dns_header.num_answers > 0) && (dns_header.num_answers <= NDPI_MAX_DNS_REQUESTS)) + || ((dns_header.authority_rrs > 0) && (dns_header.authority_rrs <= NDPI_MAX_DNS_REQUESTS)) + || ((dns_header.additional_rrs > 0) && (dns_header.additional_rrs <= NDPI_MAX_DNS_REQUESTS))) + ) { + /* This is a good reply */ + } else + invalid = 1; + } } if(invalid) { @@ -106,7 +109,7 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd } /* extract host name server */ - ret_code = (is_query == 0) ? 0 : (dns_header->flags & 0x0F); + ret_code = (is_query == 0) ? 0 : (dns_header.flags & 0x0F); int j = 0; int off = sizeof(struct ndpi_dns_packet_header) + 1; while((flow->packet.payload[off] != '\0')) @@ -119,7 +122,7 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd } flow->host_server_name[j] = '\0'; - flow->protos.dns.num_answers = (u_int8_t) (dns_header->num_answers + dns_header->authority_rrs + dns_header->additional_rrs); + flow->protos.dns.num_answers = (u_int8_t) (dns_header.num_answers + dns_header.authority_rrs + dns_header.additional_rrs); flow->protos.dns.ret_code = ret_code; if(j > 0) diff --git a/src/lib/protocols/http.c b/src/lib/protocols/http.c index ced34c099..caac7390b 100644 --- a/src/lib/protocols/http.c +++ b/src/lib/protocols/http.c @@ -37,18 +37,14 @@ static void ndpi_int_http_add_connection(struct ndpi_detection_module_struct *nd /* If no custom protocol has been detected */ if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) { - if(protocol != NDPI_PROTOCOL_HTTP) { - ndpi_search_tcp_or_udp(ndpi_struct, flow); - ndpi_set_detected_protocol(ndpi_struct, flow, protocol, NDPI_PROTOCOL_UNKNOWN); - } else { + if(protocol == NDPI_PROTOCOL_HTTP) ndpi_int_reset_protocol(flow); - ndpi_set_detected_protocol(ndpi_struct, flow, protocol, NDPI_PROTOCOL_UNKNOWN); - } + + ndpi_set_detected_protocol(ndpi_struct, flow, protocol, NDPI_PROTOCOL_UNKNOWN); } flow->http_detected = 1; } - } #ifdef NDPI_CONTENT_FLASH @@ -202,21 +198,14 @@ static void parseHttpSubprotocol(struct ndpi_detection_module_struct *ndpi_struc /* NOTE - + If http_dont_dissect_response = 1 dissection of HTTP response mime types won't happen - */ - - if(!ndpi_struct->http_dont_dissect_response) { - if(flow->http.url && flow->http_detected) - ndpi_match_host_subprotocol(ndpi_struct, flow, (char *)&flow->http.url[7], - strlen((const char *)&flow->http.url[7]), - NDPI_PROTOCOL_HTTP); - } else - ndpi_match_host_subprotocol(ndpi_struct, flow, (char *)flow->host_server_name, - strlen((const char *)flow->host_server_name), - NDPI_PROTOCOL_HTTP); - } + */ + ndpi_match_host_subprotocol(ndpi_struct, flow, (char *)flow->host_server_name, + strlen((const char *)flow->host_server_name), + NDPI_PROTOCOL_HTTP); + } } /* diff --git a/src/lib/protocols/sip.c b/src/lib/protocols/sip.c index 3d79561ac..94386d61e 100644 --- a/src/lib/protocols/sip.c +++ b/src/lib/protocols/sip.c @@ -19,7 +19,7 @@ * * You should have received a copy of the GNU Lesser General Public License * along with nDPI. If not, see <http://www.gnu.org/licenses/>. - * + * */ @@ -31,7 +31,7 @@ static void ndpi_int_sip_add_connection(struct ndpi_detection_module_struct *ndp u_int8_t due_to_correlation) { ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SIP, NDPI_PROTOCOL_UNKNOWN); } - + #if !defined(WIN32) static inline #else @@ -41,7 +41,7 @@ void ndpi_search_sip_handshake(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; - + // struct ndpi_id_struct *src=ndpi_struct->src; // struct ndpi_id_struct *dst=ndpi_struct->dst; const u_int8_t *packet_payload = packet->payload; @@ -92,7 +92,7 @@ void ndpi_search_sip_handshake(struct ndpi_detection_module_struct * maybe it could be deleted, if somebody sees it in the first direction, * please delete this comment. */ - + /* if (memcmp(packet_payload, "SIP/2.0 200 OK", 14) == 0 || memcmp(packet_payload, "sip/2.0 200 OK", 14) == 0) { NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "found sip SIP/2.0 0K.\n"); @@ -121,7 +121,7 @@ void ndpi_search_sip_handshake(struct ndpi_detection_module_struct } if ((memcmp(packet_payload, "CANCEL ", 7) == 0 || memcmp(packet_payload, "cancel ", 7) == 0) - && (memcmp(&packet_payload[4], "SIP:", 7) == 0 || memcmp(&packet_payload[4], "sip:", 7) == 0)) { + && (memcmp(&packet_payload[4], "SIP:", 4) == 0 || memcmp(&packet_payload[4], "sip:", 4) == 0)) { NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "found sip CANCEL.\n"); ndpi_int_sip_add_connection(ndpi_struct, flow, 0); return; diff --git a/src/lib/protocols/socks4.c b/src/lib/protocols/socks4.c deleted file mode 100644 index 87bc3a634..000000000 --- a/src/lib/protocols/socks4.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * socks4.c - * - * Copyright (C) 2014 Tomasz Bujlow <tomasz@skatnet.dk> - * - * The signature is based on the Libprotoident library. - * - * This file is part of nDPI, an open source deep packet inspection - * library based on the OpenDPI and PACE technology by ipoque GmbH - * - * nDPI 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. - * - * nDPI 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 - * along with nDPI. If not, see <http://www.gnu.org/licenses/>. - * - */ - - -#include "ndpi_api.h" - -#ifdef NDPI_PROTOCOL_SOCKS4 -static void ndpi_int_socks4_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) -{ - ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SOCKS4, NDPI_PROTOCOL_UNKNOWN); -} - -static void ndpi_check_socks4(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) -{ - struct ndpi_packet_struct *packet = &flow->packet; - u_int32_t payload_len = packet->payload_packet_len; - - /* Break after 20 packets. */ - if (flow->packet_counter > 20) { - NDPI_LOG(NDPI_PROTOCOL_SOCKS4, ndpi_struct, NDPI_LOG_DEBUG, "Exclude SOCKS4.\n"); - NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOCKS4); - return; - } - - /* Check if we so far detected the protocol in the request or not. */ - if (flow->socks4_stage == 0) { - NDPI_LOG(NDPI_PROTOCOL_SOCKS4, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS4 stage 0: \n"); - - /*Octets 3 and 4 contain the port number, port 80 and 25 for now. */ - if ((payload_len == 9) && - (((packet->payload[0] == 0x04) && (packet->payload[1] == 0x01) && (packet->payload[2] == 0x00) && (packet->payload[3] == 0x50)) - || - ((packet->payload[0] == 0x04) && (packet->payload[1] == 0x01) && (packet->payload[2] == 0x00) && (packet->payload[3] == 0x19)))) { - NDPI_LOG(NDPI_PROTOCOL_SOCKS4, ndpi_struct, NDPI_LOG_DEBUG, "Possible SOCKS4 request detected, we will look further for the response...\n"); - - /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */ - flow->socks4_stage = packet->packet_direction + 1; - } - - } else { - NDPI_LOG(NDPI_PROTOCOL_SOCKS4, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS4 stage %u: \n", flow->socks4_stage); - - /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */ - if ((flow->socks4_stage - packet->packet_direction) == 1) { - return; - } - - /* This is a packet in another direction. Check if we find the proper response. */ - if (payload_len == 0) { - NDPI_LOG(NDPI_PROTOCOL_SOCKS4, ndpi_struct, NDPI_LOG_DEBUG, "Found SOCKS4.\n"); - ndpi_int_socks4_add_connection(ndpi_struct, flow); - } else { - NDPI_LOG(NDPI_PROTOCOL_SOCKS4, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to SOCKS4, resetting the stage to 0...\n"); - flow->socks4_stage = 0; - } - - } -} - -void ndpi_search_socks4(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) -{ - struct ndpi_packet_struct *packet = &flow->packet; - - NDPI_LOG(NDPI_PROTOCOL_SOCKS4, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS4 detection...\n"); - - /* skip marked packets */ - if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_SOCKS4) { - if (packet->tcp_retransmission == 0) { - ndpi_check_socks4(ndpi_struct, flow); - } - } -} - -#endif diff --git a/src/lib/protocols/socks45.c b/src/lib/protocols/socks45.c new file mode 100644 index 000000000..7ad0868d2 --- /dev/null +++ b/src/lib/protocols/socks45.c @@ -0,0 +1,155 @@ +/* + * socks4.c + * + * Copyright (C) 2016 - ntop.org + * Copyright (C) 2014 Tomasz Bujlow <tomasz@skatnet.dk> + * + * The signature is based on the Libprotoident library. + * + * This file is part of nDPI, an open source deep packet inspection + * library based on the OpenDPI and PACE technology by ipoque GmbH + * + * nDPI 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. + * + * nDPI 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 + * along with nDPI. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +#include "ndpi_api.h" + +#ifdef NDPI_PROTOCOL_SOCKS +static void ndpi_int_socks_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) +{ + ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SOCKS, NDPI_PROTOCOL_UNKNOWN); +} + +static void ndpi_check_socks4(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) +{ + struct ndpi_packet_struct *packet = &flow->packet; + u_int32_t payload_len = packet->payload_packet_len; + + /* Break after 20 packets. */ + if(flow->packet_counter > 20) { + NDPI_LOG(NDPI_PROTOCOL_SOCKS, ndpi_struct, NDPI_LOG_DEBUG, "Exclude SOCKS4.\n"); + NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOCKS); + return; + } + + /* Check if we so far detected the protocol in the request or not. */ + if(flow->socks4_stage == 0) { + NDPI_LOG(NDPI_PROTOCOL_SOCKS, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS4 stage 0: \n"); + + /*Octets 3 and 4 contain the port number, port 80 and 25 for now. */ + if((payload_len == 9) && + (((packet->payload[0] == 0x04) && (packet->payload[1] == 0x01) && (packet->payload[2] == 0x00) && (packet->payload[3] == 0x50)) + || + ((packet->payload[0] == 0x04) && (packet->payload[1] == 0x01) && (packet->payload[2] == 0x00) && (packet->payload[3] == 0x19)))) { + NDPI_LOG(NDPI_PROTOCOL_SOCKS, ndpi_struct, NDPI_LOG_DEBUG, "Possible SOCKS4 request detected, we will look further for the response...\n"); + + /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */ + flow->socks4_stage = packet->packet_direction + 1; + } + + } else { + NDPI_LOG(NDPI_PROTOCOL_SOCKS, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS4 stage %u: \n", flow->socks4_stage); + + /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */ + if((flow->socks4_stage - packet->packet_direction) == 1) { + return; + } + + /* This is a packet in another direction. Check if we find the proper response. */ + if(payload_len == 0) { + NDPI_LOG(NDPI_PROTOCOL_SOCKS, ndpi_struct, NDPI_LOG_DEBUG, "Found SOCKS4.\n"); + ndpi_int_socks_add_connection(ndpi_struct, flow); + } else { + NDPI_LOG(NDPI_PROTOCOL_SOCKS, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to SOCKS4, resetting the stage to 0...\n"); + flow->socks4_stage = 0; + } + + } +} + +static void ndpi_check_socks5(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) +{ + struct ndpi_packet_struct *packet = &flow->packet; + u_int32_t payload_len = packet->payload_packet_len; + + /* Break after 20 packets. */ + if(flow->packet_counter > 20) { + NDPI_LOG(NDPI_PROTOCOL_SOCKS, ndpi_struct, NDPI_LOG_DEBUG, "Exclude SOCKS5.\n"); + NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOCKS); + return; + } + + /* Check if we so far detected the protocol in the request or not. */ + if(flow->socks5_stage == 0) { + NDPI_LOG(NDPI_PROTOCOL_SOCKS, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS5 stage 0: \n"); + + if((payload_len == 3) && (packet->payload[0] == 0x05) && (packet->payload[1] == 0x01) && (packet->payload[2] == 0x00)) { + NDPI_LOG(NDPI_PROTOCOL_SOCKS, ndpi_struct, NDPI_LOG_DEBUG, "Possible SOCKS5 request detected, we will look further for the response...\n"); + + /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */ + flow->socks5_stage = packet->packet_direction + 1; + } + + } else { + NDPI_LOG(NDPI_PROTOCOL_SOCKS, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS5 stage %u: \n", flow->socks5_stage); + + /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */ + if((flow->socks5_stage - packet->packet_direction) == 1) { + return; + } + + /* This is a packet in another direction. Check if we find the proper response. */ + if((payload_len == 0) || ((payload_len == 2) && (packet->payload[0] == 0x05) && (packet->payload[1] == 0x00))) { + NDPI_LOG(NDPI_PROTOCOL_SOCKS, ndpi_struct, NDPI_LOG_DEBUG, "Found SOCKS5.\n"); + ndpi_int_socks_add_connection(ndpi_struct, flow); + } else { + NDPI_LOG(NDPI_PROTOCOL_SOCKS, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to SOCKS5, resetting the stage to 0...\n"); + flow->socks5_stage = 0; + } + + } +} + +void ndpi_search_socks(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) +{ + struct ndpi_packet_struct *packet = &flow->packet; + + NDPI_LOG(NDPI_PROTOCOL_SOCKS, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS detection...\n"); + + /* skip marked packets */ + if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_SOCKS) { + if(packet->tcp_retransmission == 0) { + ndpi_check_socks4(ndpi_struct, flow); + + if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_SOCKS) + ndpi_check_socks5(ndpi_struct, flow); + } + } +} + +void init_socks_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask) +{ + ndpi_set_bitmask_protocol_detection("SOCKS", ndpi_struct, detection_bitmask, *id, + NDPI_PROTOCOL_SOCKS, + ndpi_search_socks, + NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION, + SAVE_DETECTION_BITMASK_AS_UNKNOWN, + ADD_TO_DETECTION_BITMASK); + + *id += 1; +} + +#endif diff --git a/src/lib/protocols/socks5.c b/src/lib/protocols/socks5.c deleted file mode 100644 index f7cf89dfc..000000000 --- a/src/lib/protocols/socks5.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * socks5.c - * - * Copyright (C) 2014 Tomasz Bujlow <tomasz@skatnet.dk> - * - * The signature is based on the Libprotoident library. - * - * This file is part of nDPI, an open source deep packet inspection - * library based on the OpenDPI and PACE technology by ipoque GmbH - * - * nDPI 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. - * - * nDPI 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 - * along with nDPI. If not, see <http://www.gnu.org/licenses/>. - * - */ - - -#include "ndpi_api.h" - -#ifdef NDPI_PROTOCOL_SOCKS5 -static void ndpi_int_socks5_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) -{ - ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SOCKS5, NDPI_PROTOCOL_UNKNOWN); -} - -static void ndpi_check_socks5(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) -{ - struct ndpi_packet_struct *packet = &flow->packet; - u_int32_t payload_len = packet->payload_packet_len; - - /* Break after 20 packets. */ - if (flow->packet_counter > 20) { - NDPI_LOG(NDPI_PROTOCOL_SOCKS5, ndpi_struct, NDPI_LOG_DEBUG, "Exclude SOCKS5.\n"); - NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOCKS5); - return; - } - - /* Check if we so far detected the protocol in the request or not. */ - if (flow->socks5_stage == 0) { - NDPI_LOG(NDPI_PROTOCOL_SOCKS5, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS5 stage 0: \n"); - - if ((payload_len == 3) && (packet->payload[0] == 0x05) && (packet->payload[1] == 0x01) && (packet->payload[2] == 0x00)) { - NDPI_LOG(NDPI_PROTOCOL_SOCKS5, ndpi_struct, NDPI_LOG_DEBUG, "Possible SOCKS5 request detected, we will look further for the response...\n"); - - /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */ - flow->socks5_stage = packet->packet_direction + 1; - } - - } else { - NDPI_LOG(NDPI_PROTOCOL_SOCKS5, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS5 stage %u: \n", flow->socks5_stage); - - /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */ - if ((flow->socks5_stage - packet->packet_direction) == 1) { - return; - } - - /* This is a packet in another direction. Check if we find the proper response. */ - if ((payload_len == 0) || ((payload_len == 2) && (packet->payload[0] == 0x05) && (packet->payload[1] == 0x00))) { - NDPI_LOG(NDPI_PROTOCOL_SOCKS5, ndpi_struct, NDPI_LOG_DEBUG, "Found SOCKS5.\n"); - ndpi_int_socks5_add_connection(ndpi_struct, flow); - } else { - NDPI_LOG(NDPI_PROTOCOL_SOCKS5, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to SOCKS5, resetting the stage to 0...\n"); - flow->socks5_stage = 0; - } - - } -} - -void ndpi_search_socks5(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) -{ - struct ndpi_packet_struct *packet = &flow->packet; - - NDPI_LOG(NDPI_PROTOCOL_SOCKS5, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS5 detection...\n"); - - /* skip marked packets */ - if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_SOCKS5) { - if (packet->tcp_retransmission == 0) { - ndpi_check_socks5(ndpi_struct, flow); - } - } -} - -#endif diff --git a/src/lib/protocols/ssl.c b/src/lib/protocols/ssl.c index bc0aa4f3c..2269ae782 100644 --- a/src/lib/protocols/ssl.c +++ b/src/lib/protocols/ssl.c @@ -92,11 +92,12 @@ static void ndpi_int_ssl_add_connection(struct ndpi_detection_module_struct *ndp ((ch) >= '{' && (ch) <= '~')) static void stripCertificateTrailer(char *buffer, int buffer_len) { - int i; + + int i, is_puny; // printf("->%s<-\n", buffer); - for(i=0; i<buffer_len; i++) { + for(i = 0; i < buffer_len; i++) { // printf("%c [%d]\n", buffer[i], buffer[i]); if((buffer[i] != '.') @@ -110,21 +111,28 @@ static void stripCertificateTrailer(char *buffer, int buffer_len) { } } - if(i > 0) i--; - - while(i > 0) { - if(!ndpi_isalpha(buffer[i])) { - buffer[i] = '\0'; - buffer_len = i; - i--; - } else - break; - } - - for(i=buffer_len; i>0; i--) { - if(buffer[i] == '.') break; - else if(ndpi_isdigit(buffer[i])) - buffer[i] = '\0', buffer_len = i; + /* check for punycode encoding */ + is_puny = check_punycode_string(buffer, buffer_len); + + // not a punycode string - need more checks + if(is_puny == 0) { + + if(i > 0) i--; + + while(i > 0) { + if(!ndpi_isalpha(buffer[i])) { + buffer[i] = '\0'; + buffer_len = i; + i--; + } else + break; + } + + for(i = buffer_len; i > 0; i--) { + if(buffer[i] == '.') break; + else if(ndpi_isdigit(buffer[i])) + buffer[i] = '\0', buffer_len = i; + } } } diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c index 69e1cad52..e21f9331b 100644 --- a/src/lib/protocols/stun.c +++ b/src/lib/protocols/stun.c @@ -27,7 +27,7 @@ #ifdef NDPI_PROTOCOL_STUN -#define MAX_NUM_STUN_PKTS 6 +#define MAX_NUM_STUN_PKTS 10 struct stun_packet_header { @@ -55,8 +55,13 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * u_int16_t msg_type, msg_len; struct stun_packet_header *h = (struct stun_packet_header*)payload; - if(payload_length < sizeof(struct stun_packet_header)) - return(NDPI_IS_NOT_STUN); + if(payload_length < sizeof(struct stun_packet_header)) { + if(flow->num_stun_udp_pkts > 0) { + *is_whatsapp = 1; + return NDPI_IS_STUN; /* This is WhatsApp Voice */ + } else + return(NDPI_IS_NOT_STUN); + } if((strncmp((const char*)payload, (const char*)"RSP/", 4) == 0) && (strncmp((const char*)&payload[7], (const char*)" STUN_", 6) == 0)) { @@ -215,10 +220,7 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * #endif - if( - ((flow->num_stun_udp_pkts > 0) && (msg_type == 0x0800)) - || ((msg_type == 0x0800) && (msg_len == 106)) - ) { + if((flow->num_stun_udp_pkts > 0) && (msg_type <= 0x00FF)) { *is_whatsapp = 1; return NDPI_IS_STUN; /* This is WhatsApp Voice */ } else diff --git a/src/lib/protocols/tcp_udp.c b/src/lib/protocols/tcp_udp.c index 9f9febfeb..2c6792551 100644 --- a/src/lib/protocols/tcp_udp.c +++ b/src/lib/protocols/tcp_udp.c @@ -30,6 +30,7 @@ u_int ndpi_search_tcp_or_udp_raw(struct ndpi_detection_module_struct *ndpi_struc u_int16_t sport, u_int16_t dport) /* host endianess */ { u_int16_t rc; + struct in_addr host; if(protocol == IPPROTO_UDP) { if((sport == dport) && (sport == 17500)) { @@ -37,9 +38,12 @@ u_int ndpi_search_tcp_or_udp_raw(struct ndpi_detection_module_struct *ndpi_struc } } - if((rc = ndpi_host_ptree_match(ndpi_struct, htonl(saddr))) != NDPI_PROTOCOL_UNKNOWN) return(rc); - - return(ndpi_host_ptree_match(ndpi_struct, htonl(daddr))); + host.s_addr = htonl(saddr); + if((rc = ndpi_network_ptree_match(ndpi_struct, &host)) != NDPI_PROTOCOL_UNKNOWN) + return (rc); + + host.s_addr = htonl(daddr); + return (ndpi_network_ptree_match(ndpi_struct, &host)); } void ndpi_search_tcp_or_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) diff --git a/src/lib/protocols/tor.c b/src/lib/protocols/tor.c index f2c2eae4c..f53e5da66 100644 --- a/src/lib/protocols/tor.c +++ b/src/lib/protocols/tor.c @@ -24,7 +24,7 @@ int ndpi_is_ssl_tor(struct ndpi_detection_module_struct *ndpi_struct, if((certificate == NULL) || (strlen(certificate) < 6) - || strncmp(certificate, "www.", 4)) + || !(strncmp(certificate, "www.", 4))) return(0); // printf("***** [SSL] %s(): %s\n", __FUNCTION__, certificate); diff --git a/src/lib/protocols/veohtv.c b/src/lib/protocols/veohtv.c deleted file mode 100644 index a3ab267b9..000000000 --- a/src/lib/protocols/veohtv.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * veohtv.c - * - * Copyright (C) 2009-2011 by ipoque GmbH - * Copyright (C) 2011-15 - ntop.org - * - * This file is part of nDPI, an open source deep packet inspection - * library based on the OpenDPI and PACE technology by ipoque GmbH - * - * nDPI 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. - * - * nDPI 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 - * along with nDPI. If not, see <http://www.gnu.org/licenses/>. - * - */ - - -#include "ndpi_api.h" - - -#ifdef NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV - -static void ndpi_int_veohtv_add_connection(struct ndpi_detection_module_struct *ndpi_struct, - struct ndpi_flow_struct *flow/* , ndpi_protocol_type_t protocol_type */) -{ - ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV, NDPI_PROTOCOL_UNKNOWN); -} - -void ndpi_search_veohtv_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) -{ - struct ndpi_packet_struct *packet = &flow->packet; - -// struct ndpi_id_struct *src=ndpi_struct->src; -// struct ndpi_id_struct *dst=ndpi_struct->dst; - - if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV) - return; - - if (flow->l4.tcp.veoh_tv_stage == 1 || flow->l4.tcp.veoh_tv_stage == 2) { - if (packet->packet_direction != flow->setup_packet_direction && - packet->payload_packet_len > NDPI_STATICSTRING_LEN("HTTP/1.1 20") - && memcmp(packet->payload, "HTTP/1.1 ", NDPI_STATICSTRING_LEN("HTTP/1.1 ")) == 0 && - (packet->payload[NDPI_STATICSTRING_LEN("HTTP/1.1 ")] == '2' || - packet->payload[NDPI_STATICSTRING_LEN("HTTP/1.1 ")] == '3' || - packet->payload[NDPI_STATICSTRING_LEN("HTTP/1.1 ")] == '4' || - packet->payload[NDPI_STATICSTRING_LEN("HTTP/1.1 ")] == '5')) { -#ifdef NDPI_CONTENT_FLASH - ndpi_parse_packet_line_info(ndpi_struct, flow); - if (packet->detected_protocol_stack[0] == NDPI_CONTENT_FLASH && - packet->server_line.ptr != NULL && - packet->server_line.len > NDPI_STATICSTRING_LEN("Veoh-") && - memcmp(packet->server_line.ptr, "Veoh-", NDPI_STATICSTRING_LEN("Veoh-")) == 0) { - NDPI_LOG(NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV, ndpi_struct, NDPI_LOG_DEBUG, "VeohTV detected.\n"); - ndpi_int_veohtv_add_connection(ndpi_struct, flow); - return; - } -#endif - if (flow->l4.tcp.veoh_tv_stage == 2) { - NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, - NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV); - return; - } - NDPI_LOG(NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV, ndpi_struct, NDPI_LOG_DEBUG, "VeohTV detected.\n"); - ndpi_int_veohtv_add_connection(ndpi_struct, flow); - return; - } else if (flow->packet_direction_counter[(flow->setup_packet_direction == 1) ? 0 : 1] > 3) { - if (flow->l4.tcp.veoh_tv_stage == 2) { - NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, - NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV); - return; - } - NDPI_LOG(NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV, ndpi_struct, NDPI_LOG_DEBUG, "VeohTV detected.\n"); - ndpi_int_veohtv_add_connection(ndpi_struct, flow); - return; - } else { - if (flow->packet_counter > 10) { - if (flow->l4.tcp.veoh_tv_stage == 2) { - NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, - NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV); - return; - } - NDPI_LOG(NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV, ndpi_struct, NDPI_LOG_DEBUG, "VeohTV detected.\n"); - ndpi_int_veohtv_add_connection(ndpi_struct, flow); - return; - } - return; - } - } else if (packet->udp) { - /* UDP packets from Veoh Client Player - * - * packet starts with 16 byte random? value - * then a 4 byte mode value - * values between 21 and 26 has been seen - * then a 4 byte counter */ - - if (packet->payload_packet_len == 28 && - get_u_int32_t(packet->payload, 16) == htonl(0x00000021) && - get_u_int32_t(packet->payload, 20) == htonl(0x00000000) && get_u_int32_t(packet->payload, 24) == htonl(0x01040000)) { - NDPI_LOG(NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV, ndpi_struct, NDPI_LOG_DEBUG, "UDP VeohTV found.\n"); - ndpi_int_veohtv_add_connection(ndpi_struct, flow); - return; - } - } - - - NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV); -} - - -void init_veohtv_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask) -{ - ndpi_set_bitmask_protocol_detection("HTTP_APPLICATION_VEOHTV", ndpi_struct, detection_bitmask, *id, - NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV, - ndpi_search_veohtv_tcp, - NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION, - SAVE_DETECTION_BITMASK_AS_UNKNOWN, - ADD_TO_DETECTION_BITMASK); - - *id += 1; -} - -#endif |