Exemplo n.º 1
0
/**
 *  \brief Recalculate the csum for a modified packet
 *
 *  \param p packet to inspect
 */
void StreamTcpInlineRecalcCsum(Packet *p) {
    if (!(p->flags & PKT_STREAM_MODIFIED)) {
        SCReturn;
    }

    if (!(PKT_IS_TCP(p))) {
        SCReturn;
    }

    if (PKT_IS_IPV4(p)) {
        /* TCP */
        p->tcph->th_sum = 0;
        p->tcph->th_sum = TCPCalculateChecksum((uint16_t *)&(p->ip4h->ip_src),
                (uint16_t *)p->tcph, (p->payload_len + p->tcpvars.hlen));
        /* IPV4 */
        p->ip4h->ip_csum = 0;
        p->ip4h->ip_csum = IPV4CalculateChecksum((uint16_t *)p->ip4h,
                IPV4_GET_RAW_HLEN(p->ip4h));
    } else if (PKT_IS_IPV6(p)) {
        /* just TCP for IPV6 */
        p->tcph->th_sum = 0;
        p->tcph->th_sum = TCPV6CalculateChecksum((uint16_t *)&(p->ip6h->ip6_src),
                (uint16_t *)p->tcph, (p->payload_len + p->tcpvars.hlen));
    }

    SCReturn;
}
Exemplo n.º 2
0
static int TCPCalculateInvalidChecksumtest02(void)
{
    uint16_t csum = 0;

    uint8_t raw_ipshdr[] = {
        0x40, 0x8e, 0x7e, 0xb2, 0xc0, 0xa8, 0x01, 0x03};

    uint8_t raw_tcp[] = {
        0x00, 0x50, 0x8e, 0x16, 0x0d, 0x59, 0xcd, 0x3c,
        0xcf, 0x0d, 0x21, 0x80, 0xa0, 0x12, 0x16, 0xa0,
        0xfa, 0x03, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4,
        0x04, 0x02, 0x08, 0x0a, 0x6e, 0x18, 0x78, 0x73,
        0x01, 0x71, 0x74, 0xde, 0x01, 0x03, 0x03, 03};

    csum = *( ((uint16_t *)raw_tcp) + 8);

    return (csum != TCPCalculateChecksum((uint16_t *) raw_ipshdr,
                                         (uint16_t *)raw_tcp, sizeof(raw_tcp)));
}
Exemplo n.º 3
0
/**
 * \brief Write a faked Packet in unified2 file for each stream segment.
 */
