applayer uri match and modified http handling

remotes/origin/master-1.0.x
Gurvinder Singh 17 years ago committed by Victor Julien
parent fcb03099a3
commit 356a8bf385

@ -64,7 +64,11 @@ static void *HTPStateAlloc(void)
htp_state_memuse+=sizeof(HtpState);
SCMutexUnlock(&htp_state_mem_lock);
#endif
/* Create a list_array of size 8 to store the incoming requests, the size of
8 has been chosen as half the size of conn->transactions in the
HTP lib. As we are storing only requests here not responses!! */
s->recent_in_tx = list_array_create(8);
htp_connp_set_user_data(s->connp, (void *)s);
SCReturnPtr((void *)s, "void");
error:
@ -88,6 +92,8 @@ static void HTPStateFree(void *state)
if (s->connp != NULL) {
htp_connp_destroy_all(s->connp);
}
if (s->recent_in_tx != NULL)
list_destroy(s->recent_in_tx);
}
free(s);
@ -260,6 +266,40 @@ void HTPFreeConfig(void)
htp_config_destroy(cfg);
}
/**
* \brief callback for request to store the recent incoming request
in to the recent_in_tx for the given htp state
* \param connp pointer to the current connection parser which has the htp
* state in it as user data
*/
static int HTPCallbackRequest(htp_connp_t *connp) {
SCEnter();
HtpState *hstate = (HtpState *)connp->user_data;
list_add(hstate->recent_in_tx, connp->in_tx);
SCReturnInt(0);
}
/**
* \brief callback for response to remove the recent received requests
from the recent_in_tx for the given htp state
* \param connp pointer to the current connection parser which has the htp
* state in it as user data
*/
static int HTPCallbackResponse(htp_connp_t *connp) {
SCEnter();
HtpState *hstate = (HtpState *)connp->user_data;
htp_tx_t *tx = NULL;
uint8_t i = 0;
for (i=0; i < list_size(hstate->recent_in_tx) - 1; i++) {
tx = list_pop(hstate->recent_in_tx);
if (tx != NULL)
htp_tx_destroy(tx);
}
SCReturnInt(0);
}
/**
* \brief Register the HTTP protocol and state handling functions to APP layer
* of the engine.
@ -275,20 +315,16 @@ void RegisterHTPParsers(void)
HTPHandleResponseData);
cfg = htp_config_create();
/* Register the callback for request to store the recent incoming request
in to the recent_in_tx for the given htp state */
htp_config_register_request(cfg, HTPCallbackRequest);
/* Register the callback for response to remove the recently received request
from the recent_in_tx for the given htp state */
htp_config_register_response(cfg, HTPCallbackResponse);
/* set the normalized request parsing to be used in uricontent matching */
htp_config_set_generate_request_uri_normalized(cfg, 1);
}
/**
* \brief Returns the main (first) HTTP transaction
*
* \param htp_state HTP library state
* \returns Main HTP transation
*
*/
htp_tx_t *HTPTransactionMain(const HtpState *htp_state)
{
SCEnter();
SCReturnPtr(list_get(htp_state->connp->conn->transactions, 0), "htp_tx_t");
}
#ifdef UNITTESTS
/** \test Test case where chunks are sent in smaller chunks and check the

@ -24,7 +24,7 @@ typedef struct HtpState_ {
htp_connp_t *connp; /**< Connection parser structure for each connection */
uint8_t flags;
list_t *recent_in_tx; /**< Point to the new received HTTP request */
} HtpState;
htp_cfg_t *cfg; /**< Config structure for HTP library */
@ -33,7 +33,6 @@ void RegisterHTPParsers(void);
void HTPParserRegisterTests(void);
void HTPAtExitPrintStats(void);
void HTPFreeConfig(void);
htp_tx_t *HTPTransactionMain(const HtpState *);
#endif /* __APP_LAYER_HTP_H__ */

@ -21,7 +21,9 @@
#include "util-debug.h"
static uint16_t app_layer_sid = 0;
static AppLayerProto al_proto_table[ALPROTO_MAX];
static AppLayerProto al_proto_table[ALPROTO_MAX]; /**< Application layer protocol
table mapped to their
corresponding parsers */
#define MAX_PARSERS 100
static AppLayerParserTableElement al_parser_table[MAX_PARSERS];

