示例#1
0
int
tls_process_segment(capture_packet_t *packet, struct tcphdr *tcp)
{
    struct SSLConnection *conn;
    const u_char *payload = capture_packet_get_payload(packet);
    uint32_t size_payload = capture_packet_get_payload_len(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->sport;
    uint16_t dport = packet->dport;

    // Convert addresses
    inet_pton(AF_INET, packet->ip_src, &ip_src);
    inet_pton(AF_INET, packet->ip_dst, &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) {
                        capture_packet_set_payload(packet, out, outl);
                        capture_packet_set_type(packet, CAPTURE_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;
}
示例#2
0
void
parse_packet(u_char *mode, const struct pcap_pkthdr *header, const u_char *packet)
{
    // IP header data
    struct ip *ip4;
#ifdef WITH_IPV6
    // IPv6 header data
    struct ip6_hdr *ip6;
#endif
    // IP version
    uint32_t ip_ver;
    // IP protocol
    uint8_t ip_proto;
    // IP header size
    uint32_t ip_hl = 0;
    // Fragment offset
    uint32_t ip_off = 0;
    // Fragmentation flag
    uint8_t ip_frag = 0;
    // Fragmentation offset
    uint16_t ip_frag_off = 0;
    //! Source Address
    char ip_src[ADDRESSLEN];
    //! Destination Address
    char ip_dst[ADDRESSLEN];
    // Source and Destination Ports
    u_short sport, dport;
    // 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 payload data
    u_char *payload = NULL;
    // Packet payload size
    uint32_t size_payload = header->caplen;
    // SIP message transport
    int transport;
    // Media structure for RTP packets
    rtp_stream_t *stream;
    // Captured packet info
    capture_packet_t *pkt;

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

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

    // Get IP header
    ip4 = (struct ip *) (packet + capinfo.link_hl);

#ifdef WITH_IPV6
    // Get IPv6 header
    ip6 = (struct ip6_hdr *) (packet + capinfo.link_hl);
#endif

    // Get IP version
    ip_ver = ip4->ip_v;

    switch (ip_ver) {
        case 4:
            ip_hl = ip4->ip_hl * 4;
            ip_proto = ip4->ip_p;
            ip_off = ntohs(ip4->ip_off);

            ip_frag = ip_off & (IP_MF | IP_OFFMASK);
            ip_frag_off = (ip_frag) ? (ip_off & IP_OFFMASK) * 8 : 0;
            // TODO Get fragment information

            inet_ntop(AF_INET, &ip4->ip_src, ip_src, sizeof(ip_src));
            inet_ntop(AF_INET, &ip4->ip_dst, ip_dst, sizeof(ip_dst));
            break;
#ifdef WITH_IPV6
        case 6:
            ip_hl = sizeof(struct ip6_hdr);
            ip_proto = ip6->ip6_nxt;

            if (ip_proto == IPPROTO_FRAGMENT) {
                struct ip6_frag *ip6f = (struct ip6_frag *) (ip6 + ip_hl);
                ip_frag_off = ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK);
                // TODO Get fragment information
            }

            inet_ntop(AF_INET6, &ip6->ip6_src, ip_src, sizeof(ip_src));
            inet_ntop(AF_INET6, &ip6->ip6_dst, ip_dst, sizeof(ip_dst));
            break;
#endif
        default:
            return;
    }

    // Only interested in UDP packets
    if (ip_proto == IPPROTO_UDP) {
        // Get UDP header
        udp = (struct udphdr *)((u_char *)(ip4) + ip_hl);
        udp_off = (ip_frag_off) ? 0 : sizeof(struct udphdr);

        // Set packet ports
        sport = htons(udp->uh_sport);
        dport = htons(udp->uh_dport);

        // Get actual payload size
        size_payload -= capinfo.link_hl + ip_hl + udp_off;

#ifdef WITH_IPV6
        if (ip_ver == 6)
            size_payload -= ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
#endif
        // Get payload start
        payload = (u_char *) (udp) + udp_off;

        // Set transport UDP
        transport = CAPTURE_PACKET_SIP_UDP;

    } else if (ip_proto == IPPROTO_TCP) {
        // Get TCP header
        tcp = (struct tcphdr *)((u_char *)(ip4 )+ ip_hl);
        tcp_off = (ip_frag_off) ? 0 : (tcp->th_off * 4);

        // Set packet ports
        sport = htons(tcp->th_sport);
        dport = htons(tcp->th_dport);

        // Get actual payload size
        size_payload -= capinfo.link_hl + ip_hl + tcp_off;

#ifdef WITH_IPV6
        if (ip_ver == 6)
            size_payload -= ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
#endif
        // Get payload start
        payload = (u_char *)(tcp) + tcp_off;

        // Set transport TCP
        transport = CAPTURE_PACKET_SIP_TCP;
    } else {
        // Not handled protocol
        return;
    }

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

    // Create a structure for this captured packet
    pkt = capture_packet_create(header, packet, header->caplen);
    capture_packet_set_type(pkt, transport);
    // For TCP and UDP, use payload directly from the packet
    capture_packet_set_payload(pkt, NULL, size_payload);

#ifdef WITH_OPENSSL
    // Check if packet is TLS
    if (capinfo.keyfile && transport == CAPTURE_PACKET_SIP_TCP)
        tls_process_segment(ip4, pkt);
#endif

    // Check if packet is WS or WSS
    if (transport == CAPTURE_PACKET_SIP_TCP)
        capture_ws_check_packet(pkt);

    // We're only interested in packets with payload
    if (capture_packet_get_payload_len(pkt)) {
        // Parse this header and payload
        if (sip_load_message(pkt, ip_src, sport, ip_dst, dport)) {
            // Store this packets in output file
            dump_packet(capinfo.pd, header, packet);
            return;
        }

        // Check if this packet belongs to a RTP stream
        // TODO Store this packet in the stream
        if ((stream = rtp_check_stream(pkt, ip_src, sport, ip_dst, dport))) {
            // We have an RTP packet!
            capture_packet_set_type(pkt, CAPTURE_PACKET_RTP);
            // Store this pacekt if capture rtp is enabled
            if (capinfo.rtp_capture) {
                call_add_rtp_packet(stream_get_call(stream), pkt);
            } else {
                capture_packet_destroy(pkt);
            }
            // Store this packets in output file
            dump_packet(capinfo.pd, header, packet);
            return;
        }
    }

    // Not an interesting packet ...
    capture_packet_destroy(pkt);
}
示例#3
0
int
capture_ws_check_packet(capture_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 = capture_packet_get_payload_len(packet);
    payload = capture_packet_get_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
    capture_packet_set_payload(packet, newpayload, size_payload);

    if (packet->type == CAPTURE_PACKET_SIP_TLS) {
        capture_packet_set_type(packet, CAPTURE_PACKET_SIP_WSS);
    } else {
        capture_packet_set_type(packet, CAPTURE_PACKET_SIP_WS);
    }
    return 1;
}