static int Unified2PrintStreamSegmentCallback(Packet *p, void *data, uint8_t *buf, uint32_t buflen)
{
    int ret = 1;
    Unified2AlertThread *aun = (Unified2AlertThread *)data;
    Unified2AlertFileHeader *hdr = (Unified2AlertFileHeader*)(aun->data);
    Unified2Packet *phdr = (Unified2Packet *)(hdr + 1);
    int ethh_offset = 0;
    EthernetHdr ethhdr = { {0,0,0,0,0,0}, {0,0,0,0,0,0}, htons(ETHERNET_TYPE_IPV6) };
    uint32_t hdr_length = 0;
    int datalink = p->datalink;

    memset(hdr, 0, sizeof(Unified2AlertFileHeader));
    memset(phdr, 0, sizeof(Unified2Packet));

    hdr->type = htonl(UNIFIED2_PACKET_TYPE);
    aun->hdr = hdr;

    phdr->sensor_id = htonl(sensor_id);
    phdr->linktype = htonl(datalink);
    phdr->event_id = aun->event_id;
    phdr->event_second = phdr->packet_second = htonl(p->ts.tv_sec);
    phdr->packet_microsecond = htonl(p->ts.tv_usec);
    aun->phdr = phdr;

    if (p->datalink != DLT_EN10MB) {
        /* We have raw data here */
        phdr->linktype = htonl(DLT_RAW);
        datalink = DLT_RAW;
    }

    aun->length = sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE;
    aun->offset = sizeof(Unified2AlertFileHeader) + UNIFIED2_PACKET_SIZE;

    /* Include Packet header */
    if (PKT_IS_IPV4(p)) {
        FakeIPv4Hdr fakehdr;
        hdr_length = sizeof(FakeIPv4Hdr);

        if (p->datalink == DLT_EN10MB) {
            /* Fake this */
            ethh_offset = 14;
            datalink = DLT_EN10MB;
            phdr->linktype = htonl(datalink);
            aun->length += ethh_offset;

            if (aun->length > aun->datalen) {
                SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
                goto error;
            }
            ethhdr.eth_type = htons(ETHERNET_TYPE_IP);

            memcpy(aun->data + aun->offset, &ethhdr, 14);
            aun->offset += ethh_offset;
        }

        memset(&fakehdr, 0, hdr_length);
        aun->length += hdr_length;
        Unified2ForgeFakeIPv4Header(&fakehdr, p, hdr_length + buflen, 0);
        if (aun->length > aun->datalen) {
            SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
            goto error;
        }
        memcpy(aun->data + aun->offset, &fakehdr, hdr_length);
        aun->iphdr = (void *)(aun->data + aun->offset);
        aun->offset += hdr_length;

    } else if (PKT_IS_IPV6(p)) {
        FakeIPv6Hdr fakehdr;
        hdr_length = sizeof(FakeIPv6Hdr);

        if (p->datalink == DLT_EN10MB) {
            /* Fake this */
            ethh_offset = 14;
            datalink = DLT_EN10MB;
            phdr->linktype = htonl(datalink);
            aun->length += ethh_offset;
            if (aun->length > aun->datalen) {
                SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
                goto error;
            }
            ethhdr.eth_type = htons(ETHERNET_TYPE_IPV6);

            memcpy(aun->data + aun->offset, &ethhdr, 14);
            aun->offset += ethh_offset;
        }

        memset(&fakehdr, 0, hdr_length);
        Unified2ForgeFakeIPv6Header(&fakehdr, p, buflen, 1);

        aun->length += hdr_length;
        if (aun->length > aun->datalen) {
            SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
            goto error;
        }
        memcpy(aun->data + aun->offset, &fakehdr, hdr_length);
        aun->iphdr = (void *)(aun->data + aun->offset);
        aun->offset += hdr_length;
    } else {
        goto error;
    }

    /* update unified2 headers for length */
    aun->hdr->length = htonl(UNIFIED2_PACKET_SIZE + ethh_offset +
            hdr_length + buflen);
    aun->phdr->packet_length = htonl(ethh_offset + hdr_length + buflen);

    /* copy stream segment payload in */
    aun->length += buflen;

    if (aun->length > aun->datalen) {
        SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread"
                   " data: %d vs %d", aun->length, aun->datalen);
        goto error;
    }

    memcpy(aun->data + aun->offset, buf, buflen);
    aun->offset += buflen;

    /* rebuild checksum */
    if (PKT_IS_IPV6(p)) {
        FakeIPv6Hdr *fakehdr = (FakeIPv6Hdr *)aun->iphdr;

        fakehdr->tcph.th_sum = TCPV6CalculateChecksum(fakehdr->ip6h.s_ip6_addrs,
                (uint16_t *)&fakehdr->tcph, buflen + sizeof(TCPHdr));
    } else {
        FakeIPv4Hdr *fakehdr = (FakeIPv4Hdr *)aun->iphdr;

        fakehdr->tcph.th_sum = TCPCalculateChecksum(fakehdr->ip4h.s_ip_addrs,
                (uint16_t *)&fakehdr->tcph, buflen + sizeof(TCPHdr));
        fakehdr->ip4h.ip_csum = IPV4CalculateChecksum((uint16_t *)&fakehdr->ip4h,
                IPV4_GET_RAW_HLEN(&fakehdr->ip4h));
    }

    /* write out */
    ret = Unified2Write(aun);
    if (ret != 1) {
        goto error;
    }
    return 1;

error:
    aun->length = 0;
    aun->offset = 0;
    return -1;
}
Exemplo n.º 4
0
/**
 * \internal
 * \brief Pseudo packet setup for flow forced reassembly.
 *
 * \param direction Direction of the packet.  0 indicates toserver and 1
 *                  indicates toclient.
 * \param f         Pointer to the flow.
 * \param ssn       Pointer to the tcp session.
 * \param dummy     Indicates to create a dummy pseudo packet.  Not all pseudo
 *                  packets need to force reassembly, in which case we just
 *                  set dummy ack/seq values.
 */