@ -35,28 +35,75 @@ uint16_t PatternMatchDefaultMatcher(void) {
* \param det_ctx detection engine thread ctx
* \param p packet to scan
*/
uint32_t PacketPatternScan(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, Packet *p) {
uint32_t PacketPatternScan(ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
Packet *p)
{
uint32_t ret;
det_ctx->pmq.mode = PMQ_MODE_SCAN;
ret = mpm_table[det_ctx->sgh->mpm_ctx->mpm_type].Scan(det_ctx->sgh->mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, p->payload, p->payload_len);
ret = mpm_table[det_ctx->sgh->mpm_ctx->mpm_type].Scan
(det_ctx->sgh->mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, p->payload,
p->payload_len);
//printf("PacketPatternScan: ret %" PRIu32 "\n", ret);
return ret;
}
/** \brief Uri Pattern match, scan part -- searches for only 'scan' patterns,
* normally one per signature.
* \param tv threadvars
* \param det_ctx detection engine thread ctx
* \param p packet to scan
*/
uint32_t UriPatternScan(ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
uint8_t *content, uint16_t content_len)
{
uint32_t ret;
det_ctx->pmq.mode = PMQ_MODE_SCAN;
ret = mpm_table[det_ctx->sgh->mpm_uri_ctx->mpm_type].Scan
(det_ctx->sgh->mpm_uri_ctx, &det_ctx->mtcu, &det_ctx->pmq,
content, content_len);
SCLogDebug("ret %" PRIu32 "", ret);
return ret;
}
/** \brief Pattern match, search part -- searches for all other patterns
* \param tv threadvars
* \param det_ctx detection engine thread ctx
* \param p packet to scan
*/
uint32_t PacketPatternMatch(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, Packet *p) {
uint32_t PacketPatternMatch(ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
Packet *p)
{
uint32_t ret;
det_ctx->pmq.mode = PMQ_MODE_SEARCH;
ret = mpm_table[det_ctx->sgh->mpm_ctx->mpm_type].Search
(det_ctx->sgh->mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, p->payload,
p->payload_len);
SCLogDebug("ret %" PRIu32 "", ret);
return ret;
}
/** \brief Uri Pattern match, search part -- searches for all other patterns
* \param tv threadvars
* \param det_ctx detection engine thread ctx
* \param p packet to scan
*/
uint32_t UriPatternMatch(ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
uint8_t *content, uint16_t content_len)
{
uint32_t ret;
det_ctx->pmq.mode = PMQ_MODE_SEARCH;
ret = mpm_table[det_ctx->sgh->mpm_ctx->mpm_type].Search(det_ctx->sgh->mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, p->payload, p->payload_len);
ret = mpm_table[det_ctx->sgh->mpm_uri_ctx->mpm_type].Search
(det_ctx->sgh->mpm_uri_ctx, &det_ctx->mtcu, &det_ctx->pmq, content,
content_len);
//printf("PacketPatternMatch: ret %" PRIu32 "\n", ret);
SCLogDebug("ret %" PRIu32 "", ret);
return ret;
}

@ -7,6 +7,9 @@ uint16_t PatternMatchDefaultMatcher(void);
uint32_t PacketPatternScan(ThreadVars *, DetectEngineThreadCtx *, Packet *);
uint32_t PacketPatternMatch(ThreadVars *, DetectEngineThreadCtx *, Packet *);
uint32_t UriPatternScan(ThreadVars *, DetectEngineThreadCtx *, uint8_t *, uint16_t);
uint32_t UriPatternMatch(ThreadVars *, DetectEngineThreadCtx *, uint8_t *, uint16_t);
void PacketPatternCleanup(ThreadVars *, DetectEngineThreadCtx *);
void PatternMatchPrepare(MpmCtx *, uint16_t);

@ -99,27 +99,25 @@ int DetectHttpCookieMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
goto end;
}
htp_tx_t *tx = list_get(htp_state->connp->conn->transactions, 0);
if (tx == NULL) {
SCLogDebug("No HTTP transaction has received on the connection");
goto end;
}
htp_header_t *h = NULL;
h = (htp_header_t *)table_getc(tx->request_headers, "Cookie");
if (h == NULL) {
SCLogDebug("no HTTP Cookie header in the received request");
goto end;
}
htp_tx_t *tx = NULL;
list_iterator_reset(htp_state->recent_in_tx);
while ((tx = list_iterator_next(htp_state->recent_in_tx)) != NULL) {
htp_header_t *h = NULL;
h = (htp_header_t *) table_getc(tx->request_headers, "Cookie");
if (h == NULL) {
SCLogDebug("no HTTP Cookie header in the received request");
goto end;
}
SCLogDebug("we have a cookie header");
SCLogDebug("we have a cookie header");
if (SpmSearch((uint8_t *)bstr_ptr(h->value), bstr_size(h->value), co->data,
co->data_len) != NULL)
{
SCLogDebug("match has been found in received request and given http_"
"cookie rule");
ret = 1;
if (SpmSearch((uint8_t *) bstr_ptr(h->value), bstr_size(h->value),
co->data, co->data_len) != NULL) {
SCLogDebug("match has been found in received request and given http_"
"cookie rule");
ret = 1;
}
}
end:

@ -72,7 +72,7 @@ int DetectHttpMethodMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
SCEnter();
DetectHttpMethodData *data = (DetectHttpMethodData *)m->ctx;
HtpState *hs = (HtpState *)state;
htp_tx_t *tx;
htp_tx_t *tx = NULL;
int ret = 0;
if (hs == NULL) {
@ -81,34 +81,33 @@ int DetectHttpMethodMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
}
SCMutexLock(&f->m);
tx = HTPTransactionMain(hs);
if (tx == NULL) {
SCLogDebug("No HTP transaction.");
goto end;
}
/* Compare the numeric methods if they are known, otherwise compare
* the raw values.
*/
if (data->method != M_UNKNOWN) {
if (data->method == tx->request_method_number) {
SCLogDebug("Matched numeric HTTP method values.");
ret = 1;
}
} else if (tx->request_method != NULL) {
const uint8_t *meth_str = (const uint8_t *)bstr_ptr(tx->request_method);
if ( (meth_str != NULL)
&& SpmSearch((uint8_t*)meth_str, bstr_size(tx->request_method),
data->content, data->content_len) != NULL)
{
SCLogDebug("Matched raw HTTP method values.");
ret = 1;
list_iterator_reset(hs->recent_in_tx);
while ((tx = list_iterator_next(hs->recent_in_tx)) != NULL) {
/* Compare the numeric methods if they are known, otherwise compare
* the raw values.
*/
if (data->method != M_UNKNOWN) {
if (data->method == tx->request_method_number) {
SCLogDebug("Matched numeric HTTP method values.");
ret = 1;
}
} else if (tx->request_method != NULL) {
const uint8_t *meth_str = (const uint8_t *)
bstr_ptr(tx->request_method);
if ((meth_str != NULL) &&
SpmSearch((uint8_t*) meth_str, bstr_size(tx->request_method),
data->content, data->content_len) != NULL)
{
SCLogDebug("Matched raw HTTP method values.");
ret = 1;
}
}
}
end:
SCMutexUnlock(&f->m);
SCReturnInt(ret);
}

@ -196,7 +196,7 @@ int DetectPcreMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, S
/* indicate to uricontent that we have a uri,
* we scanned it _AND_ we found pattern matches. */
det_ctx->de_have_httpuri = 1;
det_ctx->de_have_httpuri = TRUE;
}
}
}

@ -1,41 +1,79 @@
/* Simple uricontent match part of the detection engine.
/* Copyright (C) 2008 by Victor Julien <victor@inliniac.net>
* Copyright (c) 2009 Open Information Security Foundation */
/**
* \file Simple uricontent match part of the detection engine.
*
* \author Victor Julien <victor@inliniac.net>
* \author Gurvinder Singh <gurvindersinghdahiya@gmail.com>
*
* Copyright (C) 2008 by Victor Julien <victor@inliniac.net> */
*/
#include "suricata-common.h"
#include "decode.h"
#include "detect.h"
#include "detect-uricontent.h"
#include "detect-engine-mpm.h"
#include "detect-parse.h"
#include "detect-engine.h"
#include "flow.h"
#include "detect-flow.h"
#include "flow-var.h"
#include "threads.h"
#include "flow-alert-sid.h"
#include "stream.h"
#include "app-layer-parser.h"
#include "app-layer-protos.h"
#include "app-layer-htp.h"
#include "util-mpm.h"
#include "util-print.h"
#include "util-debug.h"
#include "util-unittest.h"
#include "util-binsearch.h"
int DetectUricontentMatch (ThreadVars *, DetectEngineThreadCtx *, Packet *, Signature *, SigMatch *);
/* prototypes */
int DetectUricontentMatch (ThreadVars *, DetectEngineThreadCtx *, Packet *,
Signature *, SigMatch *);
int DetectUricontentSetup (DetectEngineCtx *, Signature *, SigMatch *, char *);
void HttpUriRegisterTests(void);
void DetectUricontentRegister (void) {
int DetectAppLayerUricontentMatch (ThreadVars *, DetectEngineThreadCtx *,
Flow *, uint8_t , void *,
Signature *, SigMatch *);
/**
* \brief Registration function for uricontent: keyword
*/
void DetectUricontentRegister (void)
{
sigmatch_table[DETECT_URICONTENT].name = "uricontent";
sigmatch_table[DETECT_URICONTENT].AppLayerMatch = DetectAppLayerUricontentMatch;
sigmatch_table[DETECT_URICONTENT].Match = DetectUricontentMatch;
sigmatch_table[DETECT_URICONTENT].Setup = DetectUricontentSetup;
sigmatch_table[DETECT_URICONTENT].Free = NULL;
sigmatch_table[DETECT_URICONTENT].RegisterTests = HttpUriRegisterTests;
sigmatch_table[DETECT_URICONTENT].alproto = ALPROTO_HTTP;
sigmatch_table[DETECT_URICONTENT].flags |= SIGMATCH_PAYLOAD;
}
/* pass on the uricontent_max_id */
uint32_t DetectUricontentMaxId(DetectEngineCtx *de_ctx) {
/**
* \brief pass on the uricontent_max_id
* \param de_ctx pointer to the detect egine context whose max id is asked
*/
uint32_t DetectUricontentMaxId(DetectEngineCtx *de_ctx)
{
return de_ctx->uricontent_max_id;
}
void PktHttpUriFree(Packet *p) {
/**
* \brief Free the stored http_uri in the given packet
* \param p pointer to the given packet whose uri has to be freed
*/
void PktHttpUriFree(Packet *p)
{
int i;
for (i = 0; i < p->http_uri.cnt; i++) {
@ -45,10 +83,11 @@ void PktHttpUriFree(Packet *p) {
p->http_uri.cnt = 0;
}
static inline int
TestOffsetDepth(MpmMatch *m, DetectUricontentData *co) {
static inline int TestOffsetDepth(MpmMatch *m, DetectUricontentData *co)
{
if (co->offset == 0 ||
(co->offset && ((m->offset+1) - co->uricontent_len) >= co->offset)) {
(co->offset && ((m->offset+1) - co->uricontent_len) >= co->offset))
{
if (co->depth == 0 ||
(co->depth && (m->offset+1) <= co->depth))
{
@ -65,8 +104,9 @@ TestOffsetDepth(MpmMatch *m, DetectUricontentData *co) {
* was done like this is to make sure we can handle partial matches
* that turn out to fail being followed by full matches later in the
* packet. This adds some runtime complexity however. */
static inline int
TestWithinDistanceOffsetDepth(ThreadVars *t, DetectEngineThreadCtx *det_ctx, MpmMatch *m, SigMatch *nsm)
static inline int TestWithinDistanceOffsetDepth(ThreadVars *t,
DetectEngineThreadCtx *det_ctx,
MpmMatch *m, SigMatch *nsm)
{
//printf("test_nextsigmatch m:%p, nsm:%p\n", m,nsm);
if (nsm == NULL)
@ -76,21 +116,26 @@ TestWithinDistanceOffsetDepth(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Mpm
MpmMatch *nm = det_ctx->mtcu.match[co->id].top;
for (; nm; nm = nm->next) {
//printf("test_nextsigmatch: (nm->offset+1) %" PRIu32 ", (m->offset+1) %" PRIu32 "\n", (nm->offset+1), (m->offset+1));
SCLogDebug("(nm->offset+1) %" PRIu32 ", (m->offset+1) %" PRIu32 "",
(nm->offset+1), (m->offset+1));
if ((co->within == 0 || (co->within &&
((nm->offset+1) > (m->offset+1)) &&
((nm->offset+1) - (m->offset+1) <= co->within))))
{
//printf("test_nextsigmatch: WITHIN (nm->offset+1) %" PRIu32 ", (m->offset+1) %" PRIu32 "\n", (nm->offset+1), (m->offset+1));
SCLogDebug("WITHIN (nm->offset+1) %" PRIu32 ", (m->offset+1) "
"%" PRIu32 "", (nm->offset+1), (m->offset+1));
if (co->distance == 0 || (co->distance &&
((nm->offset+1) > (m->offset+1)) &&
((nm->offset+1) - (m->offset+1) >= co->distance)))
{
if (TestOffsetDepth(nm, co) == 1) {
//printf("test_nextsigmatch: DISTANCE (nm->offset+1) %" PRIu32 ", (m->offset+1) %" PRIu32 "\n", (nm->offset+1), (m->offset+1));
return TestWithinDistanceOffsetDepth(t, det_ctx, nm, nsm->next);
SCLogDebug("DISTANCE (nm->offset+1) %" PRIu32 ", "
"(m->offset+1) %" PRIu32 "", (nm->offset+1),
(m->offset+1));
return TestWithinDistanceOffsetDepth(t, det_ctx, nm,
nsm->next);
}
}
}
@ -98,8 +143,9 @@ TestWithinDistanceOffsetDepth(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Mpm
return 0;
}
static inline int
DoDetectUricontent(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, SigMatch *sm, DetectUricontentData *co)
static inline int DoDetectUricontent(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
Packet *p, SigMatch *sm,
DetectUricontentData *co)
{
int ret = 0;
char match = 0;
@ -167,26 +213,34 @@ DoDetectUricontent(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Sig
}
/*
* returns 0: no match
* 1: match
* -1: error
/**
* \brief Checks if the packet sent as the argument, has a uricontent which
* has been provided in the signature
*
* \param t Pointer to the tv for this detection module instance
* \param det_ctx Pointer to the detection engine thread context
* \param p Pointer to the Packet currently being matched
* \param s Pointer to the Signature, the packet is being currently
* matched with
* \param m Pointer to the keyword_structure(SigMatch) from the above
* Signature, the Packet is being currently matched with
*
* \retval 1 if the Packet contents match; 0 no match
*/
int DetectUricontentMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m)
int DetectUricontentMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
Packet *p, Signature *s, SigMatch *m)
{
SCEnter();
uint32_t len = 0;
/* if we don't have a uri, don't bother scanning */
if (det_ctx->de_have_httpuri == 0)
return 0;
DetectUricontentData *co = (DetectUricontentData *)m->ctx;
/* see if we had a match */
len = det_ctx->mtcu.match[co->id].len;
if (len == 0)
return 0;
if (len == 0) {
SCLogDebug("We don't have match");
SCReturnInt(0);
}
#if 0
if (SCLogDebugEnabled()) {
@ -195,20 +249,26 @@ int DetectUricontentMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet
printf("\' matched %" PRIu32 " time(s) at offsets: ", len);
MpmMatch *tmpm = NULL;
for (tmpm = det_ctx->mtcu.match[co->id].top; tmpm != NULL; tmpm = tmpm->next) {
for (tmpm = det_ctx->mtcu.match[co->id].top; tmpm != NULL;
tmpm = tmpm->next)
{
printf("%" PRIu32 " ", tmpm->offset);
}
printf("\n");
}
#endif
return DoDetectUricontent(t, det_ctx, p, m, co);
SCReturnInt(DoDetectUricontent(t, det_ctx, p, m, co));
}
int DetectUricontentSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char *contentstr)
/**
* \brief Setup the detecturicontent keyword data from the string defined in
* the rule set.
* \param contentstr Pointer to the string which has been defined in the rule
*/
DetectUricontentData *DoDetectUricontentSetup (char * contentstr)
{
DetectUricontentData *cd = NULL;
SigMatch *sm = NULL;
char *temp = NULL;
char *str = NULL;
uint16_t len = 0;
@ -220,12 +280,12 @@ int DetectUricontentSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, c
if (strlen(temp) == 0) {
free(temp);
return -1;
return NULL;
}
cd = malloc(sizeof(DetectUricontentData));
if (cd == NULL) {
printf("DetectContentSetup malloc failed\n");
SCLogError(SC_ERR_MEM_ALLOC, "malloc failed");
goto error;
}
memset(cd,0,sizeof(DetectUricontentData));
@ -237,7 +297,8 @@ int DetectUricontentSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, c
};
if (temp[pos] == '!') {
SCLogError(SC_ERR_NO_URICONTENT_NEGATION, "uricontent negation is not supported at this time. See bug #31.");
SCLogError(SC_ERR_NO_URICONTENT_NEGATION, "uricontent negation is not "
"supported at this time. See bug #31.");
goto error;
}
@ -254,14 +315,14 @@ int DetectUricontentSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, c
temp = NULL;
len = strlen(str);
//printf("DetectUricontentSetup: \"%s\", len %" PRIu32 "\n", str, len);
SCLogDebug("\"%s\", len %" PRIu32 "", str, len);
char converted = 0;
{
uint16_t i, x;
uint8_t bin = 0, binstr[3] = "", binpos = 0;
for (i = 0, x = 0; i < len; i++) {
//printf("str[%02u]: %c\n", i, str[i]);
SCLogDebug("str[%02u]: %c", i, str[i]);
if (str[i] == '|') {
if (bin) {
bin = 0;
@ -277,20 +338,21 @@ int DetectUricontentSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, c
str[i] == 'D' || str[i] == 'd' ||
str[i] == 'E' || str[i] == 'e' ||
str[i] == 'F' || str[i] == 'f') {
// printf("part of binary: %c\n", str[i]);
SCLogDebug("part of binary: %c", str[i]);
binstr[binpos] = (char)str[i];
binpos++;
if (binpos == 2) {
uint8_t c = strtol((char *)binstr, (char **) NULL, 16) & 0xFF;
uint8_t c = strtol((char *)binstr, (char **) NULL,
16) & 0xFF;
binpos = 0;
str[x] = c;
x++;
converted = 1;
}
} else if (str[i] == ' ') {
// printf("space as part of binary string\n");
SCLogDebug("space as part of binary string");
}
} else {
str[x] = str[i];
@ -318,7 +380,7 @@ int DetectUricontentSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, c
if (cd->uricontent == NULL) {
free(cd);
free(str);
return -1;
return NULL;;
}
memcpy(cd->uricontent, str, len);
@ -329,6 +391,36 @@ int DetectUricontentSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, c
cd->distance = 0;
cd->flags = 0;
free(str);
return cd;
error:
free(str);
if (cd) free(cd);
return NULL;
}
/**
* \brief Creates a SigMatch for the uricontent keyword being sent as argument,
* and appends it to the Signature(s).
*
* \param de_ctx Pointer to the detection engine context
* \param s Pointer to signature for the current Signature being parsed
* from the rules
* \param m Pointer to the head of the SigMatchs for the current rule
* being parsed
* \param contentstr Pointer to the string holding the keyword value
*
* \retval 0 on success, -1 on failure
*/
int DetectUricontentSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m,
char *contentstr)
{
SigMatch *sm = NULL;
DetectUricontentData *cd = DoDetectUricontentSetup(contentstr);
if (cd == NULL)
goto error;
/* Okay so far so good, lets get this into a SigMatch
* and put it in the Signature. */
sm = SigMatchAlloc();
@ -343,23 +435,650 @@ int DetectUricontentSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, c
cd->id = de_ctx->uricontent_max_id;
de_ctx->uricontent_max_id++;
free(str);
/* Flagged the signature as to scan the app layer data */
s->flags |=SIG_FLAG_APPLAYER;
return 0;
error:
free(str);
free(temp);
if (cd) free(cd);
if (sm) free(sm);
return -1;
}
/**
* \brief Checks if the content sent as the argument, has a uricontent which
* has been provided in the rule. This match function matches the
* normalized http uri against the given rule using multi pattern
* scan/search algorithms.
*
* \param t Pointer to the tv for this detection module instance
* \param det_ctx Pointer to the detection engine thread context
* \param content Pointer to the uri content currently being matched
* \param content_len Content_len of the received uri content
*
* \retval 1 if the uri contents match; 0 no match
*/
int DoDetectAppLayerUricontentMatch (ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
uint8_t *content, uint16_t content_len)
{
int ret = 0;
/* run the pattern matcher against the uri */
if (det_ctx->sgh->mpm_uricontent_maxlen > content_len) {
SCLogDebug("not scanning as pkt payload is smaller than the "
"largest uricontent length we need to match");
} else {
SCLogDebug("scan: (%p, maxlen %" PRIu32 ", sgh->sig_cnt "
"%" PRIu32 ")", det_ctx->sgh, det_ctx->sgh->
mpm_uricontent_maxlen, det_ctx->sgh->sig_cnt);
det_ctx->uris++;
if (det_ctx->sgh->mpm_uricontent_maxlen == 1) det_ctx->pkts_uri_scanned1++;
else if (det_ctx->sgh->mpm_uricontent_maxlen == 2) det_ctx->pkts_uri_scanned2++;
else if (det_ctx->sgh->mpm_uricontent_maxlen == 3) det_ctx->pkts_uri_scanned3++;
else if (det_ctx->sgh->mpm_uricontent_maxlen == 4) det_ctx->pkts_uri_scanned4++;
else det_ctx->pkts_uri_scanned++;
ret += UriPatternScan(tv, det_ctx, content, content_len);
SCLogDebug("post scan: cnt %" PRIu32 ", searchable %" PRIu32 "",
ret, det_ctx->pmq.searchable);
if (det_ctx->pmq.searchable > 0) {
if (det_ctx->sgh->mpm_uricontent_maxlen == 1) det_ctx->pkts_uri_searched1++;
else if (det_ctx->sgh->mpm_uricontent_maxlen == 2) det_ctx->pkts_uri_searched2++;
else if (det_ctx->sgh->mpm_uricontent_maxlen == 3) det_ctx->pkts_uri_searched3++;
else if (det_ctx->sgh->mpm_uricontent_maxlen == 4) det_ctx->pkts_uri_searched4++;
else det_ctx->pkts_uri_searched++;
ret += UriPatternMatch(tv, det_ctx, content, content_len);
}
det_ctx->pmq.searchable = 0;
det_ctx->de_scanned_uri = TRUE;
}
return ret;
}
/**
* \brief Checks if the received http request has a uricontent, which matches
* with the defined signature
*
* \param t Pointer to the tv for this detection module instance
* \param det_ctx Pointer to the detection engine thread context
* \param f pointer to the current flow
* \param flags flags to indicate the direction of the received packet
* \param state pointer the app layer state, which will cast into HtpState
* \param s pointer to the current signature
* \param m pointer to the sigmatch that we will cast into
* DetectUricontentData
*
* \retval 1 if the contents matches; 0 no match
*/
int DetectAppLayerUricontentMatch (ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
Flow *f, uint8_t flags, void *state,
Signature *s, SigMatch *sm)
{
SCEnter();
int ret = 0;
int res = 0;
DetectUricontentData *co = (DetectUricontentData *)sm->ctx;
/* if we don't have a uri, don't bother scanning */
if (det_ctx->de_have_httpuri == FALSE) {
SCLogDebug("We don't have uri");
SCReturnInt(res);
}
/* Check if we have scanned the URI already or not */
if (det_ctx->de_scanned_uri == FALSE) {
SCMutexLock(&f->m);
TcpSession *ssn = (TcpSession *) f->protoctx;
if (ssn == NULL) {
SCLogDebug("no Tcp Session");
det_ctx->de_have_httpuri = FALSE;
goto end;
}
HtpState *htp_state = ssn->aldata[AlpGetStateIdx(ALPROTO_HTTP)];
if (htp_state == NULL) {
SCLogDebug("no HTTP state");
det_ctx->de_have_httpuri = FALSE;
goto end;
}
htp_tx_t *tx = NULL;
list_iterator_reset(htp_state->recent_in_tx);
while ((tx = list_iterator_next(htp_state->recent_in_tx)) != NULL) {
if (tx->request_uri_normalized == NULL)
continue;
ret = DoDetectAppLayerUricontentMatch(tv, det_ctx, (uint8_t *)
bstr_ptr(tx->request_uri_normalized),
bstr_len(tx->request_uri_normalized));
if (ret > 0 && det_ctx->mtcu.match[co->id].len > 0) {
SCLogDebug("Match has been found in the received request and "
"given uricontent rule for s->id %"PRIu32"", s->id);
res = 1;
}
}
} else if (det_ctx->mtcu.match[co->id].len > 0) {
SCLogDebug("We have app layer URI match");
res = 1;
} else {
SCLogDebug("We don't have app layer URI match");
res = 0;
}
end:
SCMutexUnlock(&f->m);
SCReturnInt(res);
}
/*
* TESTS
* UNITTTESTS
*/
void HttpUriRegisterTests(void) {
/** none atm */
#ifdef UNITTESTS
#include "stream-tcp-reassemble.h"
/** \test Test case where path traversal has been sent as a path string in the
* HTTP URL and normalized path string is checked */
static int HTTPUriTest01(void) {
int result = 1;
Flow f;
uint8_t httpbuf1[] = "GET /../../images.gif HTTP/1.1\r\nHost: www.ExA"
"mPlE.cOM\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
TcpSession ssn;
int r = 0;
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
f.protoctx = (void *)&ssn;
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START|
STREAM_EOF, httpbuf1, httplen1);
HtpState *htp_state = ssn.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
if (htp_state == NULL) {
printf("no http state: ");
result = 0;
goto end;
}
htp_tx_t *tx = list_get(htp_state->connp->conn->transactions, 0);
if (htp_state->connp == NULL || tx->request_method_number != M_GET ||
tx->request_protocol_number != HTTP_1_1)
{
printf("expected method GET and got %s: , expected protocol "
"HTTP/1.1 and got %s \n", bstr_tocstr(tx->request_method),
bstr_tocstr(tx->request_protocol));
result = 0;
goto end;
}
if ((tx->parsed_uri->hostname == NULL) ||
(bstr_cmpc(tx->parsed_uri->hostname, "www.example.com") != 0))
{
printf("expected www.example.com as hostname, but got: %s \n",
bstr_tocstr(tx->parsed_uri->hostname));
result = 0;
goto end;
}
if ((tx->parsed_uri->path == NULL) ||
(bstr_cmpc(tx->parsed_uri->path, "/images.gif") != 0))
{
printf("expected /images.gif as path, but got: %s \n",
bstr_tocstr(tx->parsed_uri->path));
result = 0;
goto end;
}
end:
return result;
}
/** \test Test case where path traversal has been sent in special characters in
* HEX encoding in the HTTP URL and normalized path string is checked */
static int HTTPUriTest02(void) {
int result = 1;
Flow f;
uint8_t httpbuf1[] = "GET /%2e%2e/images.gif HTTP/1.1\r\nHost: www.ExA"
"mPlE.cOM\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
TcpSession ssn;
int r = 0;
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
f.protoctx = (void *)&ssn;
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START|
STREAM_EOF, httpbuf1, httplen1);
HtpState *htp_state = ssn.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
if (htp_state == NULL) {
printf("no http state: ");
result = 0;
goto end;
}
htp_tx_t *tx = list_get(htp_state->connp->conn->transactions, 0);
if (htp_state->connp == NULL || tx->request_method_number != M_GET ||
tx->request_protocol_number != HTTP_1_1)
{
printf("expected method GET and got %s: , expected protocol "
"HTTP/1.1 and got %s \n", bstr_tocstr(tx->request_method),
bstr_tocstr(tx->request_protocol));
result = 0;
goto end;
}
if ((tx->parsed_uri->hostname == NULL) ||
(bstr_cmpc(tx->parsed_uri->hostname, "www.example.com") != 0))
{
printf("expected www.example.com as hostname, but got: %s \n",
bstr_tocstr(tx->parsed_uri->hostname));
result = 0;
goto end;
}
if ((tx->parsed_uri->path == NULL) ||
(bstr_cmpc(tx->parsed_uri->path, "/images.gif") != 0))
{
printf("expected /images.gif as path, but got: %s \n",
bstr_tocstr(tx->parsed_uri->path));
result = 0;
goto end;
}
end:
return result;
}
/** \test Test case where NULL character has been sent in HEX encoding in the
* HTTP URL and normalized path string is checked */
static int HTTPUriTest03(void) {
int result = 1;
Flow f;
uint8_t httpbuf1[] = "GET%00 /images.gif HTTP/1.1\r\nHost: www.ExA"
"mPlE.cOM\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
TcpSession ssn;
int r = 0;
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
f.protoctx = (void *)&ssn;
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START|
STREAM_EOF, httpbuf1, httplen1);
HtpState *htp_state = ssn.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
if (htp_state == NULL) {
printf("no http state: ");
result = 0;
goto end;
}
htp_tx_t *tx = list_get(htp_state->connp->conn->transactions, 0);
if (htp_state->connp == NULL || tx->request_method_number != M_UNKNOWN ||
tx->request_protocol_number != HTTP_1_1)
{
printf("expected method GET and got %s: , expected protocol "
"HTTP/1.1 and got %s \n", bstr_tocstr(tx->request_method),
bstr_tocstr(tx->request_protocol));
result = 0;
goto end;
}
if ((tx->parsed_uri->hostname == NULL) ||
(bstr_cmpc(tx->parsed_uri->hostname, "www.example.com") != 0))
{
printf("expected www.example.com as hostname, but got: %s \n",
bstr_tocstr(tx->parsed_uri->hostname));
result = 0;
goto end;
}
if ((tx->parsed_uri->path == NULL) ||
(bstr_cmpc(tx->parsed_uri->path, "/images.gif") != 0))
{
printf("expected /images.gif as path, but got: %s \n",
bstr_tocstr(tx->parsed_uri->path));
result = 0;
goto end;
}
end:
return result;
}
/** \test Test case where self referencing directories request has been sent
* in the HTTP URL and normalized path string is checked */
static int HTTPUriTest04(void) {
int result = 1;
Flow f;
uint8_t httpbuf1[] = "GET /./././images.gif HTTP/1.1\r\nHost: www.ExA"
"mPlE.cOM\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
TcpSession ssn;
int r = 0;
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
f.protoctx = (void *)&ssn;
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START|
STREAM_EOF, httpbuf1, httplen1);
HtpState *htp_state = ssn.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
if (htp_state == NULL) {
printf("no http state: ");
result = 0;
goto end;
}
htp_tx_t *tx = list_get(htp_state->connp->conn->transactions, 0);
if (htp_state->connp == NULL || tx->request_method_number != M_GET ||
tx->request_protocol_number != HTTP_1_1)
{
printf("expected method GET and got %s: , expected protocol "
"HTTP/1.1 and got %s \n", bstr_tocstr(tx->request_method),
bstr_tocstr(tx->request_protocol));
result = 0;
goto end;
}
if ((tx->parsed_uri->hostname == NULL) ||
(bstr_cmpc(tx->parsed_uri->hostname, "www.example.com") != 0))
{
printf("expected www.example.com as hostname, but got: %s \n",
bstr_tocstr(tx->parsed_uri->hostname));
result = 0;
goto end;
}
if ((tx->parsed_uri->path == NULL) ||
(bstr_cmpc(tx->parsed_uri->path, "/images.gif") != 0))
{
printf("expected /images.gif as path, but got: %s \n",
bstr_tocstr(tx->parsed_uri->path));
result = 0;
goto end;
}
end:
return result;
}
/**
* \test Checks if a uricontent is registered in a Signature
*/
int DetectUriSigTest01(void)
{
SigMatch *sm = NULL;
int result = 0;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx;
Signature *s = NULL;
memset(&th_v, 0, sizeof(th_v));
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\" Test uricontent\"; "
"uricontent:\"me\"; sid:1;)");
if (s == NULL) {
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
sm = de_ctx->sig_list->match;
if (sm->type == DETECT_URICONTENT) {
result = 1;
} else {
result = 0;
}
end:
if (de_ctx != NULL) SigCleanSignatures(de_ctx);
if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
return result;
}
/** \test Check the signature working to alert when http_cookie is matched . */
static int DetectUriSigTest02(void) {
int result = 0;
Flow f;
uint8_t httpbuf1[] = "POST /one HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\nCookie:"
" hellocatch\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
TcpSession ssn;
Packet p;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx;
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.payload = httpbuf1;
p.payload_len = httplen1;
p.proto = IPPROTO_TCP;
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
f.protoctx = (void *)&ssn;
p.flow = &f;
p.flowflags |= FLOW_PKT_TOSERVER;
ssn.alproto = ALPROTO_HTTP;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
de_ctx->mpm_matcher = MPM_B2G;
de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:"
"\" Test uricontent\"; "
"uricontent:\"foo\"; sid:1;)");
if (s == NULL) {
goto end;
}
s = s->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:"
"\" Test uricontent\"; "
"uricontent:\"one\"; sid:2;)");
if (s == NULL) {
goto end;
}
s = s->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:"
"\" Test uricontent\"; "
"uricontent:\"oisf\"; sid:3;)");
if (s == NULL) {
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
goto end;
}
HtpState *http_state = ssn.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
if (http_state == NULL) {
printf("no http state: ");
goto end;
}
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p);
if ((PacketAlertCheck(&p, 1))) {
printf("sig: 1 alerted, but it should not\n");
goto end;
} else if (!PacketAlertCheck(&p, 2)) {
printf("sig: 2 did not alerted, but it should\n");
goto end;
} else if ((PacketAlertCheck(&p, 3))) {
printf("sig: 3 alerted, but it should not\n");
goto end;
}
result = 1;
end:
if (de_ctx != NULL) SigCleanSignatures(de_ctx);
if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
return result;
}
/** \test Check the working of scan/search once per packet only in applayer
* match */
static int DetectUriSigTest03(void) {
int result = 0;
Flow f;
uint8_t httpbuf1[] = "POST /one HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\nCookie:"
" hellocatch\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
uint8_t httpbuf2[] = "POST /oneself HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\nCookie:"
" hellocatch\r\n\r\n";
uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
TcpSession ssn;
Packet p;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx;
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.payload = httpbuf1;
p.payload_len = httplen1;
p.proto = IPPROTO_TCP;
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
f.protoctx = (void *)&ssn;
p.flow = &f;
p.flowflags |= FLOW_PKT_TOSERVER;
ssn.alproto = ALPROTO_HTTP;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
de_ctx->mpm_matcher = MPM_B2G;
de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:"
"\" Test uricontent\"; "
"uricontent:\"foo\"; sid:1;)");
if (s == NULL) {
goto end;
}
s = s->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:"
"\" Test uricontent\"; "
"uricontent:\"one\"; sid:2;)");
if (s == NULL) {
goto end;
}
s = s->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:"
"\" Test uricontent\"; "
"uricontent:\"self\"; sid:3;)");
if (s == NULL) {
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
goto end;
}
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p);
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf2, httplen2);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
goto end;
}
HtpState *http_state = ssn.aldata[AlpGetStateIdx(ALPROTO_HTTP)];
if (http_state == NULL) {
printf("no http state: ");
goto end;
}
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p);
if ((PacketAlertCheck(&p, 1))) {
printf("sig: 1 alerted, but it should not\n");
goto end;
} else if (! PacketAlertCheck(&p, 2)) {
printf("sig: 2 did not alerted, but it should\n");
goto end;
} else if (! (PacketAlertCheck(&p, 3))) {
printf("sig: 3 did not alerted, but it should\n");
goto end;
}
result = 1;
end:
if (de_ctx != NULL) SigCleanSignatures(de_ctx);
if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
return result;
}
#endif /* UNITTESTS */
void HttpUriRegisterTests(void) {
#ifdef UNITTESTS
UtRegisterTest("HTTPUriTest01", HTTPUriTest01, 1);
UtRegisterTest("HTTPUriTest02", HTTPUriTest02, 1);
UtRegisterTest("HTTPUriTest03", HTTPUriTest03, 1);
UtRegisterTest("HTTPUriTest04", HTTPUriTest04, 1);
UtRegisterTest("DetectUriSigTest01", DetectUriSigTest01, 1);
UtRegisterTest("DetectUriSigTest02", DetectUriSigTest02, 1);
UtRegisterTest("DetectUriSigTest03", DetectUriSigTest03, 1);
#endif /* UNITTESTS */
}

