int sip_validate_packet(packet_t *packet) { uint32_t plen = packet_payloadlen(packet); u_char payload[MAX_SIP_PAYLOAD]; regmatch_t pmatch[3]; char cl_header[10]; int content_len; int bodylen; // Max SIP payload allowed if (plen == 0 || plen > MAX_SIP_PAYLOAD) return VALIDATE_NOT_SIP; // Get payload from packet(s) memset(payload, 0, MAX_SIP_PAYLOAD); memcpy(payload, packet_payload(packet), plen); // Initialize variables memset(cl_header, 0, sizeof(cl_header)); // Check if the first line follows SIP request or response format if (regexec(&calls.reg_valid, (const char *) payload, 2, pmatch, 0) != 0) { // Not a SIP message AT ALL return VALIDATE_NOT_SIP; } // Check if we have Content Length header if (regexec(&calls.reg_cl, (const char *) payload, 4, pmatch, 0) != 0) { // Not a SIP message or not complete return VALIDATE_PARTIAL_SIP; } strncpy(cl_header, (const char *)payload + pmatch[2].rm_so, (int)pmatch[2].rm_eo - pmatch[2].rm_so); content_len = atoi(cl_header); // Check if we have Body separator field if (regexec(&calls.reg_body, (const char *) payload, 2, pmatch, 0) != 0) { // Not a SIP message or not complete return VALIDATE_PARTIAL_SIP; } // Get the SIP message body length bodylen = (int) pmatch[1].rm_eo - pmatch[1].rm_so; // The SDP body of the SIP message ends in another packet if (content_len > bodylen) { return VALIDATE_PARTIAL_SIP; } if (content_len < bodylen) { // We got more than one SIP message in the same packet packet_set_payload(packet, payload, pmatch[1].rm_so + content_len); return VALIDATE_MULTIPLE_SIP; } // We got all the SDP body of the SIP message return VALIDATE_COMPLETE_SIP; }
END_TEST /* Packet->payload */ START_TEST(test_packet_payload) { fail_unless((packet_payload(packet) != NULL), "packet_payload returned NULL"); }
struct tcp_option *tcp_options_begin( struct packet *packet, struct tcp_options_iterator *iter) { memset(iter, 0, sizeof(*iter)); iter->current_option = packet_tcp_options(packet); iter->options_end = packet_payload(packet); return get_current_option(iter); }
struct sctp_chunk *sctp_chunks_begin(struct packet *packet, struct sctp_chunks_iterator *iter, char **error) { assert(*error == NULL); memset(iter, 0, sizeof(*iter)); iter->current_chunk = packet_payload(packet); iter->packet_end = packet_end(packet); return get_current_chunk(iter, error); }
sip_msg_t * sip_check_packet(packet_t *packet) { sip_msg_t *msg; sip_call_t *call; char callid[1024], xcallid[1024]; address_t src, dst; u_char payload[MAX_SIP_PAYLOAD]; bool newcall = false; // Max SIP payload allowed if (packet->payload_len > MAX_SIP_PAYLOAD) return NULL; // Get Addresses from packet src = packet->src; dst = packet->dst; // Initialize local variables memset(callid, 0, sizeof(callid)); memset(xcallid, 0, sizeof(xcallid)); // Get payload from packet(s) memset(payload, 0, MAX_SIP_PAYLOAD); memcpy(payload, packet_payload(packet), packet_payloadlen(packet)); // Get the Call-ID of this message if (!sip_get_callid((const char*) payload, callid)) return NULL; // Create a new message from this data if (!(msg = msg_create((const char*) payload))) return NULL; // Get Method and request for the following checks // There is no need to parse all payload at this point // If no response or request code is found, this is not a SIP message if (!sip_get_msg_reqresp(msg, payload)) { // Deallocate message memory msg_destroy(msg); return NULL; } // Find the call for this msg if (!(call = sip_find_by_callid(callid))) { // Check if payload matches expression if (!sip_check_match_expression((const char*) payload)) goto skip_message; // User requested only INVITE starting dialogs if (calls.only_calls && msg->reqresp != SIP_METHOD_INVITE) goto skip_message; // Only create a new call if the first msg // is a request message in the following gorup if (calls.ignore_incomplete && msg->reqresp > SIP_METHOD_MESSAGE) goto skip_message; // Get the Call-ID of this message sip_get_xcallid((const char*) payload, xcallid); // Rotate call list if limit has been reached if (calls.limit == sip_calls_count()) sip_calls_rotate(); // Create the call if not found if (!(call = call_create(callid, xcallid))) goto skip_message; // Add this Call-Id to hash table htable_insert(calls.callids, call->callid, call); // Set call index call->index = ++calls.last_index; // Mark this as a new call newcall = true; } // At this point we know we're handling an interesting SIP Packet msg->packet = packet; // Always parse first call message if (call_msg_count(call) == 0) { // Parse SIP payload sip_parse_msg_payload(msg, payload); // If this call has X-Call-Id, append it to the parent call if (strlen(call->xcallid)) { call_add_xcall(sip_find_by_callid(call->xcallid), call); } } // Add the message to the call call_add_message(call, msg); if (call_is_invite(call)) { // Parse media data sip_parse_msg_media(msg, payload); // Update Call State call_update_state(call, msg); // Check if this call should be in active call list if (call_is_active(call)) { if (sip_call_is_active(call)) { vector_append(calls.active, call); } } else { if (sip_call_is_active(call)) { vector_remove(calls.active, call); } } } if (newcall) { // Append this call to the call list vector_append(calls.list, call); } // Mark the list as changed calls.changed = true; // Return the loaded message return msg; skip_message: // Deallocate message memory msg_destroy(msg); return NULL; }
int capture_ws_check_packet(packet_t *packet) { int ws_off = 0; u_char ws_fin; u_char ws_opcode; u_char ws_mask; uint8_t ws_len; u_char ws_mask_key[4]; u_char *payload, *newpayload; uint32_t size_payload; int i; /** * WSocket header definition according to RFC 6455 * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-------+-+-------------+-------------------------------+ * |F|R|R|R| opcode|M| Payload len | Extended payload length | * |I|S|S|S| (4) |A| (7) | (16/64) | * |N|V|V|V| |S| | (if payload len==126/127) | * | |1|2|3| |K| | | * +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + * | Extended payload length continued, if payload len == 127 | * + - - - - - - - - - - - - - - - +-------------------------------+ * | |Masking-key, if MASK set to 1 | * +-------------------------------+-------------------------------+ * | Masking-key (continued) | Payload Data | * +-------------------------------- - - - - - - - - - - - - - - - + * : Payload Data continued ... : * + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * | Payload Data continued ... | * +---------------------------------------------------------------+ */ // Get payload from packet(s) size_payload = packet_payloadlen(packet); payload = packet_payload(packet); // Check we have payload if (size_payload == 0) return 0; // Flags && Opcode ws_fin = (*payload & WH_FIN) >> 4; ws_opcode = *payload & WH_OPCODE; ws_off++; // Only interested in Ws text packets if (ws_opcode != WS_OPCODE_TEXT) return 0; // Masked flag && Payload len ws_mask = (*(payload + ws_off) & WH_MASK) >> 4; ws_len = (*(payload + ws_off) & WH_LEN); ws_off++; // Skip Payload len switch (ws_len) { // Extended case 126: ws_off += 2; break; case 127: ws_off += 8; break; default: return 0; } // Get Masking key if mask is enabled if (ws_mask) { memcpy(ws_mask_key, (payload + ws_off), 4); ws_off += 4; } // Skip Websocket headers size_payload -= ws_off; if ((int32_t) size_payload <= 0) return 0; newpayload = sng_malloc(size_payload); memcpy(newpayload, payload + ws_off, size_payload); // If mask is enabled, unmask the payload if (ws_mask) { for (i = 0; i < size_payload; i++) newpayload[i] = newpayload[i] ^ ws_mask_key[i % 4]; } // Set new packet payload into the packet packet_set_payload(packet, newpayload, size_payload); // Free the new payload sng_free(newpayload); if (packet->type == PACKET_SIP_TLS) { packet_set_type(packet, PACKET_SIP_WSS); } else { packet_set_type(packet, PACKET_SIP_WS); } return 1; }
int capture_eep_send_v3(packet_t *pkt) { struct hep_generic *hg = NULL; void* buffer; uint32_t buflen = 0, iplen = 0, tlen = 0; hep_chunk_ip4_t src_ip4, dst_ip4; #ifdef USE_IPV6 hep_chunk_ip6_t src_ip6, dst_ip6; #endif hep_chunk_t payload_chunk; hep_chunk_t authkey_chunk; frame_t *frame = vector_first(pkt->frames); unsigned char *data = packet_payload(pkt); uint32_t len = packet_payloadlen(pkt); hg = sng_malloc(sizeof(struct hep_generic)); /* header set "HEP3" */ memcpy(hg->header.id, "\x48\x45\x50\x33", 4); /* IP proto */ hg->ip_family.chunk.vendor_id = htons(0x0000); hg->ip_family.chunk.type_id = htons(0x0001); hg->ip_family.data = pkt->ip_version == 4 ? AF_INET : AF_INET6; hg->ip_family.chunk.length = htons(sizeof(hg->ip_family)); /* Proto ID */ hg->ip_proto.chunk.vendor_id = htons(0x0000); hg->ip_proto.chunk.type_id = htons(0x0002); hg->ip_proto.data = pkt->proto; hg->ip_proto.chunk.length = htons(sizeof(hg->ip_proto)); /* IPv4 */ if (pkt->ip_version == 4) { /* SRC IP */ src_ip4.chunk.vendor_id = htons(0x0000); src_ip4.chunk.type_id = htons(0x0003); inet_pton(AF_INET, pkt->src.ip, &src_ip4.data); src_ip4.chunk.length = htons(sizeof(src_ip4)); /* DST IP */ dst_ip4.chunk.vendor_id = htons(0x0000); dst_ip4.chunk.type_id = htons(0x0004); inet_pton(AF_INET, pkt->dst.ip, &dst_ip4.data); dst_ip4.chunk.length = htons(sizeof(dst_ip4)); iplen = sizeof(dst_ip4) + sizeof(src_ip4); } #ifdef USE_IPV6 /* IPv6 */ else if(pkt->ip_version == 6) { /* SRC IPv6 */ src_ip6.chunk.vendor_id = htons(0x0000); src_ip6.chunk.type_id = htons(0x0005); inet_pton(AF_INET6, pkt->src.ip, &src_ip6.data); src_ip6.chunk.length = htons(sizeof(src_ip6)); /* DST IPv6 */ dst_ip6.chunk.vendor_id = htons(0x0000); dst_ip6.chunk.type_id = htons(0x0006); inet_pton(AF_INET6, pkt->dst.ip, &dst_ip6.data); dst_ip6.chunk.length = htons(sizeof(dst_ip6)); iplen = sizeof(dst_ip6) + sizeof(src_ip6); } #endif /* SRC PORT */ hg->src_port.chunk.vendor_id = htons(0x0000); hg->src_port.chunk.type_id = htons(0x0007); hg->src_port.data = htons(pkt->src.port); hg->src_port.chunk.length = htons(sizeof(hg->src_port)); /* DST PORT */ hg->dst_port.chunk.vendor_id = htons(0x0000); hg->dst_port.chunk.type_id = htons(0x0008); hg->dst_port.data = htons(pkt->dst.port); hg->dst_port.chunk.length = htons(sizeof(hg->dst_port)); /* TIMESTAMP SEC */ hg->time_sec.chunk.vendor_id = htons(0x0000); hg->time_sec.chunk.type_id = htons(0x0009); hg->time_sec.data = htonl(frame->header->ts.tv_sec); hg->time_sec.chunk.length = htons(sizeof(hg->time_sec)); /* TIMESTAMP USEC */ hg->time_usec.chunk.vendor_id = htons(0x0000); hg->time_usec.chunk.type_id = htons(0x000a); hg->time_usec.data = htonl(frame->header->ts.tv_usec); hg->time_usec.chunk.length = htons(sizeof(hg->time_usec)); /* Protocol TYPE */ hg->proto_t.chunk.vendor_id = htons(0x0000); hg->proto_t.chunk.type_id = htons(0x000b); hg->proto_t.data = 1; hg->proto_t.chunk.length = htons(sizeof(hg->proto_t)); /* Capture ID */ hg->capt_id.chunk.vendor_id = htons(0x0000); hg->capt_id.chunk.type_id = htons(0x000c); hg->capt_id.data = htons(eep_cfg.capt_id); hg->capt_id.chunk.length = htons(sizeof(hg->capt_id)); /* Payload */ payload_chunk.vendor_id = htons(0x0000); payload_chunk.type_id = htons(0x000f); payload_chunk.length = htons(sizeof(payload_chunk) + len); tlen = sizeof(struct hep_generic) + len + iplen + sizeof(hep_chunk_t); /* auth key */ if (eep_cfg.capt_password != NULL) { tlen += sizeof(hep_chunk_t); /* Auth key */ authkey_chunk.vendor_id = htons(0x0000); authkey_chunk.type_id = htons(0x000e); authkey_chunk.length = htons(sizeof(authkey_chunk) + strlen(eep_cfg.capt_password)); tlen += strlen(eep_cfg.capt_password); } /* total */ hg->header.length = htons(tlen); if (!(buffer = sng_malloc(tlen))) { sng_free(hg); return 1; } memcpy((void*) buffer, hg, sizeof(struct hep_generic)); buflen = sizeof(struct hep_generic); /* IPv4 */ if (pkt->ip_version == 4) { /* SRC IP */ memcpy((void*) buffer + buflen, &src_ip4, sizeof(struct hep_chunk_ip4)); buflen += sizeof(struct hep_chunk_ip4); memcpy((void*) buffer + buflen, &dst_ip4, sizeof(struct hep_chunk_ip4)); buflen += sizeof(struct hep_chunk_ip4); } #ifdef USE_IPV6 /* IPv6 */ else if(pkt->ip_version == 6) { /* SRC IPv6 */ memcpy((void*) buffer+buflen, &src_ip4, sizeof(struct hep_chunk_ip6)); buflen += sizeof(struct hep_chunk_ip6); memcpy((void*) buffer+buflen, &dst_ip6, sizeof(struct hep_chunk_ip6)); buflen += sizeof(struct hep_chunk_ip6); } #endif /* AUTH KEY CHUNK */ if (eep_cfg.capt_password != NULL) { memcpy((void*) buffer + buflen, &authkey_chunk, sizeof(struct hep_chunk)); buflen += sizeof(struct hep_chunk); /* Now copying payload self */ memcpy((void*) buffer + buflen, eep_cfg.capt_password, strlen(eep_cfg.capt_password)); buflen += strlen(eep_cfg.capt_password); } /* PAYLOAD CHUNK */ memcpy((void*) buffer + buflen, &payload_chunk, sizeof(struct hep_chunk)); buflen += sizeof(struct hep_chunk); /* Now copying payload itself */ memcpy((void*) buffer + buflen, data, len); buflen += len; if (send(eep_cfg.client_sock, buffer, buflen, 0) == -1) { return 1; } /* FREE */ sng_free(buffer); sng_free(hg); return 0; }
int capture_eep_send_v2(packet_t *pkt) { void* buffer; uint32_t buflen = 0, tlen = 0; struct hep_hdr hdr; struct hep_timehdr hep_time; struct hep_iphdr hep_ipheader; #ifdef USE_IPV6 struct hep_ip6hdr hep_ip6header; #endif unsigned char *data = packet_payload(pkt); uint32_t len = packet_payloadlen(pkt); frame_t *frame = vector_first(pkt->frames); /* Version && proto */ hdr.hp_v = 2; hdr.hp_f = pkt->ip_version == 4 ? AF_INET : AF_INET6; hdr.hp_p = pkt->proto; hdr.hp_sport = htons(pkt->src.port); hdr.hp_dport = htons(pkt->dst.port); /* Timestamp */ hep_time.tv_sec = frame->header->ts.tv_sec; hep_time.tv_usec = frame->header->ts.tv_usec; hep_time.captid = eep_cfg.capt_id; /* Calculate initial HEP packet size */ tlen = sizeof(struct hep_hdr) + sizeof(struct hep_timehdr); /* IPv4 */ if (pkt->ip_version == 4) { inet_pton(AF_INET, pkt->src.ip, &hep_ipheader.hp_src); inet_pton(AF_INET, pkt->dst.ip, &hep_ipheader.hp_dst); tlen += sizeof(struct hep_iphdr); hdr.hp_l += sizeof(struct hep_iphdr); } #ifdef USE_IPV6 /* IPv6 */ else if(pkt->ip_version == 6) { inet_pton(AF_INET6, pkt->src.ip, &hep_ip6header.hp6_src); inet_pton(AF_INET6, pkt->dst.ip, &hep_ip6header.hp6_dst); tlen += sizeof(struct hep_ip6hdr); hdr.hp_l += sizeof(struct hep_ip6hdr); } #endif // Add payload size to the final size of HEP packet tlen += len; hdr.hp_l = htons(tlen); // Allocate memory for HEPv2 packet if (!(buffer = sng_malloc(tlen))) return 1; // Copy basic headers buflen = 0; memcpy((void*) buffer + buflen, &hdr, sizeof(struct hep_hdr)); buflen += sizeof(struct hep_hdr); // Copy IP header if (pkt->ip_version == 4) { memcpy((void*) buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr)); buflen += sizeof(struct hep_iphdr); } #ifdef USE_IPV6 else if(pkt->ip_version == 6) { memcpy((void*) buffer + buflen, &hep_ip6header, sizeof(struct hep_ip6hdr)); buflen += sizeof(struct hep_ip6hdr); } #endif // Copy TImestamp header memcpy((void*) buffer + buflen, &hep_time, sizeof(struct hep_timehdr)); buflen += sizeof(struct hep_timehdr); // Now copy payload itself memcpy((void*) buffer + buflen, data, len); buflen += len; if (send(eep_cfg.client_sock, buffer, buflen, 0) == -1) { return 1; } /* FREE */ sng_free(buffer); return 1; }
int tls_process_segment(packet_t *packet, struct tcphdr *tcp) { struct SSLConnection *conn; const u_char *payload = packet_payload(packet); uint32_t size_payload = packet_payloadlen(packet); uint8_t *out; uint32_t outl = packet->payload_len; out = sng_malloc(outl); struct in_addr ip_src, ip_dst; uint16_t sport = packet->src.port; uint16_t dport = packet->dst.port; // Convert addresses inet_pton(AF_INET, packet->src.ip, &ip_src); inet_pton(AF_INET, packet->dst.ip, &ip_dst); // Try to find a session for this ip if ((conn = tls_connection_find(ip_src, sport))) { // Update last connection direction conn->direction = tls_connection_dir(conn, ip_src, sport); // Check current connection state switch (conn->state) { case TCP_STATE_SYN: // First SYN received, this package must be SYN/ACK if (tcp->th_flags & TH_SYN & ~TH_ACK) conn->state = TCP_STATE_SYN_ACK; break; case TCP_STATE_SYN_ACK: // We expect an ACK packet here if (tcp->th_flags & ~TH_SYN & TH_ACK) conn->state = TCP_STATE_ESTABLISHED; break; case TCP_STATE_ACK: case TCP_STATE_ESTABLISHED: // Process data segment! if (tls_process_record(conn, payload, size_payload, &out, &outl) == 0) { if ((int32_t) outl > 0) { packet_set_payload(packet, out, outl); packet_set_type(packet, PACKET_SIP_TLS); return 0; } } break; case TCP_STATE_FIN: case TCP_STATE_CLOSED: // We can delete this connection tls_connection_destroy(conn); break; } } else { if (tcp->th_flags & TH_SYN & ~TH_ACK) { // New connection, store it status and leave tls_connection_create(ip_src, sport, ip_dst, dport); } } sng_free(out); return 0; }