static inline Packet *FlowForceReassemblyPseudoPacketSetup(Packet *p,
                                                           int direction,
                                                           Flow *f,
                                                           TcpSession *ssn,
                                                           int dummy)
{
    p->datalink = DLT_RAW;
    p->proto = IPPROTO_TCP;
    FlowReference(&p->flow, f);
    p->flags |= PKT_STREAM_EST;
    p->flags |= PKT_STREAM_EOF;
    p->flags |= PKT_HAS_FLOW;
    p->flags |= PKT_PSEUDO_STREAM_END;
    if (direction == 0)
        p->flowflags |= FLOW_PKT_TOSERVER;
    else
        p->flowflags |= FLOW_PKT_TOCLIENT;
    p->flowflags |= FLOW_PKT_ESTABLISHED;
    p->payload = NULL;
    p->payload_len = 0;

    if (FLOW_IS_IPV4(f)) {
        if (direction == 0) {
            FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->src, &p->src);
            FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->dst, &p->dst);
            p->sp = f->sp;
            p->dp = f->dp;
        } else {
            FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->src, &p->dst);
            FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->dst, &p->src);
            p->sp = f->dp;
            p->dp = f->sp;
        }

        /* set the ip header */
        p->ip4h = (IPV4Hdr *)GET_PKT_DATA(p);
        /* version 4 and length 20 bytes for the tcp header */
        p->ip4h->ip_verhl = 0x45;
        p->ip4h->ip_tos = 0;
        p->ip4h->ip_len = htons(40);
        p->ip4h->ip_id = 0;
        p->ip4h->ip_off = 0;
        p->ip4h->ip_ttl = 64;
        p->ip4h->ip_proto = IPPROTO_TCP;
        //p->ip4h->ip_csum =
        if (direction == 0) {
            p->ip4h->s_ip_src.s_addr = f->src.addr_data32[0];
            p->ip4h->s_ip_dst.s_addr = f->dst.addr_data32[0];
        } else {
            p->ip4h->s_ip_src.s_addr = f->dst.addr_data32[0];
            p->ip4h->s_ip_dst.s_addr = f->src.addr_data32[0];
        }

        /* set the tcp header */
        p->tcph = (TCPHdr *)((uint8_t *)GET_PKT_DATA(p) + 20);

        SET_PKT_LEN(p, 40); /* ipv4 hdr + tcp hdr */

    } else if (FLOW_IS_IPV6(f)) {
        if (direction == 0) {
            FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->src, &p->src);
            FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->dst, &p->dst);
            p->sp = f->sp;
            p->dp = f->dp;
        } else {
            FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->src, &p->dst);
            FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->dst, &p->src);
            p->sp = f->dp;
            p->dp = f->sp;
        }

        /* set the ip header */
        p->ip6h = (IPV6Hdr *)GET_PKT_DATA(p);
        /* version 6 */
        p->ip6h->s_ip6_vfc = 0x60;
        p->ip6h->s_ip6_flow = 0;
        p->ip6h->s_ip6_nxt = IPPROTO_TCP;
        p->ip6h->s_ip6_plen = htons(20);
        p->ip6h->s_ip6_hlim = 64;
        if (direction == 0) {
            p->ip6h->s_ip6_src[0] = f->src.addr_data32[0];
            p->ip6h->s_ip6_src[1] = f->src.addr_data32[1];
            p->ip6h->s_ip6_src[2] = f->src.addr_data32[2];
            p->ip6h->s_ip6_src[3] = f->src.addr_data32[3];
            p->ip6h->s_ip6_dst[0] = f->dst.addr_data32[0];
            p->ip6h->s_ip6_dst[1] = f->dst.addr_data32[1];
            p->ip6h->s_ip6_dst[2] = f->dst.addr_data32[2];
            p->ip6h->s_ip6_dst[3] = f->dst.addr_data32[3];
        } else {
            p->ip6h->s_ip6_src[0] = f->dst.addr_data32[0];
            p->ip6h->s_ip6_src[1] = f->dst.addr_data32[1];
            p->ip6h->s_ip6_src[2] = f->dst.addr_data32[2];
            p->ip6h->s_ip6_src[3] = f->dst.addr_data32[3];
            p->ip6h->s_ip6_dst[0] = f->src.addr_data32[0];
            p->ip6h->s_ip6_dst[1] = f->src.addr_data32[1];
            p->ip6h->s_ip6_dst[2] = f->src.addr_data32[2];
            p->ip6h->s_ip6_dst[3] = f->src.addr_data32[3];
        }

        /* set the tcp header */
        p->tcph = (TCPHdr *)((uint8_t *)GET_PKT_DATA(p) + 40);

        SET_PKT_LEN(p, 60); /* ipv6 hdr + tcp hdr */
    }

    p->tcph->th_offx2 = 0x50;
    p->tcph->th_flags |= TH_ACK;
    p->tcph->th_win = 10;
    p->tcph->th_urp = 0;

    /* to server */
    if (direction == 0) {
        p->tcph->th_sport = htons(f->sp);
        p->tcph->th_dport = htons(f->dp);

        if (dummy) {
            p->tcph->th_seq = htonl(ssn->client.next_seq);
            p->tcph->th_ack = htonl(ssn->server.last_ack);
        } else {
            p->tcph->th_seq = htonl(ssn->client.next_seq);
            p->tcph->th_ack = htonl(ssn->server.seg_list_tail->seq +
                                    ssn->server.seg_list_tail->payload_len);
        }

        /* to client */
    } else {
        p->tcph->th_sport = htons(f->dp);
        p->tcph->th_dport = htons(f->sp);

        if (dummy) {
            p->tcph->th_seq = htonl(ssn->server.next_seq);
            p->tcph->th_ack = htonl(ssn->client.last_ack);
        } else {
            p->tcph->th_seq = htonl(ssn->server.next_seq);
            p->tcph->th_ack = htonl(ssn->client.seg_list_tail->seq +
                                    ssn->client.seg_list_tail->payload_len);
        }
    }

    if (FLOW_IS_IPV4(f)) {
        p->tcph->th_sum = TCPCalculateChecksum(p->ip4h->s_ip_addrs,
                                               (uint16_t *)p->tcph, 20);
        /* calc ipv4 csum as we may log it and barnyard might reject
         * a wrong checksum */
        p->ip4h->ip_csum = IPV4CalculateChecksum((uint16_t *)p->ip4h,
                IPV4_GET_RAW_HLEN(p->ip4h));
    } else if (FLOW_IS_IPV6(f)) {
        p->tcph->th_sum = TCPCalculateChecksum(p->ip6h->s_ip6_addrs,
                                               (uint16_t *)p->tcph, 20);
    }

    memset(&p->ts, 0, sizeof(struct timeval));
    TimeGet(&p->ts);

    AppLayerSetEOF(f);

    return p;
}