Ejemplo n.º 1
0
/**
 * \brief Append a chunk of body to the HtpBody struct
 *
 * \param body pointer to the HtpBody holding the list
 * \param data pointer to the data of the chunk
 * \param len length of the chunk pointed by data
 *
 * \retval 0 ok
 * \retval -1 error
 */
int HtpBodyAppendChunk(const HTPCfgDir *hcfg, HtpBody *body,
                       const uint8_t *data, uint32_t len)
{
    SCEnter();

    HtpBodyChunk *bd = NULL;

    if (len == 0 || data == NULL) {
        SCReturnInt(0);
    }

    if (body->sb == NULL) {
        const StreamingBufferConfig *cfg = hcfg ? &hcfg->sbcfg : &default_cfg;
        body->sb = StreamingBufferInit(cfg);
        if (body->sb == NULL)
            SCReturnInt(-1);
    }

    if (body->first == NULL) {
        /* New chunk */
        bd = (HtpBodyChunk *)HTPCalloc(1, sizeof(HtpBodyChunk));
        if (bd == NULL) {
            SCReturnInt(-1);
        }

        if (StreamingBufferAppend(body->sb, &bd->sbseg, data, len) != 0) {
            HTPFree(bd, sizeof(HtpBodyChunk));
            SCReturnInt(-1);
        }

        body->first = body->last = bd;

        body->content_len_so_far = len;
    } else {
        bd = (HtpBodyChunk *)HTPCalloc(1, sizeof(HtpBodyChunk));
        if (bd == NULL) {
            SCReturnInt(-1);
        }

        if (StreamingBufferAppend(body->sb, &bd->sbseg, data, len) != 0) {
            HTPFree(bd, sizeof(HtpBodyChunk));
            SCReturnInt(-1);
        }

        body->last->next = bd;
        body->last = bd;

        body->content_len_so_far += len;
    }
    SCLogDebug("body %p", body);

    SCReturnInt(0);
}
Ejemplo n.º 2
0
/**
 * \brief Free the information held in the request body
 * \param body pointer to the HtpBody holding the list
 * \retval none
 */
void HtpBodyFree(HtpBody *body)
{
    SCEnter();

    if (body->first == NULL)
        return;

    SCLogDebug("Removing chunks of Body %p; data %p, len %"PRIu32, body,
            body->last->data, (uint32_t)body->last->len);

    HtpBodyChunk *cur = NULL;
    HtpBodyChunk *prev = NULL;

    prev = body->first;
    while (prev != NULL) {
        cur = prev->next;
        if (prev->data != NULL)
            HTPFree(prev->data, prev->len);
        HTPFree(prev, sizeof(HtpBodyChunk));
        prev = cur;
    }
    body->first = body->last = NULL;
}
Ejemplo n.º 3
0
/**
 * \brief Free the information held in the request body
 * \param body pointer to the HtpBody holding the list
 * \retval none
 */
void HtpBodyFree(HtpBody *body)
{
    SCEnter();

    SCLogDebug("removing chunks of body %p", body);

    HtpBodyChunk *cur = NULL;
    HtpBodyChunk *prev = NULL;

    prev = body->first;
    while (prev != NULL) {
        cur = prev->next;
        HTPFree(prev, sizeof(HtpBodyChunk));
        prev = cur;
    }
    body->first = body->last = NULL;

    StreamingBufferFree(body->sb);
}
Ejemplo n.º 4
0
/**
 * \brief Free request body chunks that are already fully parsed.
 *
 * \param state htp_state, with reference to our config
 * \param body the body to prune
 * \param direction STREAM_TOSERVER (request), STREAM_TOCLIENT (response)
 *
 * \retval none
 */
void HtpBodyPrune(HtpState *state, HtpBody *body, int direction)
{
    SCEnter();

    if (body == NULL || body->first == NULL) {
        SCReturn;
    }

    if (body->body_parsed == 0) {
        SCReturn;
    }

    /* get the configured inspect sizes. Default to response values */
    uint32_t min_size = state->cfg->response.inspect_min_size;
    uint32_t window = state->cfg->response.inspect_window;

    if (direction == STREAM_TOSERVER) {
        min_size = state->cfg->request.inspect_min_size;
        window = state->cfg->request.inspect_window;
    }

    uint64_t max_window = ((min_size > window) ? min_size : window);
    uint64_t in_flight = body->content_len_so_far - body->body_inspected;

    /* Special case. If body_inspected is not being updated, we make sure that
     * we prune the body. We allow for some extra size/room as we may be called
     * multiple times on uninspected body chunk additions if a large block of
     * data was ack'd at once. Want to avoid pruning before inspection. */
    if (in_flight > (max_window * 3)) {
        body->body_inspected = body->content_len_so_far - max_window;
    } else if (body->body_inspected < max_window) {
        SCReturn;
    }

    uint64_t left_edge = body->body_inspected;
    if (left_edge <= min_size || left_edge <= window)
        left_edge = 0;
    if (left_edge)
        left_edge -= window;

    if (left_edge) {
        SCLogDebug("sliding body to offset %"PRIu64, left_edge);
        StreamingBufferSlideToOffset(body->sb, left_edge);
    }

    SCLogDebug("pruning chunks of body %p", body);

    HtpBodyChunk *cur = body->first;
    while (cur != NULL) {
        HtpBodyChunk *next = cur->next;
        SCLogDebug("cur %p", cur);

        if (!StreamingBufferSegmentIsBeforeWindow(body->sb, &cur->sbseg)) {
            SCLogDebug("not removed");
            break;
        }

        body->first = next;
        if (body->last == cur) {
            body->last = next;
        }

        HTPFree(cur, sizeof(HtpBodyChunk));

        cur = next;
        SCLogDebug("removed");
    }

    SCReturn;
}
Ejemplo n.º 5
0
/**
 * \brief Append a chunk of body to the HtpBody struct
 *
 * \param body pointer to the HtpBody holding the list
 * \param data pointer to the data of the chunk
 * \param len length of the chunk pointed by data
 *
 * \retval 0 ok
 * \retval -1 error
 */
