static int matchStringProtocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, char *string_to_match, u_int string_to_match_len) { int i = 0, end = string_to_match_len-1, num_found = 0; struct ndpi_packet_struct *packet = &flow->packet; #ifdef AHOCORASICK AC_TEXT_t ac_input_text; #endif while(end > 0) { if(string_to_match[end] == '.') { num_found++; if(num_found == 2) { end++; break; } } end--; } strncpy(flow->l4.tcp.host_server_name, &string_to_match[end], ndpi_min(sizeof(flow->l4.tcp.host_server_name)-1, string_to_match_len-end)); #ifdef AHOCORASICK matching_protocol_id = -1; ac_input_text.astring = string_to_match; ac_input_text.length = string_to_match_len; ac_automata_search (ac_automa, &ac_input_text, 0); ac_automata_reset(ac_automa); if (matching_protocol_id != -1) { packet->detected_protocol_stack[0] = matching_protocol_id; return(packet->detected_protocol_stack[0]); } #else for (i = 0; i < host_match_num_items; i++) { if(ndpi_strnstr(string_to_match, host_match[i].string_to_match, string_to_match_len) != NULL) { packet->detected_protocol_stack[0] = host_match[i].protocol_id; return(packet->detected_protocol_stack[0]); } else i++; } #endif #ifdef DEBUG string_to_match[string_to_match_len] = '\0'; printf("[NTOP] Unable to find a match for '%s'\n", string_to_match); #endif return(-1); }
/* Code fixes courtesy of Alexsandro Brahm <*****@*****.**> */ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, 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 <*****@*****.**> */ if(packet->payload[0] == 0x16 /* Handshake */) { u_int16_t total_len = (packet->payload[3] << 8) + packet->payload[4] + 5 /* SSL Header */; u_int8_t handshake_protocol = packet->payload[5]; /* handshake protocol a bit misleading, it is message type according TLS specs */ memset(buffer, 0, buffer_len); /* Truncate total len, search at least in incomplete packet */ 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 */ if(total_len > 4) { int i; if(handshake_protocol == 0x02 || handshake_protocol == 0xb /* Server Hello and Certificate message types are interesting for us */) { u_int num_found = 0; flow->l4.tcp.ssl_seen_server_cert = 1; /* Check after handshake protocol header (5 bytes) and message header (4 bytes) */ for(i = 9; i < packet->payload_packet_len-3; i++) { if(((packet->payload[i] == 0x04) && (packet->payload[i+1] == 0x03) && (packet->payload[i+2] == 0x0c)) || ((packet->payload[i] == 0x55) && (packet->payload[i+1] == 0x04) && (packet->payload[i+2] == 0x03))) { u_int8_t server_len = packet->payload[i+3]; if(packet->payload[i] == 0x55) { num_found++; if(num_found != 2) continue; } if(server_len+i+3 < packet->payload_packet_len) { char *server_name = (char*)&packet->payload[i+4]; u_int8_t begin = 0, len, j, num_dots; while(begin < server_len) { if(!ndpi_isprint(server_name[begin])) begin++; else break; } // len = ndpi_min(server_len-begin, buffer_len-1); len = buffer_len-1; strncpy(buffer, &server_name[begin], len); buffer[len] = '\0'; /* We now have to check if this looks like an IP address or host name */ for(j=0, num_dots = 0; j<len; j++) { if(!ndpi_isprint((buffer[j]))) { num_dots = 0; /* This is not what we look for */ break; } else if(buffer[j] == '.') { num_dots++; if(num_dots >=2) break; } } if(num_dots >= 2) { stripCertificateTrailer(buffer, buffer_len); snprintf(flow->protos.ssl.server_certificate, sizeof(flow->protos.ssl.server_certificate), "%s", buffer); return(1 /* Server Certificate */); } } } } } else if(handshake_protocol == 0x01 /* Client Hello */) { u_int offset, base_offset = 43; u_int16_t session_id_len = packet->payload[base_offset]; if((session_id_len+base_offset+2) <= total_len) { u_int16_t cypher_len = packet->payload[session_id_len+base_offset+2] + (packet->payload[session_id_len+base_offset+1] << 8); offset = base_offset + session_id_len + cypher_len + 2; flow->l4.tcp.ssl_seen_client_cert = 1; if(offset < total_len) { u_int16_t compression_len; u_int16_t extensions_len; compression_len = packet->payload[offset+1]; offset += compression_len + 3; if(offset < total_len) { extensions_len = packet->payload[offset]; if((extensions_len+offset) < total_len) { u_int16_t extension_offset = 1; /* Move to the first extension */ while(extension_offset < extensions_len) { u_int16_t extension_id, extension_len; memcpy(&extension_id, &packet->payload[offset+extension_offset], 2); extension_offset += 2; memcpy(&extension_len, &packet->payload[offset+extension_offset], 2); extension_offset += 2; extension_id = ntohs(extension_id), extension_len = ntohs(extension_len); if(extension_id == 0) { u_int begin = 0,len; char *server_name = (char*)&packet->payload[offset+extension_offset]; while(begin < extension_len) { if((!ndpi_isprint(server_name[begin])) || ndpi_ispunct(server_name[begin]) || ndpi_isspace(server_name[begin])) begin++; else break; } len = (u_int)ndpi_min(extension_len-begin, buffer_len-1); strncpy(buffer, &server_name[begin], len); buffer[len] = '\0'; stripCertificateTrailer(buffer, buffer_len); snprintf(flow->protos.ssl.client_certificate, sizeof(flow->protos.ssl.client_certificate), "%s", buffer); /* We're happy now */ return(2 /* Client Certificate */); } extension_offset += extension_len; } } } } } } } } return(0); /* Not found */ }
static void check_content_type_and_change_protocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { #ifdef NDPI_PROTOCOL_MPEG struct ndpi_packet_struct *packet = &flow->packet; #endif #ifdef NDPI_PROTOCOL_AVI #endif // struct ndpi_id_struct *src=ndpi_struct->src; // struct ndpi_id_struct *dst=ndpi_struct->dst; u_int8_t a; if (packet->content_line.ptr != NULL && packet->content_line.len != 0) { NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "Content Type Line found %.*s\n", packet->content_line.len, packet->content_line.ptr); #ifdef NDPI_PROTOCOL_MPEG if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_MPEG) != 0) mpeg_parse_packet_contentline(ndpi_struct, flow); #endif #ifdef NDPI_PROTOCOL_FLASH if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_FLASH) != 0) flash_parse_packet_contentline(ndpi_struct, flow); #endif #ifdef NDPI_PROTOCOL_QUICKTIME if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_QUICKTIME) != 0) qt_parse_packet_contentline(ndpi_struct, flow); #endif #ifdef NDPI_PROTOCOL_REALMEDIA if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_REALMEDIA) != 0) realmedia_parse_packet_contentline(ndpi_struct, flow); #endif #ifdef NDPI_PROTOCOL_WINDOWSMEDIA if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_WINDOWSMEDIA) != 0) windowsmedia_parse_packet_contentline(ndpi_struct, flow); #endif #ifdef NDPI_PROTOCOL_MMS if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_MMS) != 0) mms_parse_packet_contentline(ndpi_struct, flow); #endif #ifdef NDPI_PROTOCOL_OFF if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_OFF) != 0) off_parse_packet_contentline(ndpi_struct, flow); #endif #ifdef NDPI_PROTOCOL_OGG if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_OGG) != 0) ogg_parse_packet_contentline(ndpi_struct, flow); #endif #ifdef NDPI_PROTOCOL_MOVE if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_MOVE) != 0) move_parse_packet_contentline(ndpi_struct, flow); #endif #ifdef NDPI_PROTOCOL_WEBM if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_WEBM) != 0) webm_parse_packet_contentline(ndpi_struct, flow); #endif } /* check user agent here too */ if (packet->user_agent_line.ptr != NULL && packet->user_agent_line.len != 0) { NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "User Agent Type Line found %.*s\n", packet->user_agent_line.len, packet->user_agent_line.ptr); #ifdef NDPI_PROTOCOL_XBOX if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_XBOX) != 0) xbox_parse_packet_useragentline(ndpi_struct, flow); #endif #ifdef NDPI_PROTOCOL_WINDOWS_UPDATE if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_WINDOWS_UPDATE) != 0) windows_update_packet_useragentline(ndpi_struct, flow); #endif #ifdef NDPI_PROTOCOL_WINDOWSMEDIA if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_WINDOWSMEDIA) != 0) winmedia_parse_packet_useragentline(ndpi_struct, flow); #endif } /* check for host line */ if (packet->host_line.ptr != NULL) { u_int len; NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HOST Line found %.*s\n", packet->host_line.len, packet->host_line.ptr); #ifdef NDPI_PROTOCOL_QQ if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_QQ) != 0) { qq_parse_packet_URL_and_hostname(ndpi_struct, flow); } #endif /* Copy result for nDPI apps */ len = ndpi_min(packet->host_line.len, sizeof(flow->host_server_name)-1); strncpy((char*)flow->host_server_name, (char*)packet->host_line.ptr, len); flow->host_server_name[len] = '\0'; parseHttpSubprotocol(ndpi_struct, flow); if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_HTTP) { ndpi_int_http_add_connection(ndpi_struct, flow, packet->detected_protocol_stack[0]); return; /* We have identified a sub-protocol so we're done */ } } /* check for accept line */ if (packet->accept_line.ptr != NULL) { NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "Accept Line found %.*s\n", packet->accept_line.len, packet->accept_line.ptr); #ifdef NDPI_PROTOCOL_RTSP if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_RTSP) != 0) { rtsp_parse_packet_acceptline(ndpi_struct, flow); } #endif } /* search for line startin with "Icy-MetaData" */ #ifdef NDPI_PROTOCOL_MPEG for (a = 0; a < packet->parsed_lines; a++) { if (packet->line[a].len > 11 && memcmp(packet->line[a].ptr, "Icy-MetaData", 12) == 0) { NDPI_LOG(NDPI_PROTOCOL_MPEG, ndpi_struct, NDPI_LOG_DEBUG, "MPEG: Icy-MetaData found.\n"); ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MPEG); return; } } #ifdef NDPI_PROTOCOL_AVI #endif #endif }