Example #1
0
File: sip.c Project: irontec/sngrep
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);
}
Example #4
0
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);
}
Example #5
0
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;

}
Example #6
0
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;
}
Example #7
0
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;
}
Example #8
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;
}
Example #9
0
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;
}