int HtpBodyAppendChunk(HtpTxUserData *htud, HtpBody *body, uint8_t *data, uint32_t len)
{
    SCEnter();

    HtpBodyChunk *bd = NULL;

    if (len == 0 || data == NULL) {
        SCReturnInt(0);
    }

    if (body->first == NULL) {
        /* New chunk */
        bd = (HtpBodyChunk *)HTPMalloc(sizeof(HtpBodyChunk));
        if (bd == NULL)
            goto error;

        bd->len = len;
        bd->stream_offset = 0;
        bd->next = NULL;
        bd->logged = 0;

        bd->data = HTPMalloc(len);
        if (bd->data == NULL) {
            goto error;
        }
        memcpy(bd->data, data, len);

        body->first = body->last = bd;

        body->content_len_so_far = len;
    } else {
        bd = (HtpBodyChunk *)HTPMalloc(sizeof(HtpBodyChunk));
        if (bd == NULL)
            goto error;

        bd->len = len;
        bd->stream_offset = body->content_len_so_far;
        bd->next = NULL;
        bd->logged = 0;

        bd->data = HTPMalloc(len);
        if (bd->data == NULL) {
            goto error;
        }
        memcpy(bd->data, data, len);

        body->last->next = bd;
        body->last = bd;

        body->content_len_so_far += len;
    }
    SCLogDebug("Body %p; data %p, len %"PRIu32, body, bd->data, (uint32_t)bd->len);

    SCReturnInt(0);

error:
    if (bd != NULL) {
        if (bd->data != NULL) {
            HTPFree(bd->data, bd->len);
        }
        HTPFree(bd, sizeof(HtpBodyChunk));
    }
    SCReturnInt(-1);
}
Ejemplo n.º 6
0
/**
 * \brief Free request body chunks that are already fully parsed.
 *
 * \param state htp_state, with reference to our config
 * \param body the body to prune
 * \param direction STREAM_TOSERVER (request), STREAM_TOCLIENT (response)
 *
 * \retval none
 */
void HtpBodyPrune(HtpState *state, HtpBody *body, int direction)
{
    SCEnter();

    if (body == NULL || body->first == NULL) {
        SCReturn;
    }

    if (body->body_parsed == 0) {
        SCReturn;
    }

    /* get the configured inspect sizes. Default to response values */
    uint32_t min_size = state->cfg->response_inspect_min_size;
    uint32_t window = state->cfg->response_inspect_window;

    if (direction == STREAM_TOSERVER) {
        min_size = state->cfg->request_inspect_min_size;
        window = state->cfg->request_inspect_window;
    }

    if (body->body_inspected < (min_size > window) ? min_size : window) {
        SCReturn;
    }

    SCLogDebug("Pruning chunks of Body %p; data %p, len %"PRIu32, body,
            body->last->data, (uint32_t)body->last->len);

    HtpBodyChunk *cur = body->first;
    while (cur != NULL) {
        HtpBodyChunk *next = cur->next;

        SCLogDebug("cur->stream_offset %"PRIu64" + cur->len %u = %"PRIu64", "
                "body->body_parsed %"PRIu64, cur->stream_offset, cur->len,
                cur->stream_offset + cur->len, body->body_parsed);

        uint64_t left_edge = body->body_inspected;
        if (left_edge <= min_size || left_edge <= window)
            left_edge = 0;
        if (left_edge)
            left_edge -= window;

        if (cur->stream_offset + cur->len > left_edge) {
            break;
        }

        body->first = next;
        if (body->last == cur) {
            body->last = next;
        }

        if (cur->data != NULL) {
            HTPFree(cur->data, cur->len);
        }
        HTPFree(cur, sizeof(HtpBodyChunk));

        cur = next;
    }

    SCReturn;
}