|
|
|
/* Copyright (C) 2007-2010 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 Anoop Saldanha <poonaatsoc@gmail.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "suricata-common.h"
|
|
|
|
#include "suricata.h"
|
|
|
|
#include "decode.h"
|
|
|
|
|
|
|
|
#include "detect.h"
|
|
|
|
#include "detect-engine.h"
|
|
|
|
#include "detect-engine-mpm.h"
|
|
|
|
#include "detect-parse.h"
|
|
|
|
#include "detect-engine-state.h"
|
|
|
|
#include "detect-pcre.h"
|
|
|
|
#include "detect-isdataat.h"
|
|
|
|
#include "detect-bytetest.h"
|
|
|
|
#include "detect-bytejump.h"
|
|
|
|
|
|
|
|
#include "flow-util.h"
|
|
|
|
#include "util-spm.h"
|
|
|
|
#include "util-debug.h"
|
|
|
|
#include "util-print.h"
|
|
|
|
#include "flow.h"
|
|
|
|
#include "detect-flow.h"
|
|
|
|
#include "flow-var.h"
|
|
|
|
#include "threads.h"
|
|
|
|
#include "flow-alert-sid.h"
|
|
|
|
|
|
|
|
#include "stream-tcp.h"
|
|
|
|
#include "stream.h"
|
|
|
|
#include "app-layer-parser.h"
|
|
|
|
|
|
|
|
#include "util-unittest.h"
|
|
|
|
#include "util-unittest-helper.h"
|
|
|
|
#include "app-layer.h"
|
|
|
|
#include "app-layer-htp.h"
|
|
|
|
#include "app-layer-protos.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Run the actual payload match function for http request body.
|
|
|
|
*
|
|
|
|
* For accounting the last match in relative matching the
|
|
|
|
* det_ctx->payload_offset int is used.
|
|
|
|
*
|
|
|
|
* \param de_ctx Detection engine context.
|
|
|
|
* \param det_ctx Detection engine thread context.
|
|
|
|
* \param s Signature to inspect.
|
|
|
|
* \param sm SigMatch to inspect.
|
|
|
|
* \param payload Ptr to the request body to inspect.
|
|
|
|
* \param payload_len Length of the request body.
|
|
|
|
*
|
|
|
|
* \retval 0 no match.
|
|
|
|
* \retval 1 match.
|
|
|
|
*/
|
|
|
|
static int DoInspectHttpClientBody(DetectEngineCtx *de_ctx,
|
|
|
|
DetectEngineThreadCtx *det_ctx,
|
|
|
|
Signature *s, SigMatch *sm,
|
|
|
|
uint8_t *payload, uint32_t payload_len)
|
|
|
|
{
|
|
|
|
SCEnter();
|
|
|
|
|
|
|
|
det_ctx->inspection_recursion_counter++;
|
|
|
|
|
|
|
|
if (det_ctx->inspection_recursion_counter == de_ctx->inspection_recursion_limit) {
|
|
|
|
det_ctx->discontinue_matching = 1;
|
|
|
|
SCReturnInt(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sm == NULL) {
|
|
|
|
SCReturnInt(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sm->type == DETECT_AL_HTTP_CLIENT_BODY) {
|
|
|
|
if (payload_len == 0) {
|
|
|
|
SCReturnInt(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
DetectContentData *cd = (DetectContentData *)sm->ctx;
|
|
|
|
SCLogDebug("inspecting content %"PRIu32" payload_len %"PRIu32, cd->id, payload_len);
|
|
|
|
|
|
|
|
if (cd->flags & DETECT_CONTENT_HCBD_MPM && !(cd->flags & DETECT_CONTENT_NEGATED))
|
|
|
|
goto match;
|
|
|
|
|
|
|
|
/* rule parsers should take care of this */
|
|
|
|
BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
|
|
|
|
|
|
|
|
/* search for our pattern, checking the matches recursively.
|
|
|
|
* if we match we look for the next SigMatch as well */
|
|
|
|
uint8_t *found = NULL;
|
|
|
|
uint32_t offset = 0;
|
|
|
|
uint32_t depth = payload_len;
|
|
|
|
uint32_t prev_offset = 0; /**< used in recursive searching */
|
|
|
|
uint32_t prev_payload_offset = det_ctx->payload_offset;
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (cd->flags & DETECT_CONTENT_DISTANCE ||
|
|
|
|
cd->flags & DETECT_CONTENT_WITHIN) {
|
|
|
|
SCLogDebug("prev_payload_offset %"PRIu32, prev_payload_offset);
|
|
|
|
|
|
|
|
offset = prev_payload_offset;
|
|
|
|
depth = payload_len;
|
|
|
|
|
|
|
|
if (cd->flags & DETECT_CONTENT_DISTANCE) {
|
|
|
|
if (cd->distance < 0 && (uint32_t)(abs(cd->distance)) > offset)
|
|
|
|
offset = 0;
|
|
|
|
else
|
|
|
|
offset += cd->distance;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cd->flags & DETECT_CONTENT_WITHIN) {
|
|
|
|
if ((int32_t)depth > (int32_t)(prev_payload_offset + cd->within)) {
|
|
|
|
depth = prev_payload_offset + cd->within;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cd->depth != 0) {
|
|
|
|
if ((cd->depth + prev_payload_offset) < depth) {
|
|
|
|
depth = prev_payload_offset + cd->depth;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cd->offset > offset) {
|
|
|
|
offset = cd->offset;
|
|
|
|
}
|
|
|
|
} else { /* implied no relative matches */
|
|
|
|
/* set depth */
|
|
|
|
if (cd->depth != 0) {
|
|
|
|
depth = cd->depth;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set offset */
|
|
|
|
offset = cd->offset;
|
|
|
|
prev_payload_offset = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* update offset with prev_offset if we're searching for
|
|
|
|
* matches after the first occurence. */
|
|
|
|
if (prev_offset != 0)
|
|
|
|
offset = prev_offset;
|
|
|
|
|
|
|
|
if (depth > payload_len)
|
|
|
|
depth = payload_len;
|
|
|
|
|
|
|
|
/* if offset is bigger than depth we can never match on a pattern.
|
|
|
|
* We can however, "match" on a negated pattern. */
|
|
|
|
if (offset > depth || depth == 0) {
|
|
|
|
if (cd->flags & DETECT_CONTENT_NEGATED) {
|
|
|
|
goto match;
|
|
|
|
} else {
|
|
|
|
SCReturnInt(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t *spayload = payload + offset;
|
|
|
|
uint32_t spayload_len = depth - offset;
|
|
|
|
uint32_t match_offset = 0;
|
|
|
|
BUG_ON(spayload_len > payload_len);
|
|
|
|
|
|
|
|
/* do the actual search with boyer moore precooked ctx */
|
|
|
|
if (cd->flags & DETECT_CONTENT_NOCASE) {
|
|
|
|
found = BoyerMooreNocase(cd->content, cd->content_len,
|
|
|
|
spayload, spayload_len,
|
|
|
|
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
|
|
|
|
} else {
|
|
|
|
found = BoyerMoore(cd->content, cd->content_len,
|
|
|
|
spayload, spayload_len,
|
|
|
|
cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* next we evaluate the result in combination with the
|
|
|
|
* negation flag. */
|
|
|
|
if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) {
|
|
|
|
SCReturnInt(0);
|
|
|
|
} else if (found == NULL && cd->flags & DETECT_CONTENT_NEGATED) {
|
|
|
|
goto match;
|
|
|
|
} else if (found != NULL && cd->flags & DETECT_CONTENT_NEGATED) {
|
|
|
|
det_ctx->discontinue_matching = 1;
|
|
|
|
SCReturnInt(0);
|
|
|
|
} else {
|
|
|
|
match_offset = (uint32_t)((found - payload) + cd->content_len);
|
|
|
|
det_ctx->payload_offset = match_offset;
|
|
|
|
|
|
|
|
if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
|
|
|
|
SCLogDebug("no relative match coming up, so this is a match");
|
|
|
|
goto match;
|
|
|
|
}
|
|
|
|
|
|
|
|
BUG_ON(sm->next == NULL);
|
|
|
|
|
|
|
|
/* see if the next payload keywords match. If not, we will
|
|
|
|
* search for another occurence of this http client body content
|
|
|
|
* and see if the others match then until we run out of matches */
|
|
|
|
int r = DoInspectHttpClientBody(de_ctx, det_ctx, s, sm->next,
|
|
|
|
payload, payload_len);
|
|
|
|
if (r == 1) {
|
|
|
|
SCReturnInt(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (det_ctx->discontinue_matching)
|
|
|
|
SCReturnInt(0);
|
|
|
|
|
|
|
|
/* set the previous match offset to the start of this match + 1 */
|
|
|
|
prev_offset = (match_offset - (cd->content_len - 1));
|
|
|
|
SCLogDebug("trying to see if there is another match after "
|
|
|
|
"prev_offset %"PRIu32, prev_offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
} while(1);
|
|
|
|
} else {
|
|
|
|
/* we should never get here, but bail out just in case */
|
|
|
|
BUG_ON(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
SCReturnInt(0);
|
|
|
|
|
|
|
|
match:
|
|
|
|
/* this sigmatch matched, inspect the next one. If it was the last,
|
|
|
|
* the payload portion of the signature matched. */
|
|
|
|
if (sm->next != NULL) {
|
|
|
|
int r = DoInspectHttpClientBody(de_ctx, det_ctx, s, sm->next, payload,
|
|
|
|
payload_len);
|
|
|
|
SCReturnInt(r);
|
|
|
|
} else {
|
|
|
|
SCReturnInt(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Helps buffer request bodies for different transactions and stores them
|
|
|
|
* away in detection code. Also calls the mpm on the bodies.
|
|
|
|
*
|
|
|
|
* \param det_ctx Detection engine thread ctx.
|
|
|
|
* \param f Pointer to the flow.
|
|
|
|
* \param htp_state http state.
|
|
|
|
*
|
|
|
|
* \retval cnt The match count from the mpm call. If call_mpm is 0, the retval
|
|
|
|
* is ignored.
|
|
|
|
*/
|
|
|
|
static uint32_t DetectEngineInspectHttpClientBodyMpmInspect(DetectEngineCtx *de_ctx,
|
|
|
|
DetectEngineThreadCtx *det_ctx,
|
|
|
|
Signature *s, Flow *f,
|
|
|
|
HtpState *htp_state)
|
|
|
|
{
|
|
|
|
uint32_t cnt = 0;
|
|
|
|
size_t idx = 0;
|
|
|
|
htp_tx_t *tx = NULL;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
for (idx = AppLayerTransactionGetInspectId(f);
|
|
|
|
i < det_ctx->hcbd_buffers_list_len; idx++, i++) {
|
|
|
|
|
|
|
|
/* if the buffer already exists, use it */
|
|
|
|
if (det_ctx->hcbd_buffers[i] != NULL) {
|
|
|
|
/* we only call the mpm if the hcbd mpm has been set */
|
|
|
|
if (s->mpm_flags & SIG_FLAG_MPM_HCBDCONTENT) {
|
|
|
|
cnt += HttpClientBodyPatternSearch(det_ctx,
|
|
|
|
det_ctx->hcbd_buffers[i],
|
|
|
|
det_ctx->hcbd_buffers_len[i]);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
tx = list_get(htp_state->connp->conn->transactions, idx);
|
|
|
|
if (tx == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
SCHtpTxUserData *htud = (SCHtpTxUserData *)htp_tx_get_user_data(tx);
|
|
|
|
if (htud == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
HtpBodyChunk *cur = htud->body.first;
|
|
|
|
|
|
|
|
if (htud->body.nchunks == 0) {
|
|
|
|
SCLogDebug("No http chunks to inspect for this transacation");
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
/* no chunks?!! move on to the next transaction */
|
|
|
|
if (cur == NULL) {
|
|
|
|
SCLogDebug("No http chunks to inspect");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this applies only for the client request body like the keyword name says */
|
|
|
|
if (htud->body.operation != HTP_BODY_REQUEST) {
|
|
|
|
SCLogDebug("htp chunk not a request chunk");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (htud->content_len != htud->content_len_so_far) {
|
|
|
|
SCLogDebug("we still haven't seen the entire request body. "
|
|
|
|
"Let's defer body inspection till we see the "
|
|
|
|
"entire body.");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t *chunks_buffer = NULL;
|
|
|
|
int32_t chunks_buffer_len = 0;
|
|
|
|
while (cur != NULL) {
|
|
|
|
/* \todo Currently we limit the body length we inspect. We
|
|
|
|
* should change to handling chunks statefully */
|
|
|
|
if (chunks_buffer_len > de_ctx->hcbd_buffer_limit)
|
|
|
|
break;
|
|
|
|
chunks_buffer_len += cur->len;
|
|
|
|
if ( (chunks_buffer = SCRealloc(chunks_buffer, chunks_buffer_len)) == NULL) {
|
|
|
|
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
memcpy(chunks_buffer + chunks_buffer_len - cur->len, cur->data, cur->len);
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
/* store the buffers. We will need it for further inspection */
|
|
|
|
det_ctx->hcbd_buffers[i] = chunks_buffer;
|
|
|
|
det_ctx->hcbd_buffers_len[i] = chunks_buffer_len;
|
|
|
|
|
|
|
|
/* carry out the mpm if we have hcbd mpm set */
|
|
|
|
if (s->mpm_flags & SIG_FLAG_MPM_HCBDCONTENT)
|
|
|
|
cnt += HttpClientBodyPatternSearch(det_ctx, chunks_buffer, chunks_buffer_len);
|
|
|
|
} /* else - if (htud->body.nchunks == 0) */
|
|
|
|
} /* for (idx = AppLayerTransactionGetInspectId(f); .. */
|
|
|
|
|
|
|
|
SCReturnUInt(cnt);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Do the http_client_body content inspection for a signature.
|
|
|
|
*
|
|
|
|
* \param de_ctx Detection engine context.
|
|
|
|
* \param det_ctx Detection engine thread context.
|
|
|
|
* \param s Signature to inspect.
|
|
|
|
* \param f Flow.
|
|
|
|
* \param flags App layer flags.
|
|
|
|
* \param state App layer state.
|
|
|
|
*
|
|
|
|
* \retval 0 No match.
|
|
|
|
* \retval 1 Match.
|
|
|
|
*/
|
|
|
|
int DetectEngineInspectHttpClientBody(DetectEngineCtx *de_ctx,
|
|
|
|
DetectEngineThreadCtx *det_ctx,
|
|
|
|
Signature *s, Flow *f, uint8_t flags,
|
|
|
|
void *alstate)
|
|
|
|
{
|
|
|
|
SCEnter();
|
|
|
|
int r = 0;
|
|
|
|
HtpState *htp_state = NULL;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
htp_state = (HtpState *)alstate;
|
|
|
|
if (htp_state == NULL) {
|
|
|
|
SCLogDebug("no HTTP state");
|
|
|
|
SCReturnInt(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* locking the flow, we will inspect the htp state */
|
|
|
|
SCMutexLock(&f->m);
|
|
|
|
|
|
|
|
if (htp_state->connp == NULL) {
|
|
|
|
SCLogDebug("HTP state has no connp");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* it is either the first entry into this function. If it is not,
|
|
|
|
* then we just don't have any http transactions */
|
|
|
|
if (det_ctx->hcbd_buffers_list_len == 0) {
|
|
|
|
/* get the transaction id */
|
|
|
|
int tmp_idx = AppLayerTransactionGetInspectId(f);
|
|
|
|
/* error! get out of here */
|
|
|
|
if (tmp_idx == -1)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
/* let's get the transaction count. We need this to hold the client body
|
|
|
|
* buffer for each transaction */
|
|
|
|
det_ctx->hcbd_buffers_list_len = list_size(htp_state->connp->conn->transactions) - tmp_idx;
|
|
|
|
/* no transactions?! cool. get out of here */
|
|
|
|
if (det_ctx->hcbd_buffers_list_len == 0)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
/* assign space to hold buffers. Each per transaction */
|
|
|
|
det_ctx->hcbd_buffers = SCMalloc(det_ctx->hcbd_buffers_list_len * sizeof(uint8_t *));
|
|
|
|
if (det_ctx->hcbd_buffers == NULL) {
|
|
|
|
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
memset(det_ctx->hcbd_buffers, 0, det_ctx->hcbd_buffers_list_len * sizeof(uint8_t *));
|
|
|
|
|
|
|
|
det_ctx->hcbd_buffers_len = SCMalloc(det_ctx->hcbd_buffers_list_len * sizeof(uint32_t));
|
|
|
|
if (det_ctx->hcbd_buffers_len == NULL) {
|
|
|
|
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
memset(det_ctx->hcbd_buffers_len, 0, det_ctx->hcbd_buffers_list_len * sizeof(uint32_t));
|
|
|
|
} /* if (det_ctx->hcbd_buffers_list_len == 0) */
|
|
|
|
|
|
|
|
if (s->mpm_flags & SIG_FLAG_MPM_HCBDCONTENT) {
|
|
|
|
if (det_ctx->de_mpm_scanned_hcbd == FALSE) {
|
|
|
|
uint32_t cnt = DetectEngineInspectHttpClientBodyMpmInspect(de_ctx,
|
|
|
|
det_ctx, s,
|
|
|
|
f, htp_state);
|
|
|
|
if (cnt <= 0)
|
|
|
|
det_ctx->de_have_hcbd = FALSE;
|
|
|
|
|
|
|
|
det_ctx->de_mpm_scanned_hcbd = TRUE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
DetectEngineInspectHttpClientBodyMpmInspect(de_ctx, det_ctx, s, f,
|
|
|
|
htp_state);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (det_ctx->de_have_hcbd == FALSE &&
|
|
|
|
s->mpm_flags & SIG_FLAG_MPM_HCBDCONTENT &&
|
|
|
|
!(s->mpm_flags & SIG_FLAG_MPM_HCBDCONTENT_NEG)) {
|
|
|
|
SCLogDebug("mpm results failure for client_body. Get out of here");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((s->mpm_flags & SIG_FLAG_MPM_HCBDCONTENT) && (det_ctx->de_mpm_scanned_hcbd == TRUE)) {
|
|
|
|
/* filter out the sig that needs a match, but have no matches */
|
|
|
|
if (!(det_ctx->pmq.pattern_id_bitarray[(s->mpm_hcbdpattern_id / 8)] & (1 << (s->mpm_hcbdpattern_id % 8))) &&
|
|
|
|
!(s->mpm_flags & SIG_FLAG_MPM_HCBDCONTENT_NEG)) {
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < det_ctx->hcbd_buffers_list_len; i++) {
|
|
|
|
uint8_t *hcbd_buffer = det_ctx->hcbd_buffers[i];
|
|
|
|
uint32_t hcbd_buffer_len = det_ctx->hcbd_buffers_len[i];
|
|
|
|
|
|
|
|
if (hcbd_buffer == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
r = DoInspectHttpClientBody(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HCBDMATCH],
|
|
|
|
hcbd_buffer, hcbd_buffer_len);
|
|
|
|
if (r == 1) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
|
|
|
SCMutexUnlock(&f->m);
|
|
|
|
SCReturnInt(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Clean the hcbd buffers.
|
|
|
|
*
|
|
|
|
* \param det_ctx Pointer to the detection engine thread ctx.
|
|
|
|
*/
|
|
|
|
void DetectEngineCleanHCBDBuffers(DetectEngineThreadCtx *det_ctx)
|
|
|
|
{
|
|
|
|
if (det_ctx->hcbd_buffers_list_len != 0) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < det_ctx->hcbd_buffers_list_len; i++) {
|
|
|
|
if (det_ctx->hcbd_buffers[i] != NULL)
|
|
|
|
SCFree(det_ctx->hcbd_buffers[i]);
|
|
|
|
}
|
|
|
|
SCFree(det_ctx->hcbd_buffers);
|
|
|
|
det_ctx->hcbd_buffers = NULL;
|
|
|
|
det_ctx->hcbd_buffers_list_len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************Unittests**********************************/
|
|
|
|
|
|
|
|
#ifdef UNITTESTS
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest01(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.1\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:body1This; http_client_body; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if ((PacketAlertCheck(p1, 1))) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (!(PacketAlertCheck(p2, 1))) {
|
|
|
|
printf("sid 1 didn't match but should have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest02(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 19\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:body1; http_client_body; offset:5; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (!(PacketAlertCheck(p1, 1))) {
|
|
|
|
printf("sid 1 didn't match but should have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest03(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:body1; http_client_body; offset:16; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p1, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p2, 1)) {
|
|
|
|
printf("sid 1 didn't match but should have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest04(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:!body1; http_client_body; offset:16; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p1, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (!PacketAlertCheck(p2, 1)) {
|
|
|
|
printf("sid 1 didn't match but should have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest05(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:body1; http_client_body; depth:25; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p1, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (!PacketAlertCheck(p2, 1)) {
|
|
|
|
printf("sid 1 didn't match but should have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest06(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:!body1; http_client_body; depth:25; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p1, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p2, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest07(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:!body1; http_client_body; depth:15; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p1, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (!PacketAlertCheck(p2, 1)) {
|
|
|
|
printf("sid 1 didn't match but should have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest08(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:!body1; http_client_body; depth:25; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p1, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p2, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest09(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:body1; http_client_body; "
|
|
|
|
"content:This; http_client_body; within:5; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p1, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (!PacketAlertCheck(p2, 1)) {
|
|
|
|
printf("sid 1 didn't match but should have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest10(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:body1; http_client_body; "
|
|
|
|
"content:!boom; http_client_body; within:5; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p1, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (!PacketAlertCheck(p2, 1)) {
|
|
|
|
printf("sid 1 didn't match but should have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest11(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:body1; http_client_body; "
|
|
|
|
"content:boom; http_client_body; within:5; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p1, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p2, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest12(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:body1; http_client_body; "
|
|
|
|
"content:!This; http_client_body; within:5; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p1, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p2, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest13(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:body1; http_client_body; "
|
|
|
|
"content:dummy; http_client_body; distance:5; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p1, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (!PacketAlertCheck(p2, 1)) {
|
|
|
|
printf("sid 1 didn't match but should have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest14(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:body1; http_client_body; "
|
|
|
|
"content:!dummy; http_client_body; distance:10; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p1, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (!PacketAlertCheck(p2, 1)) {
|
|
|
|
printf("sid 1 didn't match but should have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest15(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:body1; http_client_body; "
|
|
|
|
"content:dummy; http_client_body; distance:10; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p1, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p2, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest16(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
Packet *p2 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
HtpState *http_state = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] =
|
|
|
|
"GET /index.html HTTP/1.0\r\n"
|
|
|
|
"Host: www.openinfosecfoundation.org\r\n"
|
|
|
|
"Content-Type: text/html\r\n"
|
|
|
|
"Content-Length: 46\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"This is dummy body1";
|
|
|
|
uint8_t http2_buf[] =
|
|
|
|
"This is dummy message body2";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
uint32_t http2_len = sizeof(http2_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
p2->flow = &f;
|
|
|
|
p2->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p2->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p2->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:body1; http_client_body; "
|
|
|
|
"content:!dummy; http_client_body; distance:5; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
|
|
|
|
if (http_state == NULL) {
|
|
|
|
printf("no http state: \n");
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p1, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
|
|
|
|
result = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do detect */
|
|
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
|
|
|
|
|
|
|
|
if (PacketAlertCheck(p2, 1)) {
|
|
|
|
printf("sid 1 matched but shouldn't have");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
UTHFreePackets(&p2, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest17(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] = "This is dummy body1";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:body1; http_client_body; "
|
|
|
|
"content:bambu; http_client_body; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
/* start the search phase */
|
|
|
|
det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p1);
|
|
|
|
uint32_t r = HttpClientBodyPatternSearch(det_ctx, http1_buf, http1_len);
|
|
|
|
if (r != 1) {
|
|
|
|
printf("expected 1 result, got %"PRIu32": ", r);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest18(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] = "This is dummy body1";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:body1; http_client_body; "
|
|
|
|
"content:bambu; http_client_body; fast_pattern; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
/* start the search phase */
|
|
|
|
det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p1);
|
|
|
|
uint32_t r = HttpClientBodyPatternSearch(det_ctx, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("expected 1 result, got %"PRIu32": ", r);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest19(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] = "This is dummy body1";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:bambu; http_client_body; "
|
|
|
|
"content:is; http_client_body; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
/* start the search phase */
|
|
|
|
det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p1);
|
|
|
|
uint32_t r = HttpClientBodyPatternSearch(det_ctx, http1_buf, http1_len);
|
|
|
|
if (r != 0) {
|
|
|
|
printf("expected 1 result, got %"PRIu32": ", r);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DetectEngineHttpClientBodyTest20(void)
|
|
|
|
{
|
|
|
|
TcpSession ssn;
|
|
|
|
Packet *p1 = NULL;
|
|
|
|
ThreadVars th_v;
|
|
|
|
DetectEngineCtx *de_ctx = NULL;
|
|
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
|
|
Flow f;
|
|
|
|
uint8_t http1_buf[] = "This is dummy body1";
|
|
|
|
uint32_t http1_len = sizeof(http1_buf) - 1;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
f.src.family = AF_INET;
|
|
|
|
f.dst.family = AF_INET;
|
|
|
|
|
|
|
|
p1->flow = &f;
|
|
|
|
p1->flowflags |= FLOW_PKT_TOSERVER;
|
|
|
|
p1->flowflags |= FLOW_PKT_ESTABLISHED;
|
|
|
|
p1->flags |= PKT_HAS_FLOW;
|
|
|
|
f.alproto = ALPROTO_HTTP;
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
FlowL7DataPtrInit(&f);
|
|
|
|
|
|
|
|
de_ctx = DetectEngineCtxInit();
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
|
|
|
|
"(msg:\"http client body test\"; "
|
|
|
|
"content:bambu; http_client_body; "
|
|
|
|
"content:is; http_client_body; fast_pattern; "
|
|
|
|
"sid:1;)");
|
|
|
|
if (de_ctx->sig_list == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
SigGroupBuild(de_ctx);
|
|
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
|
|
|
|
/* start the search phase */
|
|
|
|
det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p1);
|
|
|
|
uint32_t r = HttpClientBodyPatternSearch(det_ctx, http1_buf, http1_len);
|
|
|
|
if (r != 2) {
|
|
|
|
printf("expected 1 result, got %"PRIu32": ", r);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigGroupCleanup(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
SigCleanSignatures(de_ctx);
|
|
|
|
if (de_ctx != NULL)
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
|
|
|
|
FlowL7DataPtrFree(&f);
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
UTHFreePackets(&p1, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* UNITTESTS */
|
|
|
|
|
|
|
|
void DetectEngineHttpClientBodyRegisterTests(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
#ifdef UNITTESTS
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest01",
|
|
|
|
DetectEngineHttpClientBodyTest01, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest02",
|
|
|
|
DetectEngineHttpClientBodyTest02, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest03",
|
|
|
|
DetectEngineHttpClientBodyTest03, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest04",
|
|
|
|
DetectEngineHttpClientBodyTest04, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest05",
|
|
|
|
DetectEngineHttpClientBodyTest05, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest06",
|
|
|
|
DetectEngineHttpClientBodyTest06, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest07",
|
|
|
|
DetectEngineHttpClientBodyTest07, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest08",
|
|
|
|
DetectEngineHttpClientBodyTest08, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest09",
|
|
|
|
DetectEngineHttpClientBodyTest09, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest10",
|
|
|
|
DetectEngineHttpClientBodyTest10, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest11",
|
|
|
|
DetectEngineHttpClientBodyTest11, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest12",
|
|
|
|
DetectEngineHttpClientBodyTest12, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest13",
|
|
|
|
DetectEngineHttpClientBodyTest13, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest14",
|
|
|
|
DetectEngineHttpClientBodyTest14, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest15",
|
|
|
|
DetectEngineHttpClientBodyTest15, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest16",
|
|
|
|
DetectEngineHttpClientBodyTest16, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest17",
|
|
|
|
DetectEngineHttpClientBodyTest17, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest18",
|
|
|
|
DetectEngineHttpClientBodyTest18, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest19",
|
|
|
|
DetectEngineHttpClientBodyTest19, 1);
|
|
|
|
UtRegisterTest("DetectEngineHttpClientBodyTest20",
|
|
|
|
DetectEngineHttpClientBodyTest20, 1);
|
|
|
|
#endif /* UNITTESTS */
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|