void ipoque_search_http_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; u16 filename_start; IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "search http\n"); /* set client-server_direction */ if (flow->l4.tcp.http_setup_dir == 0) { IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "initializes http to stage: 1 \n"); flow->l4.tcp.http_setup_dir = 1 + packet->packet_direction; } if (IPOQUE_COMPARE_PROTOCOL_TO_BITMASK (ipoque_struct->generic_http_packet_bitmask, packet->detected_protocol_stack[0]) != 0) { IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "protocol might be detected earlier as http jump to payload type detection\n"); goto http_parse_detection; } if (flow->l4.tcp.http_setup_dir == 1 + packet->packet_direction) { IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "http stage: 1\n"); if (flow->l4.tcp.http_wait_for_retransmission) { if (!packet->tcp_retransmission) { if (flow->packet_counter <= 5) { IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "still waiting for retransmission\n"); return; } else { IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "retransmission not found, exclude\n"); http_bitmask_exclude(flow); return; } } } if (flow->l4.tcp.http_stage == 0) { filename_start = http_request_url_offset(ipoque_struct); if (filename_start == 0) { IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "filename not found, exclude\n"); http_bitmask_exclude(flow); return; } // parse packet ipq_parse_packet_line_info(ipoque_struct); if (packet->parsed_lines <= 1) { /* parse one more packet .. */ IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "just one line, search next packet\n"); flow->l4.tcp.http_stage = 1; return; } // parsed_lines > 1 here if (packet->line[0].len >= (9 + filename_start) && memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) == 0) { packet->http_url_name.ptr = &packet->payload[filename_start]; packet->http_url_name.len = packet->line[0].len - (filename_start + 9); packet->http_method.ptr = packet->line[0].ptr; packet->http_method.len = filename_start - 1; IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "http structure detected, adding\n"); ipoque_int_http_add_connection(ipoque_struct, (filename_start == 8) ? NTOP_PROTOCOL_HTTP_CONNECT : IPOQUE_PROTOCOL_HTTP); check_content_type_and_change_protocol(ipoque_struct); /* HTTP found, look for host... */ if (packet->host_line.ptr != NULL) { /* aaahh, skip this direction and wait for a server reply here */ flow->l4.tcp.http_stage = 2; IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "HTTP START HOST found\n"); return; } IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "HTTP START HOST found\n"); /* host not found, check in next packet after */ flow->l4.tcp.http_stage = 1; return; } } else if (flow->l4.tcp.http_stage == 1) { /* SECOND PAYLOAD TRAFFIC FROM CLIENT, FIRST PACKET MIGHT HAVE BEEN HTTP... */ /* UNKNOWN TRAFFIC, HERE FOR HTTP again.. */ // parse packet ipq_parse_packet_line_info(ipoque_struct); if (packet->parsed_lines <= 1) { /* wait some packets in case request is split over more than 2 packets */ if (flow->packet_counter < 5) { IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "line still not finished, search next packet\n"); return; } else { /* stop parsing here */ IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "HTTP: PACKET DOES NOT HAVE A LINE STRUCTURE\n"); http_bitmask_exclude(flow); return; } } if (packet->line[0].len >= 9 && memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) == 0) { ipoque_int_http_add_connection(ipoque_struct, IPOQUE_PROTOCOL_HTTP); check_content_type_and_change_protocol(ipoque_struct); IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "HTTP START HTTP found in 2. packet, check host here...\n"); /* HTTP found, look for host... */ flow->l4.tcp.http_stage = 2; return; } } } IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "HTTP: REQUEST NOT HTTP CONFORM\n"); http_bitmask_exclude(flow); return; http_parse_detection: if (flow->l4.tcp.http_setup_dir == 1 + packet->packet_direction) { /* we have something like http here, so check for host and content type if possible */ if (flow->l4.tcp.http_stage == 0 || flow->l4.tcp.http_stage == 3) { IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "HTTP RUN MAYBE NEXT GET/POST...\n"); // parse packet ipq_parse_packet_line_info(ipoque_struct); /* check for url here */ filename_start = http_request_url_offset(ipoque_struct); if (filename_start != 0 && packet->parsed_lines > 1 && packet->line[0].len >= (9 + filename_start) && memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) == 0) { packet->http_url_name.ptr = &packet->payload[filename_start]; packet->http_url_name.len = packet->line[0].len - (filename_start + 9); packet->http_method.ptr = packet->line[0].ptr; packet->http_method.len = filename_start - 1; IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "next http action, " "resetting to http and search for other protocols later.\n"); ipoque_int_http_add_connection(ipoque_struct, IPOQUE_PROTOCOL_HTTP); } check_content_type_and_change_protocol(ipoque_struct); /* HTTP found, look for host... */ if (packet->host_line.ptr != NULL) { IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "HTTP RUN MAYBE NEXT HOST found, skipping all packets from this direction\n"); /* aaahh, skip this direction and wait for a server reply here */ flow->l4.tcp.http_stage = 2; return; } IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "HTTP RUN MAYBE NEXT HOST NOT found, scanning one more packet from this direction\n"); flow->l4.tcp.http_stage = 1; } else if (flow->l4.tcp.http_stage == 1) { // parse packet and maybe find a packet info with host ptr,... ipq_parse_packet_line_info(ipoque_struct); check_content_type_and_change_protocol(ipoque_struct); IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "HTTP RUN second packet scanned\n"); /* HTTP found, look for host... */ flow->l4.tcp.http_stage = 2; } IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "HTTP skipping client packets after second packet\n"); return; } /* server response */ if (flow->l4.tcp.http_stage > 0) { /* first packet from server direction, might have a content line */ ipq_parse_packet_line_info(ipoque_struct); check_content_type_and_change_protocol(ipoque_struct); if (packet->empty_line_position_set != 0 || flow->l4.tcp.http_empty_line_seen == 1) { IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "empty line. check_http_payload.\n"); check_http_payload(ipoque_struct); } if (flow->l4.tcp.http_stage == 2) { flow->l4.tcp.http_stage = 3; } else { flow->l4.tcp.http_stage = 0; } IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "HTTP response first or second packet scanned,new stage is: %u\n", flow->l4.tcp.http_stage); return; } else { IPQ_LOG(IPOQUE_PROTOCOL_HTTP, ipoque_struct, IPQ_LOG_DEBUG, "HTTP response next packet skipped\n"); } }
void ndpi_search_jabber_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_int16_t x; NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_TRACE, "JABBER detection....\n"); /* search for jabber file transfer */ /* this part is working asymmetrically */ if (packet->tcp != NULL && packet->tcp->syn != 0 && packet->payload_packet_len == 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "check jabber syn\n"); if (src != NULL && src->jabber_file_transfer_port[0] != 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "src jabber ft port set, ports are: %u, %u\n", ntohs(src->jabber_file_transfer_port[0]), ntohs(src->jabber_file_transfer_port[1])); if (((u_int32_t) (packet->tick_timestamp - src->jabber_stun_or_ft_ts)) >= ndpi_struct->jabber_file_transfer_timeout) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER src stun timeout %u %u\n", src->jabber_stun_or_ft_ts, packet->tick_timestamp); src->jabber_file_transfer_port[0] = 0; src->jabber_file_transfer_port[1] = 0; } else if (src->jabber_file_transfer_port[0] == packet->tcp->dest || src->jabber_file_transfer_port[0] == packet->tcp->source || src->jabber_file_transfer_port[1] == packet->tcp->dest || src->jabber_file_transfer_port[1] == packet->tcp->source) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "found jabber file transfer.\n"); ndpi_int_jabber_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_UNENCRYPED_JABBER); } } if (dst != NULL && dst->jabber_file_transfer_port[0] != 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "dst jabber ft port set, ports are: %u, %u\n", ntohs(dst->jabber_file_transfer_port[0]), ntohs(dst->jabber_file_transfer_port[1])); if (((u_int32_t) (packet->tick_timestamp - dst->jabber_stun_or_ft_ts)) >= ndpi_struct->jabber_file_transfer_timeout) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER dst stun timeout %u %u\n", dst->jabber_stun_or_ft_ts, packet->tick_timestamp); dst->jabber_file_transfer_port[0] = 0; dst->jabber_file_transfer_port[1] = 0; } else if (dst->jabber_file_transfer_port[0] == packet->tcp->dest || dst->jabber_file_transfer_port[0] == packet->tcp->source || dst->jabber_file_transfer_port[1] == packet->tcp->dest || dst->jabber_file_transfer_port[1] == packet->tcp->source) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "found jabber file transfer.\n"); ndpi_int_jabber_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_UNENCRYPED_JABBER); } } return; } if (packet->tcp != 0 && packet->payload_packet_len == 0) { return; } /* this part parses a packet and searches for port=. it works asymmetrically. */ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNENCRYPED_JABBER) { u_int16_t lastlen; u_int16_t j_port = 0; /* check for google jabber voip connections ... */ /* need big packet */ if (packet->payload_packet_len < 100) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "packet too small, return.\n"); return; } /* need message to or type for file-transfer */ if (memcmp(packet->payload, "<iq from=\"", 8) == 0 || memcmp(packet->payload, "<iq from=\'", 8) == 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER <iq from=\".\n"); lastlen = packet->payload_packet_len - 11; for (x = 10; x < lastlen; x++) { if (packet->payload[x] == 'p') { if (memcmp(&packet->payload[x], "port=", 5) == 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "port=\n"); if (src != NULL) { src->jabber_stun_or_ft_ts = packet->tick_timestamp; } if (dst != NULL) { dst->jabber_stun_or_ft_ts = packet->tick_timestamp; } x += 6; j_port = ntohs_ndpi_bytestream_to_number(&packet->payload[x], packet->payload_packet_len, &x); NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER port : %u\n", ntohs(j_port)); if (src != NULL) { if (src->jabber_file_transfer_port[0] == 0 || src->jabber_file_transfer_port[0] == j_port) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "src->jabber_file_transfer_port[0] = j_port = %u;\n", ntohs(j_port)); src->jabber_file_transfer_port[0] = j_port; } else { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "src->jabber_file_transfer_port[1] = j_port = %u;\n", ntohs(j_port)); src->jabber_file_transfer_port[1] = j_port; } } if (dst != NULL) { if (dst->jabber_file_transfer_port[0] == 0 || dst->jabber_file_transfer_port[0] == j_port) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "dst->jabber_file_transfer_port[0] = j_port = %u;\n", ntohs(j_port)); dst->jabber_file_transfer_port[0] = j_port; } else { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "dst->jabber_file_transfer_port[1] = j_port = %u;\n", ntohs(j_port)); dst->jabber_file_transfer_port[1] = j_port; } } } } } } else if (memcmp(packet->payload, "<iq to=\"", 8) == 0 || memcmp(packet->payload, "<iq to=\'", 8) == 0 || memcmp(packet->payload, "<iq type=", 9) == 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER <iq to=\"/type=\"\n"); lastlen = packet->payload_packet_len - 21; for (x = 8; x < lastlen; x++) { /* invalid character */ if (packet->payload[x] < 32 || packet->payload[x] > 127) { return; } if (packet->payload[x] == '@') { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER @\n"); break; } } if (x >= lastlen) { return; } lastlen = packet->payload_packet_len - 10; for (; x < lastlen; x++) { if (packet->payload[x] == 'p') { if (memcmp(&packet->payload[x], "port=", 5) == 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "port=\n"); if (src != NULL) { src->jabber_stun_or_ft_ts = packet->tick_timestamp; } if (dst != NULL) { dst->jabber_stun_or_ft_ts = packet->tick_timestamp; } x += 6; j_port = ntohs_ndpi_bytestream_to_number(&packet->payload[x], packet->payload_packet_len, &x); NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER port : %u\n", ntohs(j_port)); if (src != NULL && src->jabber_voice_stun_used_ports < JABBER_MAX_STUN_PORTS - 1) { if (packet->payload[5] == 'o') { src->jabber_voice_stun_port[src->jabber_voice_stun_used_ports++] = j_port; } else { if (src->jabber_file_transfer_port[0] == 0 || src->jabber_file_transfer_port[0] == j_port) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "src->jabber_file_transfer_port[0] = j_port = %u;\n", ntohs(j_port)); src->jabber_file_transfer_port[0] = j_port; } else { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "src->jabber_file_transfer_port[1] = j_port = %u;\n", ntohs(j_port)); src->jabber_file_transfer_port[1] = j_port; } } } if (dst != NULL && dst->jabber_voice_stun_used_ports < JABBER_MAX_STUN_PORTS - 1) { if (packet->payload[5] == 'o') { dst->jabber_voice_stun_port[dst->jabber_voice_stun_used_ports++] = j_port; } else { if (dst->jabber_file_transfer_port[0] == 0 || dst->jabber_file_transfer_port[0] == j_port) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "dst->jabber_file_transfer_port[0] = j_port = %u;\n", ntohs(j_port)); dst->jabber_file_transfer_port[0] = j_port; } else { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "dst->jabber_file_transfer_port[1] = j_port = %u;\n", ntohs(j_port)); dst->jabber_file_transfer_port[1] = j_port; } } } return; } } } } return; } /* search for jabber here */ /* this part is working asymmetrically */ if ((packet->payload_packet_len > 13 && memcmp(packet->payload, "<?xml version=", 14) == 0) || (packet->payload_packet_len >= NDPI_STATICSTRING_LEN("<stream:stream ") && memcmp(packet->payload, "<stream:stream ", NDPI_STATICSTRING_LEN("<stream:stream ")) == 0)) { int start = packet->payload_packet_len-13; if(ndpi_strnstr((const char *)&packet->payload[13], "xmlns:stream='http://etherx.jabber.org/streams'", start) || ndpi_strnstr((const char *)&packet->payload[13], "xmlns:stream=\"http://etherx.jabber.org/streams\"", start)) { /* Protocol family */ ndpi_int_jabber_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_UNENCRYPED_JABBER); /* search for subprotocols */ check_content_type_and_change_protocol(ndpi_struct, flow, 13); return; } } if (flow->packet_counter < 3) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "packet_counter: %u\n", flow->packet_counter); return; } NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_TRACE, "JABBER Excluded.\n"); NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_UNENCRYPED_JABBER); #ifdef NDPI_PROTOCOL_TRUPHONE NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_TRUPHONE); #endif }
void ipoque_search_jabber_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; u16 x; IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "search jabber.\n"); /* search for jabber file transfer */ /* this part is working asymmetrically */ if (packet->tcp != NULL && packet->tcp->syn != 0 && packet->payload_packet_len == 0) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "check jabber syn\n"); if (src != NULL && src->jabber_file_transfer_port[0] != 0) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "src jabber ft port set, ports are: %u, %u\n", ntohs(src->jabber_file_transfer_port[0]), ntohs(src->jabber_file_transfer_port[1])); if (((IPOQUE_TIMESTAMP_COUNTER_SIZE) (packet->tick_timestamp - src->jabber_stun_or_ft_ts)) >= ipoque_struct->jabber_file_transfer_timeout) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "JABBER src stun timeout %u %u\n", src->jabber_stun_or_ft_ts, packet->tick_timestamp); src->jabber_file_transfer_port[0] = 0; src->jabber_file_transfer_port[1] = 0; } else if (src->jabber_file_transfer_port[0] == packet->tcp->dest || src->jabber_file_transfer_port[0] == packet->tcp->source || src->jabber_file_transfer_port[1] == packet->tcp->dest || src->jabber_file_transfer_port[1] == packet->tcp->source) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "found jabber file transfer.\n"); ipoque_int_jabber_add_connection(ipoque_struct, IPOQUE_PROTOCOL_UNENCRYPED_JABBER, IPOQUE_CORRELATED_PROTOCOL); } } if (dst != NULL && dst->jabber_file_transfer_port[0] != 0) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "dst jabber ft port set, ports are: %u, %u\n", ntohs(dst->jabber_file_transfer_port[0]), ntohs(dst->jabber_file_transfer_port[1])); if (((IPOQUE_TIMESTAMP_COUNTER_SIZE) (packet->tick_timestamp - dst->jabber_stun_or_ft_ts)) >= ipoque_struct->jabber_file_transfer_timeout) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "JABBER dst stun timeout %u %u\n", dst->jabber_stun_or_ft_ts, packet->tick_timestamp); dst->jabber_file_transfer_port[0] = 0; dst->jabber_file_transfer_port[1] = 0; } else if (dst->jabber_file_transfer_port[0] == packet->tcp->dest || dst->jabber_file_transfer_port[0] == packet->tcp->source || dst->jabber_file_transfer_port[1] == packet->tcp->dest || dst->jabber_file_transfer_port[1] == packet->tcp->source) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "found jabber file transfer.\n"); ipoque_int_jabber_add_connection(ipoque_struct, IPOQUE_PROTOCOL_UNENCRYPED_JABBER, IPOQUE_CORRELATED_PROTOCOL); } } return; } if (packet->tcp != 0 && packet->payload_packet_len == 0) { return; } /* this part parses a packet and searches for port=. it works asymmetrically. */ if (packet->detected_protocol_stack[0] == IPOQUE_PROTOCOL_UNENCRYPED_JABBER) { u16 lastlen; u16 j_port = 0; /* check for google jabber voip connections ... */ /* need big packet */ if (packet->payload_packet_len < 100) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "packet too small, return.\n"); return; } /* need message to or type for file-transfer */ if (memcmp(packet->payload, "<iq from=\"", 8) == 0 || memcmp(packet->payload, "<iq from=\'", 8) == 0) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "JABBER <iq from=\".\n"); lastlen = packet->payload_packet_len - 11; for (x = 10; x < lastlen; x++) { if (packet->payload[x] == 'p') { if (ipq_mem_cmp(&packet->payload[x], "port=", 5) == 0) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "port=\n"); if (src != NULL) { src->jabber_stun_or_ft_ts = packet->tick_timestamp; } if (dst != NULL) { dst->jabber_stun_or_ft_ts = packet->tick_timestamp; } x += 6; j_port = ntohs_ipq_bytestream_to_number(&packet->payload[x], packet->payload_packet_len, &x); IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "JABBER port : %u\n", ntohs(j_port)); if (src != NULL) { if (src->jabber_file_transfer_port[0] == 0 || src->jabber_file_transfer_port[0] == j_port) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "src->jabber_file_transfer_port[0] = j_port = %u;\n", ntohs(j_port)); src->jabber_file_transfer_port[0] = j_port; } else { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "src->jabber_file_transfer_port[1] = j_port = %u;\n", ntohs(j_port)); src->jabber_file_transfer_port[1] = j_port; } } if (dst != NULL) { if (dst->jabber_file_transfer_port[0] == 0 || dst->jabber_file_transfer_port[0] == j_port) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "dst->jabber_file_transfer_port[0] = j_port = %u;\n", ntohs(j_port)); dst->jabber_file_transfer_port[0] = j_port; } else { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "dst->jabber_file_transfer_port[1] = j_port = %u;\n", ntohs(j_port)); dst->jabber_file_transfer_port[1] = j_port; } } } } } } else if (memcmp(packet->payload, "<iq to=\"", 8) == 0 || memcmp(packet->payload, "<iq to=\'", 8) == 0 || memcmp(packet->payload, "<iq type=", 9) == 0) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "JABBER <iq to=\"/type=\"\n"); lastlen = packet->payload_packet_len - 21; for (x = 8; x < lastlen; x++) { /* invalid character */ if (packet->payload[x] < 32 || packet->payload[x] > 127) { return; } if (packet->payload[x] == '@') { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "JABBER @\n"); break; } } if (x >= lastlen) { return; } lastlen = packet->payload_packet_len - 10; for (; x < lastlen; x++) { if (packet->payload[x] == 'p') { if (ipq_mem_cmp(&packet->payload[x], "port=", 5) == 0) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "port=\n"); if (src != NULL) { src->jabber_stun_or_ft_ts = packet->tick_timestamp; } if (dst != NULL) { dst->jabber_stun_or_ft_ts = packet->tick_timestamp; } x += 6; j_port = ntohs_ipq_bytestream_to_number(&packet->payload[x], packet->payload_packet_len, &x); IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "JABBER port : %u\n", ntohs(j_port)); if (src != NULL && src->jabber_voice_stun_used_ports < JABBER_MAX_STUN_PORTS - 1) { if (packet->payload[5] == 'o') { src->jabber_voice_stun_port[src->jabber_voice_stun_used_ports++] = j_port; } else { if (src->jabber_file_transfer_port[0] == 0 || src->jabber_file_transfer_port[0] == j_port) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "src->jabber_file_transfer_port[0] = j_port = %u;\n", ntohs(j_port)); src->jabber_file_transfer_port[0] = j_port; } else { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "src->jabber_file_transfer_port[1] = j_port = %u;\n", ntohs(j_port)); src->jabber_file_transfer_port[1] = j_port; } } } if (dst != NULL && dst->jabber_voice_stun_used_ports < JABBER_MAX_STUN_PORTS - 1) { if (packet->payload[5] == 'o') { dst->jabber_voice_stun_port[dst->jabber_voice_stun_used_ports++] = j_port; } else { if (dst->jabber_file_transfer_port[0] == 0 || dst->jabber_file_transfer_port[0] == j_port) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "dst->jabber_file_transfer_port[0] = j_port = %u;\n", ntohs(j_port)); dst->jabber_file_transfer_port[0] = j_port; } else { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "dst->jabber_file_transfer_port[1] = j_port = %u;\n", ntohs(j_port)); dst->jabber_file_transfer_port[1] = j_port; } } } return; } } } } return; } /* search for jabber here */ /* this part is working asymmetrically */ if ((packet->payload_packet_len > 13 && memcmp(packet->payload, "<?xml version=", 14) == 0) || (packet->payload_packet_len >= IPQ_STATICSTRING_LEN("<stream:stream ") && memcmp(packet->payload, "<stream:stream ", IPQ_STATICSTRING_LEN("<stream:stream ")) == 0)) { if (packet->payload_packet_len > 47) { const u16 lastlen = packet->payload_packet_len - 47; for (x = 0; x < lastlen; x++) { if (ipq_mem_cmp (&packet->payload[x], "xmlns:stream='http://etherx.jabber.org/streams'", 47) == 0 || ipq_mem_cmp(&packet->payload[x], "xmlns:stream=\"http://etherx.jabber.org/streams\"", 47) == 0) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_TRACE, "found JABBER.\n"); x += 47; ipoque_int_jabber_add_connection(ipoque_struct, IPOQUE_PROTOCOL_UNENCRYPED_JABBER, IPOQUE_REAL_PROTOCOL); /* search for other protocols: Truphone */ check_content_type_and_change_protocol(ipoque_struct, x); return; } } } } if (flow->packet_counter < 3) { IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_TRACE, "packet_counter: %u\n", flow->packet_counter); return; } IPQ_LOG(IPOQUE_PROTOCOL_UNENCRYPED_JABBER, ipoque_struct, IPQ_LOG_DEBUG, "Excluding jabber connection\n"); IPOQUE_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, IPOQUE_PROTOCOL_UNENCRYPED_JABBER); #ifdef IPOQUE_PROTOCOL_TRUPHONE IPOQUE_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, IPOQUE_PROTOCOL_TRUPHONE); #endif }