You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/src/app-layer-htp-body.c

242 lines
5.9 KiB
C

/* Copyright (C) 2007-2011 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file
*
* \author Victor Julien <victor@inliniac.net>
* \author Gurvinder Singh <gurvindersinghdahiya@gmail.com>
* \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
* \author Brian Rectanus <brectanu@gmail.com>
*
* This file provides a HTTP protocol support for the engine using HTP library.
*/
#include "suricata.h"
#include "suricata-common.h"
#include "debug.h"
#include "decode.h"
#include "threads.h"
#include "util-print.h"
#include "util-pool.h"
#include "util-radix-tree.h"
#include "stream-tcp-private.h"
#include "stream-tcp-reassemble.h"
#include "stream-tcp.h"
#include "stream.h"
#include "app-layer-protos.h"
#include "app-layer-parser.h"
#include "app-layer-htp.h"
#include "util-spm.h"
#include "util-debug.h"
#include "app-layer-htp.h"
#include "app-layer-htp-file.h"
#include "util-time.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
#include "flow-util.h"
#include "detect-engine.h"
#include "detect-engine-state.h"
#include "detect-parse.h"
#include "conf.h"
#include "util-memcmp.h"
/**
* \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 *)SCMalloc(sizeof(HtpBodyChunk));
if (bd == NULL)
goto error;
bd->len = len;
bd->stream_offset = 0;
bd->next = NULL;
bd->data = SCMalloc(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 *)SCMalloc(sizeof(HtpBodyChunk));
if (bd == NULL)
goto error;
bd->len = len;
bd->stream_offset = body->content_len_so_far;
bd->next = NULL;
bd->data = SCMalloc(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) {
SCFree(bd->data);
}
SCFree(bd);
}
SCReturnInt(-1);
}
/**
* \brief Print the information and chunks of a Body
* \param body pointer to the HtpBody holding the list
* \retval none
*/
void HtpBodyPrint(HtpBody *body)
{
if (SCLogDebugEnabled()||1) {
SCEnter();
if (body->first == NULL)
return;
HtpBodyChunk *cur = NULL;
SCLogDebug("--- Start body chunks at %p ---", body);
printf("--- Start body chunks at %p ---\n", body);
for (cur = body->first; cur != NULL; cur = cur->next) {
SCLogDebug("Body %p; data %p, len %"PRIu32, body, cur->data, (uint32_t)cur->len);
printf("Body %p; data %p, len %"PRIu32"\n", body, cur->data, (uint32_t)cur->len);
PrintRawDataFp(stdout, (uint8_t*)cur->data, cur->len);
}
SCLogDebug("--- End body chunks at %p ---", body);
}
}
/**
* \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)
SCFree(prev->data);
SCFree(prev);
prev = cur;
}
body->first = body->last = NULL;
}
/**
* \brief Free request body chunks that are already fully parsed.
*
* \param htud pointer to the HtpTxUserData holding the body
*
* \retval none
*/
void HtpBodyPrune(HtpBody *body)
{
SCEnter();
if (body == NULL || body->first == NULL) {
SCReturn;
}
if (body->body_parsed == 0) {
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);
if (cur->stream_offset >= body->body_inspected) {
break;
}
body->first = next;
if (body->last == cur) {
body->last = next;
}
if (cur->data != NULL) {
SCFree(cur->data);
}
SCFree(cur);
cur = next;
}
SCReturn;
}