void ndpi_search_ssl_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=flow->src; // struct ndpi_id_struct *dst=flow->dst; 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) { /* 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) { /* still ssl so check another packet */ return; } else { /* protocol has changed so we are done */ return; } } return; } NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "search ssl\n"); { /* Check if this is whatsapp first (this proto runs over port 443) */ if((packet->payload_packet_len > 5) && ((packet->payload[0] == 'W') && (packet->payload[1] == 'A') && (packet->payload[4] == 0) && (packet->payload[2] <= 9) && (packet->payload[3] <= 9))) { ndpi_int_add_connection(ndpi_struct, flow, NDPI_SERVICE_WHATSAPP, NDPI_REAL_PROTOCOL); return; } else { /* No whatsapp, let's try SSL */ if(sslDetectProtocolFromCertificate(ndpi_struct, flow) > 0) return; } } 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 && (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"); flow->l4.tcp.ssl_stage = 1 + packet->packet_direction; return; } 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 NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "sslv3 len match\n"); flow->l4.tcp.ssl_stage = 1 + packet->packet_direction; return; } } 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) { 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 && (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"); ssl_mark_and_payload_search_for_other_protocols(ndpi_struct, flow); return; } ret = ndpi_search_sslv3_direction1(ndpi_struct, flow); 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) { 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) { flow->l4.tcp.ssl_stage = 3; } return; } 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; } } NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "exclude ssl\n"); NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SSL); return; }
void ipoque_search_ssl_tcp(struct ipoque_detection_module_struct *ipoque_struct) { struct ipoque_packet_struct *packet = &ipoque_struct->packet; struct ipoque_flow_struct *flow = ipoque_struct->flow; // struct ipoque_id_struct *src=ipoque_struct->src; // struct ipoque_id_struct *dst=ipoque_struct->dst; u8 ret; if (packet->detected_protocol_stack[0] == IPOQUE_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 */ IPQ_LOG(IPOQUE_PROTOCOL_SSL, ipoque_struct, IPQ_LOG_DEBUG, "ssl flow but check another packet for patterns\n"); ssl_mark_and_payload_search_for_other_protocols(ipoque_struct); if (packet->detected_protocol_stack[0] == IPOQUE_PROTOCOL_SSL) { /* still ssl so check another packet */ return; } else { /* protocol has changed so we are done */ return; } } return; } IPQ_LOG(IPOQUE_PROTOCOL_SSL, ipoque_struct, IPQ_LOG_DEBUG, "search ssl\n"); if (packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 0) { IPQ_LOG(IPOQUE_PROTOCOL_SSL, ipoque_struct, IPQ_LOG_DEBUG, "first ssl packet\n"); // SSLv2 Record 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)) { IPQ_LOG(IPOQUE_PROTOCOL_SSL, ipoque_struct, IPQ_LOG_DEBUG, "sslv2 len match\n"); flow->l4.tcp.ssl_stage = 1 + packet->packet_direction; return; } 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_u16(packet->payload, 3)) == 5)) { // SSLv3 Record IPQ_LOG(IPOQUE_PROTOCOL_SSL, ipoque_struct, IPQ_LOG_DEBUG, "sslv3 len match\n"); flow->l4.tcp.ssl_stage = 1 + packet->packet_direction; return; } } 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) { IPQ_LOG(IPOQUE_PROTOCOL_SSL, ipoque_struct, IPQ_LOG_DEBUG, "second ssl packet\n"); // SSLv2 Record 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]) { IPQ_LOG(IPOQUE_PROTOCOL_SSL, ipoque_struct, IPQ_LOG_DEBUG, "sslv2 server len match\n"); ssl_mark_and_payload_search_for_other_protocols(ipoque_struct); return; } ret = ipoque_search_sslv3_direction1(ipoque_struct); if (ret == 1) { IPQ_LOG(IPOQUE_PROTOCOL_SSL, ipoque_struct, IPQ_LOG_DEBUG, "sslv3 server len match\n"); ssl_mark_and_payload_search_for_other_protocols(ipoque_struct); return; } else if (ret == 2) { IPQ_LOG(IPOQUE_PROTOCOL_SSL, ipoque_struct, IPQ_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(ipoque_struct); if (packet->detected_protocol_stack[0] == IPOQUE_PROTOCOL_SSL) { flow->l4.tcp.ssl_stage = 3; } return; } if (packet->payload_packet_len > 40 && flow->packet_direction_counter[packet->packet_direction] < 5) { IPQ_LOG(IPOQUE_PROTOCOL_SSL, ipoque_struct, IPQ_LOG_DEBUG, "need next packet\n"); return; } } IPQ_LOG(IPOQUE_PROTOCOL_SSL, ipoque_struct, IPQ_LOG_DEBUG, "exclude ssl\n"); IPOQUE_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, IPOQUE_PROTOCOL_SSL); return; }