Exemple #1
0
static int decode_ftp(packet_t *p, const _uint8 *bytes, size_t len)
{
  header_t *h = packet_append_header(p, PROTO_NAME_FTP, (void *)bytes, len);
  packet_set_payload(p, h);

  return DECODE_OK;
}
Exemple #2
0
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;
}
Exemple #3
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;
}
Exemple #4
0
packet_t *
capture_packet_reasm_tcp(packet_t *packet, struct tcphdr *tcp, u_char *payload, int size_payload) {

    vector_iter_t it = vector_iterator(capture_cfg.tcp_reasm);
    packet_t *pkt;
    u_char *new_payload;

    //! Assembled
    if ((int32_t) size_payload <= 0)
        return packet;

    while ((pkt = vector_iterator_next(&it))) {
        if (addressport_equals(pkt->src, packet->src) &&
                addressport_equals(pkt->dst, packet->dst)) {
            break;
        }
    }

    // If we already have this packet stored
    if (pkt) {
        frame_t *frame;
        // Append this frames to the original packet
        vector_iter_t frames = vector_iterator(packet->frames);
        while ((frame = vector_iterator_next(&frames)))
            packet_add_frame(pkt, frame->header, frame->data);
        // Destroy current packet as its frames belong to the stored packet
        packet_destroy(packet);
    } else {
        // First time this packet has been seen
        pkt = packet;
        // Add To the possible reassembly list
        vector_append(capture_cfg.tcp_reasm, packet);
    }

    // Store firt tcp sequence
    if (pkt->tcp_seq == 0) {
        pkt->tcp_seq = ntohl(tcp->th_seq);
    }

    // If the first frame of this packet
    if (vector_count(pkt->frames) == 1) {
        // Set initial payload
        packet_set_payload(pkt, payload, size_payload);
    } else {
        // Check payload length. Dont handle too big payload packets
        if (pkt->payload_len + size_payload > MAX_CAPTURE_LEN) {
            packet_destroy(pkt);
            vector_remove(capture_cfg.tcp_reasm, pkt);
            return NULL;
        }
        new_payload = sng_malloc(pkt->payload_len + size_payload);
        if (pkt->tcp_seq < ntohl(tcp->th_seq)) {
            // Append payload to the existing
            pkt->tcp_seq =  ntohl(tcp->th_seq);
            memcpy(new_payload, pkt->payload, pkt->payload_len);
            memcpy(new_payload + pkt->payload_len, payload, size_payload);
        } else {
            // Prepend payload to the existing
            memcpy(new_payload, payload, size_payload);
            memcpy(new_payload + size_payload, pkt->payload, pkt->payload_len);
        }
        packet_set_payload(pkt, new_payload, pkt->payload_len + size_payload);
        sng_free(new_payload);

    }

    // This packet is ready to be parsed
    int valid = sip_validate_packet(pkt);
    if (valid == VALIDATE_COMPLETE_SIP) {
        // Full SIP packet!
        vector_remove(capture_cfg.tcp_reasm, pkt);
        return pkt;
    } else if (valid == VALIDATE_NOT_SIP) {
        vector_remove(capture_cfg.tcp_reasm, pkt);
        return pkt;
    }

    // An incomplete SIP Packet
    return NULL;
}
Exemple #5
0
void
parse_packet(u_char *info, const struct pcap_pkthdr *header, const u_char *packet)
{
    // Capture info
    capture_info_t *capinfo = (capture_info_t *) info;
    // UDP header data
    struct udphdr *udp;
    // UDP header size
    uint16_t udp_off;
    // TCP header data
    struct tcphdr *tcp;
    // TCP header size
    uint16_t tcp_off;
    // Packet data
    u_char data[MAX_CAPTURE_LEN];
    // Packet payload data
    u_char *payload = NULL;
    // Whole packet size
    uint32_t size_capture = header->caplen;
    // Packet payload size
    uint32_t size_payload =  size_capture - capinfo->link_hl;
    // Captured packet info
    packet_t *pkt;

    // Ignore packets while capture is paused
    if (capture_paused())
        return;

    // Check if we have reached capture limit
    if (capture_cfg.limit && sip_calls_count() >= capture_cfg.limit)
        return;

    // Check maximum capture length
    if (header->caplen > MAX_CAPTURE_LEN)
        return;

    // Copy packet payload
    memcpy(data, packet, header->caplen);

    // Check if we have a complete IP packet
    if (!(pkt = capture_packet_reasm_ip(capinfo, header, data, &size_payload, &size_capture)))
        return;

    // Only interested in UDP packets
    if (pkt->proto == IPPROTO_UDP) {
        // Get UDP header
        udp = (struct udphdr *)((u_char *)(data) + (size_capture - size_payload));
        udp_off = sizeof(struct udphdr);

        // Set packet ports
        pkt->src.port = htons(udp->uh_sport);
        pkt->dst.port = htons(udp->uh_dport);

        // Remove UDP Header from payload
        size_payload -= udp_off;

        if ((int32_t)size_payload < 0)
            size_payload = 0;

        // Remove TCP Header from payload
        payload = (u_char *) (udp) + udp_off;

        // Complete packet with Transport information
        packet_set_type(pkt, PACKET_SIP_UDP);
        packet_set_payload(pkt, payload, size_payload);

    } else if (pkt->proto == IPPROTO_TCP) {
        // Get TCP header
        tcp = (struct tcphdr *)((u_char *)(data) + (size_capture - size_payload));
        tcp_off = (tcp->th_off * 4);

        // Set packet ports
        pkt->src.port = htons(tcp->th_sport);
        pkt->dst.port = htons(tcp->th_dport);

        // Get actual payload size
        size_payload -= tcp_off;

        if ((int32_t)size_payload < 0)
            size_payload = 0;

        // Get payload start
        payload = (u_char *)(tcp) + tcp_off;

        // Complete packet with Transport information
        packet_set_type(pkt, PACKET_SIP_TCP);
        packet_set_payload(pkt, payload, size_payload);

        // Create a structure for this captured packet
        if (!(pkt = capture_packet_reasm_tcp(pkt, tcp, payload, size_payload)))
            return;

#if defined(WITH_GNUTLS) || defined(WITH_OPENSSL)
        // Check if packet is TLS
        if (capture_cfg.keyfile) {
            tls_process_segment(pkt, tcp);
        }
#endif

        // Check if packet is WS or WSS
        capture_ws_check_packet(pkt);
    } else {
        // Not handled protocol
        packet_destroy(pkt);
        return;
    }

    // Avoid parsing from multiples sources.
    // Avoid parsing while screen in being redrawn
    capture_lock();
    // Check if we can handle this packet
    if (capture_packet_parse(pkt) == 0) {
#ifdef USE_EEP
        // Send this packet through eep
        capture_eep_send(pkt);
#endif
        // Store this packets in output file
        dump_packet(capture_cfg.pd, pkt);
        // If storage is disabled, delete frames payload
        if (capture_cfg.storage == 0) {
            packet_free_frames(pkt);
        }
        // Allow Interface refresh and user input actions
        capture_unlock();
        return;
    }

    // Not an interesting packet ...
    packet_destroy(pkt);
    // Allow Interface refresh and user input actions
    capture_unlock();
}
Exemple #6
0
packet_t *
capture_eep_receive_v3()
{

    struct hep_generic hg;
    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;
    uint8_t family, proto;
    char password[100];
    int password_len;
    unsigned char *payload = 0;
    uint32_t len, pos;
    char buffer[MAX_CAPTURE_LEN] ;
    //! Source and Destination Address
    address_t src, dst;
    //! EEP client data
    struct sockaddr eep_client;
    socklen_t eep_client_len;
    //! Packet header
    struct pcap_pkthdr header;
    //! New created packet pointer
    packet_t *pkt;

    /* Receive EEP generic header */
    if (recvfrom(eep_cfg.server_sock, buffer, MAX_CAPTURE_LEN, 0, &eep_client, &eep_client_len) == -1)
        return NULL;

    /* Copy initial bytes to EEP Generic header */
    memcpy(&hg, buffer, sizeof(struct hep_generic));

    /* header check */
    if (memcmp(hg.header.id, "\x48\x45\x50\x33", 4) != 0)
        return NULL;

    /* IP proto */
    family = hg.ip_family.data;
    /* Proto ID */
    proto = hg.ip_proto.data;

    len = ntohs(hg.header.length) - sizeof(struct hep_generic);
    pos = sizeof(struct hep_generic);

    /* IPv4 */
    if (family == AF_INET) {
        /* SRC IP */
        memcpy(&src_ip4, (void*) buffer + pos, sizeof(struct hep_chunk_ip4));
        inet_ntop(AF_INET, &src_ip4.data, src.ip, sizeof(src.ip));
        pos += sizeof(struct hep_chunk_ip4);

        /* DST IP */
        memcpy(&dst_ip4, (void*) buffer + pos, sizeof(struct hep_chunk_ip4));
        inet_ntop(AF_INET, &dst_ip4.data, dst.ip, sizeof(src.ip));
        pos += sizeof(struct hep_chunk_ip4);
    }
#ifdef USE_IPV6
    /* IPv6 */
    else if(family == AF_INET6) {
        /* SRC IPv6 */
        memcpy(&src_ip6, (void*) buffer + pos, sizeof(struct hep_chunk_ip6));
        inet_ntop(AF_INET6, &src_ip6.data, src.ip, sizeof(src.ip));
        pos += sizeof(struct hep_chunk_ip6);

        /* DST IP */
        memcpy(&src_ip6, (void*) buffer + pos, sizeof(struct hep_chunk_ip6));
        inet_ntop(AF_INET6, &dst_ip6.data, dst.ip, sizeof(dst.ip));
        pos += sizeof(struct hep_chunk_ip6);
    }
#endif

    /* SRC PORT */
    src.port = ntohs(hg.src_port.data);
    /* DST PORT */
    dst.port = ntohs(hg.dst_port.data);
    /* TIMESTAMP*/
    header.ts.tv_sec = ntohl(hg.time_sec.data);
    header.ts.tv_usec = ntohl(hg.time_usec.data);
    /* Protocol TYPE */
    /* Capture ID */

    /* auth key */
    if (eep_cfg.capt_srv_password != NULL) {
        memcpy(&authkey_chunk, (void*) buffer + pos, sizeof(authkey_chunk));
        pos += sizeof(authkey_chunk);

        password_len = ntohs(authkey_chunk.length) - sizeof(authkey_chunk);
        memcpy(password, (void*) buffer + pos, password_len);
        pos += password_len;

        // Validate the password
        if (strncmp(password, eep_cfg.capt_srv_password, password_len) != 0)
            return NULL;
    }

    /* Payload */
    memcpy(&payload_chunk, (void*) buffer + pos, sizeof(payload_chunk));
    pos += sizeof(payload_chunk);

    // Calculate payload size
    header.caplen = header.len = ntohs(payload_chunk.length) - sizeof(payload_chunk);

    // Receive packet payload
    payload = sng_malloc(header.caplen);
    memcpy(payload, (void*) buffer + pos, header.caplen);

    // Create a new packet
    pkt = packet_create((family == AF_INET)?4:6, proto, src, dst, 0);
    packet_add_frame(pkt, &header, payload);
    packet_set_type(pkt, PACKET_SIP_UDP);
    packet_set_payload(pkt, payload, header.caplen);

    /* FREE */
    sng_free(payload);
    return pkt;
}
Exemple #7
0
packet_t *
capture_eep_receive_v2()
{
    uint8_t family, proto;
    unsigned char *payload = 0;
    uint32_t pos;
    char buffer[MAX_CAPTURE_LEN] ;
    //! Source Address
    address_t src;
    //! Destination address
    address_t dst;
    //! Packet header
    struct pcap_pkthdr header;
    //! New created packet pointer
    packet_t *pkt;
    //! EEP client data
    struct sockaddr eep_client;
    socklen_t eep_client_len;
    struct hep_hdr hdr;
    struct hep_timehdr hep_time;
    struct hep_iphdr hep_ipheader;
#ifdef USE_IPV6
    struct hep_ip6hdr hep_ip6header;
#endif

    // Initialize buffer
    memset(buffer, 0, MAX_CAPTURE_LEN);

    /* Receive EEP generic header */
    if (recvfrom(eep_cfg.server_sock, buffer, MAX_CAPTURE_LEN, 0, &eep_client, &eep_client_len) == -1)
        return NULL;

    /* Copy initial bytes to HEPv2 header */
    memcpy(&hdr, buffer, sizeof(struct hep_hdr));

    // Check HEP version
    if (hdr.hp_v != 2)
        return NULL;

    /* IP proto */
    family = hdr.hp_f;
    /* Proto ID */
    proto = hdr.hp_p;

    pos = sizeof(struct hep_hdr);

    /* IPv4 */
    if (family == AF_INET) {
        memcpy(&hep_ipheader, (void*) buffer + pos, sizeof(struct hep_iphdr));
        inet_ntop(AF_INET, &hep_ipheader.hp_src, src.ip, sizeof(src.ip));
        inet_ntop(AF_INET, &hep_ipheader.hp_dst, dst.ip, sizeof(dst.ip));
        pos += sizeof(struct hep_iphdr);
    }
#ifdef USE_IPV6
    /* IPv6 */
    else if(family == AF_INET6) {
        memcpy(&hep_ip6header, (void*) buffer + pos, sizeof(struct hep_ip6hdr));
        inet_ntop(AF_INET6, &hep_ip6header.hp6_src, src.ip, sizeof(src.ip));
        inet_ntop(AF_INET6, &hep_ip6header.hp6_dst, dst.ip, sizeof(dst.ip));
        pos += sizeof(struct hep_ip6hdr);
    }
#endif

    /* PORTS */
    src.port = ntohs(hdr.hp_sport);
    dst.port = ntohs(hdr.hp_dport);

    /* TIMESTAMP*/
    memcpy(&hep_time, (void*) buffer + pos, sizeof(struct hep_timehdr));
    pos += sizeof(struct hep_timehdr);
    header.ts.tv_sec = hep_time.tv_sec;
    header.ts.tv_usec = hep_time.tv_usec;

    /* Protocol TYPE */
    /* Capture ID */

    // Calculate payload size (Total size - headers size)
    header.caplen = header.len = ntohs(hdr.hp_l) - pos;

    // Copy packet payload
    payload = sng_malloc(header.caplen + 1);
    memcpy(payload, (void*) buffer + pos, header.caplen);

    // Create a new packet
    pkt = packet_create((family == AF_INET) ? 4 : 6, proto, src, dst, 0);
    packet_add_frame(pkt, &header, payload);
    packet_set_transport_data(pkt, src.port, dst.port);
    packet_set_type(pkt, PACKET_SIP_UDP);
    packet_set_payload(pkt, payload, header.caplen);

    /* FREE */
    sng_free(payload);
    return pkt;

}
Exemple #8
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;
}