@ -553,8 +553,11 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
FlowSetIPOnlyFlag(p->flow, p->flowflags & FLOW_PKT_TOSERVER ? 1 : 0);
}
/* we assume we don't have an uri when we start inspection */
det_ctx->de_have_httpuri = 0;
/* we assume we have an uri when we start inspection */
det_ctx->de_have_httpuri = TRUE;
/* we don't scan the uri when we start inspection */
det_ctx->de_scanned_uri = FALSE;
det_ctx->sgh = SigMatchSignaturesGetSgh(th_v, de_ctx, det_ctx, p);
/* if we didn't get a sig group head, we
@ -618,9 +621,18 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
/* filter out sigs that want pattern matches, but
* have no matches */
if (!(det_ctx->pmq.sig_bitarray[(sig / 8)] & (1<<(sig % 8))) &&
(s->flags & SIG_FLAG_MPM) && !(s->flags & SIG_FLAG_MPM_NEGCONTENT)) {
SCLogDebug("mpm sig without matches.");
continue;
(s->flags & SIG_FLAG_MPM) && !(s->flags & SIG_FLAG_MPM_NEGCONTENT)) {
/* If uri_ctx sigs are not scanned till now, we need to scan them
Once */
if (det_ctx->sgh->flags & SIG_GROUP_HAVEURICONTENT) {
if (det_ctx->de_scanned_uri == TRUE) {
SCLogDebug("mpm sig without matches.");
continue;
}
} else {
SCLogDebug("mpm sig without matches.");
continue;
}
}
//printf("idx %" PRIu32 ", det_ctx->pmq.sig_id_array_cnt %" PRIu32 ", s->id %" PRIu32 " (MPM? %s)\n", idx, det_ctx->pmq.sig_id_array_cnt, s->id, s->flags & SIG_FLAG_MPM ? "TRUE":"FALSE");
@ -697,7 +709,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
match = sigmatch_table[sm->type].Match(th_v, det_ctx, p, s, sm);
}
if (match) {
if (match > 0) {
/* okay, try the next match */
sm = sm->next;
@ -741,7 +753,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
match = sigmatch_table[sm->type].Match(th_v, det_ctx, p, s, sm);
}
if (match) {
if (match > 0) {
/* okay, try the next match */
sm = sm->next;
@ -2900,6 +2912,7 @@ void SigTableRegisterTests(void) {
#ifdef UNITTESTS
#include "flow-util.h"
#include "stream-tcp-reassemble.h"
static const char *dummy_conf_string =
"%YAML 1.1\n"
@ -3240,15 +3253,24 @@ static int SigTest06Real (int mpm_type) {
Packet p;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx;
Flow f;
TcpSession ssn;
int result = 0;
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.payload = buf;
p.payload_len = buflen;
p.proto = IPPROTO_TCP;
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
f.protoctx = (void *)&ssn;
p.flow = &f;
p.flowflags |= FLOW_PKT_TOSERVER;
ssn.alproto = ALPROTO_HTTP;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
@ -3273,6 +3295,13 @@ static int SigTest06Real (int mpm_type) {
//PatternMatchPrepare(mpm_ctx, mpm_type);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, buf, buflen);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
goto end;
}
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p);
if (PacketAlertCheck(&p, 1) && PacketAlertCheck(&p, 2))
result = 1;
@ -3384,15 +3413,24 @@ static int SigTest08Real (int mpm_type) {
Packet p;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx;
Flow f;
TcpSession ssn;
int result = 0;
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.payload = buf;
p.payload_len = buflen;
p.proto = IPPROTO_TCP;
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
f.protoctx = (void *)&ssn;
p.flow = &f;
p.flowflags |= FLOW_PKT_TOSERVER;
ssn.alproto = ALPROTO_HTTP;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
@ -3417,6 +3455,13 @@ static int SigTest08Real (int mpm_type) {
//PatternMatchPrepare(mpm_ctx, mpm_type);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, buf, buflen);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
goto end;
}
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p);
if (PacketAlertCheck(&p, 1) && PacketAlertCheck(&p, 2))
result = 1;
@ -3522,15 +3567,24 @@ static int SigTest10Real (int mpm_type) {
Packet p;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx;
Flow f;
TcpSession ssn;
int result = 0;
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.payload = buf;
p.payload_len = buflen;
p.proto = IPPROTO_TCP;
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
f.protoctx = (void *)&ssn;
p.flow = &f;
p.flowflags |= FLOW_PKT_TOSERVER;
ssn.alproto = ALPROTO_HTTP;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
@ -3555,6 +3609,13 @@ static int SigTest10Real (int mpm_type) {
//PatternMatchPrepare(mpm_ctx, mpm_type);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx,(void *)&det_ctx);
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, buf, buflen);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
goto end;
}
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p);
if (PacketAlertCheck(&p, 1) && PacketAlertCheck(&p, 2))
result = 0;
@ -3587,15 +3648,24 @@ static int SigTest11Real (int mpm_type) {
Packet p;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx;
Flow f;
TcpSession ssn;
int result = 0;
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.payload = buf;
p.payload_len = buflen;
p.proto = IPPROTO_TCP;
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
f.protoctx = (void *)&ssn;
p.flow = &f;
p.flowflags |= FLOW_PKT_TOSERVER;
ssn.alproto = ALPROTO_HTTP;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {

@ -308,6 +308,9 @@ typedef struct DetectionEngineThreadCtx_ {
/* http_uri stuff for uricontent */
char de_have_httpuri;
/* to indicate http_uri scanned or not */
char de_scanned_uri;
/** pointer to the current mpm ctx that is stored
* in a rule group head -- can be either a content
* or uricontent ctx. */

Loading…
Cancel
Save