support relative modifiers for http_client_body. Introduce body processing engine in detect-engine-hcbd.[ch]

remotes/origin/master-1.1.x
Anoop Saldanha 15 years ago committed by Victor Julien
parent 234656e5f6
commit 5c6a65dc58

@ -63,6 +63,7 @@ detect-engine-iponly.c detect-engine-iponly.h \
detect-engine-payload.c detect-engine-payload.h \ detect-engine-payload.c detect-engine-payload.h \
detect-engine-dcepayload.c detect-engine-dcepayload.h \ detect-engine-dcepayload.c detect-engine-dcepayload.h \
detect-engine-uri.c detect-engine-uri.h \ detect-engine-uri.c detect-engine-uri.h \
detect-engine-hcbd.c detect-engine-hcbd.h \
detect-engine-state.c detect-engine-state.h \ detect-engine-state.c detect-engine-state.h \
detect-parse.c detect-parse.h \ detect-parse.c detect-parse.h \
detect-ack.c detect-ack.h \ detect-ack.c detect-ack.h \

@ -25,6 +25,7 @@
* This file provides a HTTP protocol support for the engine using HTP library. * This file provides a HTTP protocol support for the engine using HTP library.
*/ */
#include "suricata.h"
#include "suricata-common.h" #include "suricata-common.h"
#include "debug.h" #include "debug.h"
#include "decode.h" #include "decode.h"
@ -70,6 +71,7 @@ struct HTPCfgRec_ {
static SCRadixTree *cfgtree; static SCRadixTree *cfgtree;
/** List of HTP configurations. */ /** List of HTP configurations. */
static HTPCfgRec cfglist; static HTPCfgRec cfglist;
static HTPCfgRec cfglist_backup;
#ifdef DEBUG #ifdef DEBUG
static SCMutex htp_state_mem_lock = PTHREAD_MUTEX_INITIALIZER; static SCMutex htp_state_mem_lock = PTHREAD_MUTEX_INITIALIZER;
@ -537,7 +539,7 @@ static int HTPHandleResponseData(Flow *f, void *htp_state,
* \param len length of the chunk pointed by data * \param len length of the chunk pointed by data
* \retval none * \retval none
*/ */
void HtpBodyAppendChunk(HtpBody *body, uint8_t *data, uint32_t len) void HtpBodyAppendChunk(SCHtpTxUserData *htud, HtpBody *body, uint8_t *data, uint32_t len)
{ {
SCEnter(); SCEnter();
@ -560,6 +562,7 @@ void HtpBodyAppendChunk(HtpBody *body, uint8_t *data, uint32_t len)
} }
memcpy(bd->data, data, len); memcpy(bd->data, data, len);
htud->content_len_so_far = len;
body->first = body->last = bd; body->first = body->last = bd;
body->nchunks++; body->nchunks++;
bd->next = NULL; bd->next = NULL;
@ -570,6 +573,11 @@ void HtpBodyAppendChunk(HtpBody *body, uint8_t *data, uint32_t len)
/* Weird, but sometimes htp lib calls the callback /* Weird, but sometimes htp lib calls the callback
* more than once for the same chunk, with more * more than once for the same chunk, with more
* len, so updating the len */ * len, so updating the len */
if (body->last->len > len)
htud->content_len_so_far -= (body->last->len - len);
else
htud->content_len_so_far += (len - body->last->len);
body->last->len = len; body->last->len = len;
bd = body->last; bd = body->last;
@ -593,6 +601,7 @@ void HtpBodyAppendChunk(HtpBody *body, uint8_t *data, uint32_t len)
} }
memcpy(bd->data, data, len); memcpy(bd->data, data, len);
htud->content_len_so_far += len;
body->last->next = bd; body->last->next = bd;
body->last = bd; body->last = bd;
body->nchunks++; body->nchunks++;
@ -696,13 +705,17 @@ int HTPCallbackRequestBodyData(htp_tx_data_t *d)
htud->body.operation = HTP_BODY_NONE; htud->body.operation = HTP_BODY_NONE;
htud->body.pcre_flags = HTP_PCRE_NONE; htud->body.pcre_flags = HTP_PCRE_NONE;
htp_header_t *cl = table_getc(d->tx->request_headers, "content-length");
if (cl != NULL)
htud->content_len = htp_parse_content_length(cl->value);
/* Set the user data for handling body chunks on this transaction */ /* Set the user data for handling body chunks on this transaction */
htp_tx_set_user_data(d->tx, htud); htp_tx_set_user_data(d->tx, htud);
} }
htud->body.operation = HTP_BODY_REQUEST; htud->body.operation = HTP_BODY_REQUEST;
HtpBodyAppendChunk(&htud->body, (uint8_t*)d->data, (uint32_t)d->len); HtpBodyAppendChunk(htud, &htud->body, (uint8_t*)d->data, (uint32_t)d->len);
htud->body.pcre_flags = HTP_PCRE_NONE; htud->body.pcre_flags = HTP_PCRE_NONE;
if (SCLogDebugEnabled()) { if (SCLogDebugEnabled()) {
HtpBodyPrint(&htud->body); HtpBodyPrint(&htud->body);
@ -1021,6 +1034,22 @@ static void HTPConfigure(void)
SCReturn; SCReturn;
} }
static void HtpConfigCreateBackup(void)
{
cfglist_backup.cfg = cfglist.cfg;
cfglist_backup.next = cfglist.next;
return;
}
static void HtpConfigRestoreBackup(void)
{
cfglist.cfg = cfglist_backup.cfg;
cfglist.next = cfglist_backup.next;
return;
}
/** /**
* \brief Register the HTTP protocol and state handling functions to APP layer * \brief Register the HTTP protocol and state handling functions to APP layer
* of the engine. * of the engine.
@ -1753,6 +1782,7 @@ libhtp:\n\
ConfCreateContextBackup(); ConfCreateContextBackup();
ConfInit(); ConfInit();
HtpConfigCreateBackup();
ConfYamlLoadString(input, strlen(input)); ConfYamlLoadString(input, strlen(input));
@ -1816,8 +1846,10 @@ libhtp:\n\
ret = 1; ret = 1;
end: end:
HTPFreeConfig();
ConfDeInit(); ConfDeInit();
ConfRestoreContextBackup(); ConfRestoreContextBackup();
HtpConfigRestoreBackup();
return ret; return ret;
} }
@ -1858,6 +1890,7 @@ libhtp:\n\
ConfCreateContextBackup(); ConfCreateContextBackup();
ConfInit(); ConfInit();
HtpConfigCreateBackup();
ConfYamlLoadString(input, strlen(input)); ConfYamlLoadString(input, strlen(input));
@ -1922,8 +1955,10 @@ libhtp:\n\
} }
end: end:
HTPFreeConfig();
ConfDeInit(); ConfDeInit();
ConfRestoreContextBackup(); ConfRestoreContextBackup();
HtpConfigRestoreBackup();
FlowL7DataPtrFree(&f); FlowL7DataPtrFree(&f);
StreamTcpFreeConfig(TRUE); StreamTcpFreeConfig(TRUE);

@ -85,7 +85,12 @@ typedef struct HtpBody_ {
/** Now the Body Chunks will be stored per transaction, at /** Now the Body Chunks will be stored per transaction, at
* the tx user data */ * the tx user data */
typedef struct SCHtpTxUserData_ { typedef struct SCHtpTxUserData_ {
HtpBody body; /**< Body of the request (if any) */ /* Body of the request (if any) */
HtpBody body;
/* Holds the length of the htp request body */
uint32_t content_len;
/* Holds the length of the htp request body seen so far */
uint32_t content_len_so_far;
} SCHtpTxUserData; } SCHtpTxUserData;
typedef struct HtpState_ { typedef struct HtpState_ {

@ -83,12 +83,13 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths
break; break;
default: default:
pm = SigMatchGetLastSMFromLists(s, 4, pm = SigMatchGetLastSMFromLists(s, 6,
DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH],
DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH]); DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH],
DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH]);
if (pm == NULL) { if (pm == NULL) {
SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "depth needs " SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "depth needs "
"preceeding content or uricontent option"); "preceeding content or uricontent option or http_client_body option");
if (dubbed) if (dubbed)
SCFree(str); SCFree(str);
return -1; return -1;
@ -167,6 +168,20 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depths
break; break;
case DETECT_AL_HTTP_CLIENT_BODY:
cd = (DetectContentData *)pm->ctx;
cd->depth = (uint32_t)atoi(str);
if (cd->depth < cd->content_len) {
cd->depth = cd->content_len;
SCLogDebug("depth increased to %"PRIu32" to match pattern len ",
cd->depth);
}
/* Now update the real limit, as depth is relative to the offset */
cd->depth += cd->offset;
cd->flags |= DETECT_CONTENT_DEPTH;
break;
default: default:
SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "depth needs a preceeding " SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "depth needs a preceeding "
"content (or uricontent) option"); "content (or uricontent) option");

@ -163,12 +163,14 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s,
} }
} }
} else { } else {
pm = SigMatchGetLastSMFromLists(s, 4, pm = SigMatchGetLastSMFromLists(s, 6,
DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH],
DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH]); DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH],
DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH]);
if (pm == NULL) { if (pm == NULL) {
SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs" SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs"
"preceeding content or uricontent option"); "preceeding content or uricontent option or http_client_body options");
if (dubbed) if (dubbed)
SCFree(str); SCFree(str);
return -1; return -1;
@ -361,6 +363,29 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s,
break; break;
case DETECT_AL_HTTP_CLIENT_BODY:
cd = (DetectContentData *)pm->ctx;
cd->distance = strtol(str, NULL, 10);
if (cd->flags & DETECT_CONTENT_WITHIN) {
if ((cd->distance + cd->content_len) > cd->within) {
cd->within = cd->distance + cd->content_len;
}
}
cd->flags |= DETECT_CONTENT_DISTANCE;
pm = SigMatchGetLastSMFromLists(s, 2,
DETECT_AL_HTTP_CLIENT_BODY, pm->prev);
if (pm == NULL) {
SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for http_client_body "
"needs preceeding http_client_body content");
goto error;
}
((DetectContentData *)pm->ctx)->flags |= DETECT_CONTENT_RELATIVE_NEXT;
break;
default: default:
SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance needs two " SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance needs two "
"preceeding content or uricontent options"); "preceeding content or uricontent options");

File diff suppressed because it is too large Load Diff

@ -0,0 +1,31 @@
/* 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>
*/
#ifndef __DETECT_ENGINE_HCBD_H__
#define __DETECT_ENGINE_HCBD_H__
int DetectEngineInspectHttpClientBody(DetectEngineCtx *, DetectEngineThreadCtx *,
Signature *, Flow *, uint8_t, void *);
void HttpClientBodyRegisterTests(void);
#endif /* __DETECT_ENGINE_HCBD_H__ */

@ -31,6 +31,7 @@
#include "detect-engine-state.h" #include "detect-engine-state.h"
#include "detect-engine-uri.h" #include "detect-engine-uri.h"
#include "detect-engine-hcbd.h"
#include "detect-engine-dcepayload.h" #include "detect-engine-dcepayload.h"
#include "stream-tcp.h" #include "stream-tcp.h"
@ -194,15 +195,16 @@ int DeStateUpdateInspectTransactionId(Flow *f, char direction) {
} }
/** /**
* \brief Append a signature to the detect engine state * \brief Append a signature to the detect engine state
* *
* \param state the detect engine state * \param state the detect engine state
* \param s signature * \param s signature
* \param sm sigmatch * \param sm sigmatch
* \param uri did uri already match (if any) * \param uri did uri already match (if any)
* \param dce did dce already match (if any) * \param dce did dce already match (if any)
* \param hcbd did http client body already match (if any)
*/ */
static void DeStateSignatureAppend(DetectEngineState *state, Signature *s, SigMatch *sm, char uri, char dce) { static void DeStateSignatureAppend(DetectEngineState *state, Signature *s, SigMatch *sm, char uri, char dce, char hcbd) {
DeStateStore *store = state->tail; DeStateStore *store = state->tail;
if (store == NULL) { if (store == NULL) {
@ -236,12 +238,17 @@ static void DeStateSignatureAppend(DetectEngineState *state, Signature *s, SigMa
if (dce) { if (dce) {
store->store[idx].flags |= DE_STATE_FLAG_DCE_MATCH; store->store[idx].flags |= DE_STATE_FLAG_DCE_MATCH;
} }
if (hcbd) {
store->store[idx].flags |= DE_STATE_FLAG_HCBD_MATCH;
}
store->store[idx].nm = sm; store->store[idx].nm = sm;
state->cnt++; state->cnt++;
SCLogDebug("store %p idx %"PRIuMAX" cnt %"PRIuMAX" sig id %"PRIuMAX"", SCLogDebug("store %p idx %"PRIuMAX" cnt %"PRIuMAX" sig id %"PRIuMAX"",
store, (uintmax_t)idx, (uintmax_t)state->cnt, store, (uintmax_t)idx, (uintmax_t)state->cnt,
(uintmax_t)store->store[idx].sid); (uintmax_t)store->store[idx].sid);
return;
} }
@ -293,6 +300,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx,
int r = 0; int r = 0;
char umatch = 0; char umatch = 0;
char uinspect = 0; char uinspect = 0;
char hcbdmatch = 0;
char hcbdinspect = 0;
char dmatch = 0; char dmatch = 0;
char dinspect = 0; char dinspect = 0;
char appinspect = 0; char appinspect = 0;
@ -320,6 +329,14 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx,
SCLogDebug("uri inspected but no match"); SCLogDebug("uri inspected but no match");
} }
} }
if (s->sm_lists[DETECT_SM_LIST_HCBDMATCH] != NULL) {
hcbdinspect = 1;
if (DetectEngineInspectHttpClientBody(de_ctx, det_ctx, s, f,
flags, alstate) == 1) {
hcbdmatch = 1;
}
SCLogDebug("inspecting http client body");
}
} else if (alproto == ALPROTO_DCERPC || alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) { } else if (alproto == ALPROTO_DCERPC || alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) {
if (s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL) { if (s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL) {
dinspect = 1; dinspect = 1;
@ -350,8 +367,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx,
} }
} }
appinspect = uinspect + dinspect; appinspect = uinspect + dinspect + hcbdinspect;
appmatch = umatch + dmatch; appmatch = umatch + dmatch + hcbdmatch;
if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) { if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) {
for ( ; sm != NULL; sm = sm->next) { for ( ; sm != NULL; sm = sm->next) {
@ -393,8 +410,8 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx,
} }
} }
SCLogDebug("detection done, store results: sm %p, uri %d, dce %d", SCLogDebug("detection done, store results: sm %p, uri %d, dce %d", hcbd %d,
sm, umatch, dmatch); sm, umatch, dmatch, hcbdmatch);
SCMutexLock(&f->de_state_m); SCMutexLock(&f->de_state_m);
/* match or no match, we store the state anyway /* match or no match, we store the state anyway
@ -404,7 +421,7 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx,
f->de_state = DetectEngineStateAlloc(); f->de_state = DetectEngineStateAlloc();
} }
if (f->de_state != NULL) { if (f->de_state != NULL) {
DeStateSignatureAppend(f->de_state, s, sm, umatch, dmatch); DeStateSignatureAppend(f->de_state, s, sm, umatch, dmatch, hcbdmatch);
} }
SCMutexUnlock(&f->de_state_m); SCMutexUnlock(&f->de_state_m);
@ -426,6 +443,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete
int match = 0; int match = 0;
char umatch = 0; char umatch = 0;
char uinspect = 0; char uinspect = 0;
char hcbdmatch = 0;
char hcbdinspect = 0;
char dmatch = 0; char dmatch = 0;
char dinspect = 0; char dinspect = 0;
char appinspect = 0; char appinspect = 0;
@ -452,6 +471,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete
umatch = 0; umatch = 0;
uinspect = 0; uinspect = 0;
hcbdmatch = 0;
hcbdinspect = 0;
dmatch = 0; dmatch = 0;
dinspect = 0; dinspect = 0;
appinspect = 0; appinspect = 0;
@ -495,6 +516,19 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete
SCLogDebug("uri already inspected"); SCLogDebug("uri already inspected");
} }
} }
if (s->sm_lists[DETECT_SM_LIST_HCBDMATCH] != NULL) {
if (!(item->flags & DE_STATE_FLAG_HCBD_MATCH)) {
SCLogDebug("inspecting http client body data");
hcbdinspect = 1;
if (DetectEngineInspectHttpClientBody(de_ctx, det_ctx, s, f,
flags, alstate) == 1) {
SCLogDebug("uri matched");
item->flags |= DE_STATE_FLAG_HCBD_MATCH;
hcbdmatch = 1;
}
}
}
} else if (alproto == ALPROTO_DCERPC || alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) { } else if (alproto == ALPROTO_DCERPC || alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) {
if (s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL) { if (s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL) {
if (!(item->flags & DE_STATE_FLAG_DCE_MATCH)) { if (!(item->flags & DE_STATE_FLAG_DCE_MATCH)) {
@ -532,8 +566,8 @@ int DeStateDetectContinueDetection(ThreadVars *tv, DetectEngineCtx *de_ctx, Dete
} }
appinspect = uinspect + dinspect; appinspect = uinspect + dinspect + hcbdinspect;
appmatch = umatch + dmatch; appmatch = umatch + dmatch + hcbdmatch;
SCLogDebug("appinspect %d, appmatch %d", appinspect, appmatch); SCLogDebug("appinspect %d, appmatch %d", appinspect, appmatch);
/* next, check the other sig matches */ /* next, check the other sig matches */
@ -673,39 +707,39 @@ static int DeStateTest02(void) {
memset(&s, 0x00, sizeof(s)); memset(&s, 0x00, sizeof(s));
s.num = 0; s.num = 0;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 11; s.num = 11;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 22; s.num = 22;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 33; s.num = 33;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 44; s.num = 44;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 55; s.num = 55;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 66; s.num = 66;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 77; s.num = 77;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 88; s.num = 88;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 99; s.num = 99;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 100; s.num = 100;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 111; s.num = 111;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 122; s.num = 122;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 133; s.num = 133;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 144; s.num = 144;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 155; s.num = 155;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 166; s.num = 166;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
if (state->head == NULL) { if (state->head == NULL) {
goto end; goto end;
@ -748,9 +782,9 @@ static int DeStateTest03(void) {
memset(&s, 0x00, sizeof(s)); memset(&s, 0x00, sizeof(s));
s.num = 11; s.num = 11;
DeStateSignatureAppend(state, &s, NULL, 0, 0); DeStateSignatureAppend(state, &s, NULL, 0, 0, 0);
s.num = 22; s.num = 22;
DeStateSignatureAppend(state, &s, NULL, 1, 0); DeStateSignatureAppend(state, &s, NULL, 1, 0, 0);
if (state->head == NULL) { if (state->head == NULL) {
goto end; goto end;

@ -47,7 +47,8 @@
#define DE_STATE_FLAG_PAYLOAD_MATCH 0x01 /**< payload part of the sig matched */ #define DE_STATE_FLAG_PAYLOAD_MATCH 0x01 /**< payload part of the sig matched */
#define DE_STATE_FLAG_URI_MATCH 0x02 /**< uri part of the sig matched */ #define DE_STATE_FLAG_URI_MATCH 0x02 /**< uri part of the sig matched */
#define DE_STATE_FLAG_DCE_MATCH 0x04 /**< dce payload inspection part matched */ #define DE_STATE_FLAG_DCE_MATCH 0x04 /**< dce payload inspection part matched */
#define DE_STATE_FLAG_FULL_MATCH 0x08 /**< sig already fully matched */ #define DE_STATE_FLAG_HCBD_MATCH 0x08 /**< hcbd payload inspection part matched */
#define DE_STATE_FLAG_FULL_MATCH 0x10 /**< sig already fully matched */
/** per signature detection engine state */ /** per signature detection engine state */
typedef enum { typedef enum {

@ -64,11 +64,11 @@ void DetectHttpClientBodyRegister(void)
{ {
sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].name = "http_client_body"; sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].name = "http_client_body";
sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].Match = NULL; sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].Match = NULL;
sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].AppLayerMatch = DetectHttpClientBodyMatch; sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].AppLayerMatch = NULL;
sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].alproto = ALPROTO_HTTP;
sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].Setup = DetectHttpClientBodySetup; sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].Setup = DetectHttpClientBodySetup;
sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].Free = DetectHttpClientBodyFree; sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].Free = DetectHttpClientBodyFree;
sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].RegisterTests = DetectHttpClientBodyRegisterTests; sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].RegisterTests = DetectHttpClientBodyRegisterTests;
sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].alproto = ALPROTO_HTTP;
sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].flags |= SIGMATCH_PAYLOAD ; sigmatch_table[DETECT_AL_HTTP_CLIENT_BODY].flags |= SIGMATCH_PAYLOAD ;
} }
@ -235,39 +235,34 @@ int DetectHttpClientBodySetup(DetectEngineCtx *de_ctx, Signature *s, char *arg)
goto error; goto error;
} }
/* setup the HttpClientBodyData's data from content data structure's data */ DetectContentData *cd = (DetectContentData *)sm->ctx;
hcbd = SCMalloc(sizeof(DetectContentData)); if (cd->flags & DETECT_CONTENT_WITHIN || cd->flags & DETECT_CONTENT_DISTANCE) {
if (hcbd == NULL) SigMatch *pm = SigMatchGetLastSMFromLists(s, 2,
goto error; DETECT_CONTENT, sm->prev);
memset(hcbd, 0, sizeof(DetectContentData)); /* pm is never NULL. So no NULL check */
DetectContentData *tmp_cd = (DetectContentData *)pm->ctx;
/* transfer the pattern details from the content struct to the clientbody struct */ tmp_cd->flags &= ~DETECT_CONTENT_RELATIVE_NEXT;
hcbd->content = ((DetectContentData *)sm->ctx)->content;
hcbd->content_len = ((DetectContentData *)sm->ctx)->content_len; pm = SigMatchGetLastSMFromLists(s, 2,
hcbd->flags |= (((DetectContentData *)sm->ctx)->flags & DETECT_CONTENT_NOCASE) ? DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH]);
DETECT_CONTENT_NOCASE : 0; if (pm == NULL) {
hcbd->flags |= (((DetectContentData *)sm->ctx)->flags & DETECT_CONTENT_NEGATED) ? SCLogError(SC_ERR_INVALID_SIGNATURE, "http_client_body seen with a "
DETECT_CONTENT_NEGATED : 0; "distance or within without a previous http_client_body "
//hcbd->id = ((DetectContentData *)sm->ctx)->id; "content. Invalidating signature.");
hcbd->id = DetectPatternGetId(de_ctx->mpm_pattern_id_store, hcbd, DETECT_AL_HTTP_CLIENT_BODY); goto error;
hcbd->bm_ctx = ((DetectContentData *)sm->ctx)->bm_ctx; }
tmp_cd = (DetectContentData *)pm->ctx;
nm = SigMatchAlloc(); tmp_cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
if (nm == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
goto error;
} }
nm->type = DETECT_AL_HTTP_CLIENT_BODY; cd->id = DetectPatternGetId(de_ctx->mpm_pattern_id_store, cd, DETECT_AL_HTTP_CLIENT_BODY);
nm->ctx = (void *)hcbd; sm->type = DETECT_AL_HTTP_CLIENT_BODY;
/* pull the previous content from the pmatch list, append /* transfer the sm from the pmatch list to hcbdmatch list */
* the new match to the match list */ SigMatchTransferSigMatchAcrossLists(sm,
SigMatchReplaceContent(s, sm, nm); &s->sm_lists[DETECT_SM_LIST_PMATCH],
&s->sm_lists_tail[DETECT_SM_LIST_PMATCH],
/* free the old content sigmatch, the content pattern memory &s->sm_lists[DETECT_SM_LIST_HCBDMATCH],
* is taken over by the new sigmatch */ &s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH]);
SCFree(sm->ctx);
SCFree(sm);
/* flag the signature to indicate that we scan the app layer data */ /* flag the signature to indicate that we scan the app layer data */
s->flags |= SIG_FLAG_APPLAYER; s->flags |= SIG_FLAG_APPLAYER;
@ -484,7 +479,7 @@ static int DetectHttpClientBodyTest06(void)
"Content-Type: text/html\r\n" "Content-Type: text/html\r\n"
"Content-Length: 26\r\n" "Content-Length: 26\r\n"
"\r\n" "\r\n"
"This is dummy message body\r\n"; "This is dummy message body";
uint32_t http_len = sizeof(http_buf) - 1; uint32_t http_len = sizeof(http_buf) - 1;
int result = 0; int result = 0;
@ -581,11 +576,11 @@ static int DetectHttpClientBodyTest07(void)
"Host: www.openinfosecfoundation.org\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" "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-Type: text/html\r\n"
"Content-Length: 67\r\n" "Content-Length: 54\r\n"
"\r\n" "\r\n"
"This is dummy message body1"; "This is dummy message body1";
uint8_t http2_buf[] = uint8_t http2_buf[] =
"This is dummy message body2\r\n"; "This is dummy message body2";
uint32_t http1_len = sizeof(http1_buf) - 1; uint32_t http1_len = sizeof(http1_buf) - 1;
uint32_t http2_len = sizeof(http2_buf) - 1; uint32_t http2_len = sizeof(http2_buf) - 1;
int result = 0; int result = 0;
@ -647,8 +642,8 @@ static int DetectHttpClientBodyTest07(void)
/* do detect */ /* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
if (!(PacketAlertCheck(p1, 1))) { if (PacketAlertCheck(p1, 1)) {
printf("sid 1 didn't match on p1 but should have: "); printf("sid 1 matched on p1 but shouldn't have: ");
goto end; goto end;
} }
@ -660,13 +655,11 @@ static int DetectHttpClientBodyTest07(void)
/* do detect */ /* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p2); SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
/* VJ right now we won't inspect the body another time if it
already matched once. Later we will take care of that.
if (!(PacketAlertCheck(p2, 1))) { if (!(PacketAlertCheck(p2, 1))) {
printf("sid 1 didn't match on p2 but should have: "); printf("sid 1 didn't match on p2 but should have: ");
goto end; goto end;
} }
*/
result = 1; result = 1;
end: end:
if (de_ctx != NULL) if (de_ctx != NULL)
@ -703,11 +696,11 @@ static int DetectHttpClientBodyTest08(void)
"Host: www.openinfosecfoundation.org\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" "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-Type: text/html\r\n"
"Content-Length: 67\r\n" "Content-Length: 46\r\n"
"\r\n" "\r\n"
"This is dummy body1"; "This is dummy body1";
uint8_t http2_buf[] = uint8_t http2_buf[] =
"This is dummy message body2\r\n"; "This is dummy message body2";
uint32_t http1_len = sizeof(http1_buf) - 1; uint32_t http1_len = sizeof(http1_buf) - 1;
uint32_t http2_len = sizeof(http2_buf) - 1; uint32_t http2_len = sizeof(http2_buf) - 1;
int result = 0; int result = 0;
@ -827,11 +820,11 @@ static int DetectHttpClientBodyTest09(void)
"Host: www.openinfosecfoundation.org\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" "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-Type: text/html\r\n"
"Content-Length: 67\r\n" "Content-Length: 46\r\n"
"\r\n" "\r\n"
"This is dummy body1"; "This is dummy body1";
uint8_t http2_buf[] = uint8_t http2_buf[] =
"This is dummy message body2\r\n"; "This is dummy message body2";
uint32_t http1_len = sizeof(http1_buf) - 1; uint32_t http1_len = sizeof(http1_buf) - 1;
uint32_t http2_len = sizeof(http2_buf) - 1; uint32_t http2_len = sizeof(http2_buf) - 1;
int result = 0; int result = 0;
@ -951,11 +944,11 @@ static int DetectHttpClientBodyTest10(void)
"Host: www.openinfosecfoundation.org\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" "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-Type: text/html\r\n"
"Content-Length: 67\r\n" "Content-Length: 46\r\n"
"\r\n" "\r\n"
"This is dummy bodY1"; "This is dummy bodY1";
uint8_t http2_buf[] = uint8_t http2_buf[] =
"This is dummy message body2\r\n"; "This is dummy message body2";
uint32_t http1_len = sizeof(http1_buf) - 1; uint32_t http1_len = sizeof(http1_buf) - 1;
uint32_t http2_len = sizeof(http2_buf) - 1; uint32_t http2_len = sizeof(http2_buf) - 1;
int result = 0; int result = 0;
@ -1075,7 +1068,7 @@ static int DetectHttpClientBodyTest11(void)
"Content-Type: text/html\r\n" "Content-Type: text/html\r\n"
"Content-Length: 26\r\n" "Content-Length: 26\r\n"
"\r\n" "\r\n"
"This is dummy message body\r\n"; "This is dummy message body";
uint32_t http_len = sizeof(http_buf) - 1; uint32_t http_len = sizeof(http_buf) - 1;
int result = 0; int result = 0;
@ -1173,7 +1166,7 @@ static int DetectHttpClientBodyTest12(void)
"Content-Type: text/html\r\n" "Content-Type: text/html\r\n"
"Content-Length: 26\r\n" "Content-Length: 26\r\n"
"\r\n" "\r\n"
"This is dummy message body\r\n"; "This is dummy message body";
uint32_t http_len = sizeof(http_buf) - 1; uint32_t http_len = sizeof(http_buf) - 1;
int result = 0; int result = 0;
@ -1269,9 +1262,9 @@ static int DetectHttpClientBodyTest13(void)
"Host: www.openinfosecfoundation.org\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" "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-Type: text/html\r\n"
"Content-Length: 100\r\n" "Content-Length: 55\r\n"
"\r\n" "\r\n"
"longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend\r\n"; "longbufferabcdefghijklmnopqrstuvwxyz0123456789bufferend";
uint32_t http_len = sizeof(http_buf) - 1; uint32_t http_len = sizeof(http_buf) - 1;
int result = 0; int result = 0;
@ -1793,13 +1786,13 @@ int DetectHttpClientBodyTest16(void)
goto end; goto end;
} }
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL) { if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCBDMATCH] == NULL) {
printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL\n"); printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCBDMATCH] == NULL\n");
goto end; goto end;
} }
DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
DetectContentData *hcbd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; DetectContentData *hcbd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH]->ctx;
if (cd->id == hcbd->id) if (cd->id == hcbd->id)
goto end; goto end;
@ -1832,13 +1825,13 @@ int DetectHttpClientBodyTest17(void)
goto end; goto end;
} }
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL) { if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCBDMATCH] == NULL) {
printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL\n"); printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCBDMATCH] == NULL\n");
goto end; goto end;
} }
DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
DetectContentData *hcbd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; DetectContentData *hcbd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH]->ctx;
if (cd->id == hcbd->id) if (cd->id == hcbd->id)
goto end; goto end;
@ -1871,13 +1864,13 @@ int DetectHttpClientBodyTest18(void)
goto end; goto end;
} }
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL) { if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCBDMATCH] == NULL) {
printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL\n"); printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCBDMATCH] == NULL\n");
goto end; goto end;
} }
DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
DetectContentData *hcbd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; DetectContentData *hcbd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH]->ctx;
if (cd->id != 0 || hcbd->id != 1) if (cd->id != 0 || hcbd->id != 1)
goto end; goto end;
@ -1910,13 +1903,13 @@ int DetectHttpClientBodyTest19(void)
goto end; goto end;
} }
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL) { if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCBDMATCH] == NULL) {
printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL\n"); printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCBDMATCH] == NULL\n");
goto end; goto end;
} }
DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
DetectContentData *hcbd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; DetectContentData *hcbd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH]->ctx;
if (cd->id != 1 || hcbd->id != 0) if (cd->id != 1 || hcbd->id != 0)
goto end; goto end;
@ -1950,14 +1943,14 @@ int DetectHttpClientBodyTest20(void)
goto end; goto end;
} }
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL) { if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCBDMATCH] == NULL) {
printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL\n"); printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCBDMATCH] == NULL\n");
goto end; goto end;
} }
DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
DetectContentData *hcbd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; DetectContentData *hcbd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH]->ctx;
DetectContentData *hcbd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->prev->ctx; DetectContentData *hcbd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH]->prev->ctx;
if (cd->id != 1 || hcbd1->id != 0 || hcbd2->id != 0) if (cd->id != 1 || hcbd1->id != 0 || hcbd2->id != 0)
goto end; goto end;
@ -1991,14 +1984,14 @@ int DetectHttpClientBodyTest21(void)
goto end; goto end;
} }
if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL) { if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCBDMATCH] == NULL) {
printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_AMATCH] == NULL\n"); printf("de_ctx->sig_list->sm_lists[DETECT_SM_LIST_HCBDMATCH] == NULL\n");
goto end; goto end;
} }
DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx; DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
DetectContentData *hcbd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->ctx; DetectContentData *hcbd1 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH]->ctx;
DetectContentData *hcbd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_AMATCH]->prev->ctx; DetectContentData *hcbd2 = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH]->prev->ctx;
if (cd->id != 2 || hcbd1->id != 0 || hcbd2->id != 0) if (cd->id != 2 || hcbd1->id != 0 || hcbd2->id != 0)
goto end; goto end;

@ -65,101 +65,101 @@ void DetectNocaseRegister (void) {
* \retval sm sigmatch of either content or uricontent that is the last * \retval sm sigmatch of either content or uricontent that is the last
* or NULL if none was found * or NULL if none was found
*/ */
static SigMatch *SigMatchGetLastNocasePattern(Signature *s) { //static SigMatch *SigMatchGetLastNocasePattern(Signature *s) {
SCEnter(); // SCEnter();
//
BUG_ON(s == NULL); // BUG_ON(s == NULL);
//
SigMatch *co_sm = DetectContentGetLastPattern(s->sm_lists_tail[DETECT_SM_LIST_PMATCH]); // SigMatch *co_sm = DetectContentGetLastPattern(s->sm_lists_tail[DETECT_SM_LIST_PMATCH]);
SigMatch *ur_sm = SigMatchGetLastSM(s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_URICONTENT); // SigMatch *ur_sm = SigMatchGetLastSM(s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_URICONTENT);
/* http client body SigMatch */ // /* http client body SigMatch */
SigMatch *hcbd_sm = SigMatchGetLastSM(s->sm_lists_tail[DETECT_SM_LIST_AMATCH], DETECT_AL_HTTP_CLIENT_BODY); // SigMatch *hcbd_sm = SigMatchGetLastSM(s->sm_lists_tail[DETECT_SM_LIST_AMATCH], DETECT_AL_HTTP_CLIENT_BODY);
/* http cookie SigMatch */ // /* http cookie SigMatch */
SigMatch *hcd_sm = SigMatchGetLastSM(s->sm_lists_tail[DETECT_SM_LIST_AMATCH], DETECT_AL_HTTP_COOKIE); // SigMatch *hcd_sm = SigMatchGetLastSM(s->sm_lists_tail[DETECT_SM_LIST_AMATCH], DETECT_AL_HTTP_COOKIE);
/* http header SigMatch */ // /* http header SigMatch */
SigMatch *hhd_sm = SigMatchGetLastSM(s->sm_lists_tail[DETECT_SM_LIST_AMATCH], DETECT_AL_HTTP_HEADER); // SigMatch *hhd_sm = SigMatchGetLastSM(s->sm_lists_tail[DETECT_SM_LIST_AMATCH], DETECT_AL_HTTP_HEADER);
/* http method SigMatch */ // /* http method SigMatch */
SigMatch *hmd_sm = SigMatchGetLastSM(s->sm_lists_tail[DETECT_SM_LIST_AMATCH], DETECT_AL_HTTP_METHOD); // SigMatch *hmd_sm = SigMatchGetLastSM(s->sm_lists_tail[DETECT_SM_LIST_AMATCH], DETECT_AL_HTTP_METHOD);
//
SigMatch *temp_sm = NULL; // SigMatch *temp_sm = NULL;
//
SigMatch **sm_list = NULL; // SigMatch **sm_list = NULL;
uint8_t sm_list_count = 0; // uint8_t sm_list_count = 0;
//
if (co_sm != NULL) { // if (co_sm != NULL) {
sm_list_count++; // sm_list_count++;
if ( (sm_list = SCRealloc(sm_list, sizeof(SigMatch *) * sm_list_count)) == NULL) { // if ( (sm_list = SCRealloc(sm_list, sizeof(SigMatch *) * sm_list_count)) == NULL) {
SCLogError(SC_ERR_FATAL, "Fatal error encountered in SigMatchGetLastNocasePattern. Exiting..."); // SCLogError(SC_ERR_FATAL, "Fatal error encountered in SigMatchGetLastNocasePattern. Exiting...");
exit(EXIT_FAILURE); // exit(EXIT_FAILURE);
} // }
sm_list[sm_list_count - 1] = co_sm; // sm_list[sm_list_count - 1] = co_sm;
} // }
if (ur_sm != NULL) { // if (ur_sm != NULL) {
sm_list_count++; // sm_list_count++;
if ( (sm_list = SCRealloc(sm_list, sizeof(SigMatch *) * sm_list_count)) == NULL) { // if ( (sm_list = SCRealloc(sm_list, sizeof(SigMatch *) * sm_list_count)) == NULL) {
SCLogError(SC_ERR_FATAL, "Fatal error encountered in SigMatchGetLastNocasePattern. Exiting..."); // SCLogError(SC_ERR_FATAL, "Fatal error encountered in SigMatchGetLastNocasePattern. Exiting...");
exit(EXIT_FAILURE); // exit(EXIT_FAILURE);
} // }
sm_list[sm_list_count - 1] = ur_sm; // sm_list[sm_list_count - 1] = ur_sm;
} // }
if (hcbd_sm != NULL) { // if (hcbd_sm != NULL) {
sm_list_count++; // sm_list_count++;
if ( (sm_list = SCRealloc(sm_list, sizeof(SigMatch *) * sm_list_count)) == NULL) { // if ( (sm_list = SCRealloc(sm_list, sizeof(SigMatch *) * sm_list_count)) == NULL) {
SCLogError(SC_ERR_FATAL, "Fatal error encountered in SigMatchGetLastNocasePattern. Exiting..."); // SCLogError(SC_ERR_FATAL, "Fatal error encountered in SigMatchGetLastNocasePattern. Exiting...");
exit(EXIT_FAILURE); // exit(EXIT_FAILURE);
} // }
sm_list[sm_list_count - 1] = hcbd_sm; // sm_list[sm_list_count - 1] = hcbd_sm;
} // }
if (hcd_sm != NULL) { // if (hcd_sm != NULL) {
sm_list_count++; // sm_list_count++;
if ( (sm_list = SCRealloc(sm_list, sizeof(SigMatch *) * sm_list_count)) == NULL) { // if ( (sm_list = SCRealloc(sm_list, sizeof(SigMatch *) * sm_list_count)) == NULL) {
SCLogError(SC_ERR_FATAL, "Fatal error encountered in SigMatchGetLastNocasePattern. Exiting..."); // SCLogError(SC_ERR_FATAL, "Fatal error encountered in SigMatchGetLastNocasePattern. Exiting...");
exit(EXIT_FAILURE); // exit(EXIT_FAILURE);
} // }
sm_list[sm_list_count - 1] = hcd_sm; // sm_list[sm_list_count - 1] = hcd_sm;
} // }
if (hhd_sm != NULL) { // if (hhd_sm != NULL) {
sm_list_count++; // sm_list_count++;
if ( (sm_list = SCRealloc(sm_list, sizeof(SigMatch *) * sm_list_count)) == NULL) { // if ( (sm_list = SCRealloc(sm_list, sizeof(SigMatch *) * sm_list_count)) == NULL) {
SCLogError(SC_ERR_FATAL, "Fatal error encountered in SigMatchGetLastNocasePattern. Exiting..."); // SCLogError(SC_ERR_FATAL, "Fatal error encountered in SigMatchGetLastNocasePattern. Exiting...");
exit(EXIT_FAILURE); // exit(EXIT_FAILURE);
} // }
sm_list[sm_list_count - 1] = hhd_sm; // sm_list[sm_list_count - 1] = hhd_sm;
} // }
//
if (hmd_sm != NULL) { // if (hmd_sm != NULL) {
sm_list_count++; // sm_list_count++;
if ( (sm_list = SCRealloc(sm_list, sizeof(SigMatch *) * sm_list_count)) == NULL) { // if ( (sm_list = SCRealloc(sm_list, sizeof(SigMatch *) * sm_list_count)) == NULL) {
SCLogError(SC_ERR_FATAL, "Fatal error encountered in SigMatchGetLastNocasePattern. Exiting..."); // SCLogError(SC_ERR_FATAL, "Fatal error encountered in SigMatchGetLastNocasePattern. Exiting...");
exit(EXIT_FAILURE); // exit(EXIT_FAILURE);
} // }
sm_list[sm_list_count - 1] = hmd_sm; // sm_list[sm_list_count - 1] = hmd_sm;
} // }
//
if (sm_list_count == 0) // if (sm_list_count == 0)
SCReturnPtr(NULL, "SigMatch"); // SCReturnPtr(NULL, "SigMatch");
//
/* find the highest idx sm, so we apply to the last sm that we support */ // /* find the highest idx sm, so we apply to the last sm that we support */
int i = 0, j = 0; // int i = 0, j = 0;
int swapped = 1; // int swapped = 1;
while (swapped) { // while (swapped) {
swapped = 0; // swapped = 0;
for (j = i; j < sm_list_count - 1; j++) { // for (j = i; j < sm_list_count - 1; j++) {
if (sm_list[j]->idx < sm_list[j + 1]->idx) { // if (sm_list[j]->idx < sm_list[j + 1]->idx) {
temp_sm = sm_list[j]; // temp_sm = sm_list[j];
sm_list[j] = sm_list[j + 1]; // sm_list[j] = sm_list[j + 1];
sm_list[j + 1] = temp_sm; // sm_list[j + 1] = temp_sm;
swapped = 1; // swapped = 1;
i++; // i++;
} // }
} // }
} // }
//
temp_sm = sm_list[0]; // temp_sm = sm_list[0];
SCFree(sm_list); // SCFree(sm_list);
//
SCReturnPtr(temp_sm, "SigMatch"); // SCReturnPtr(temp_sm, "SigMatch");
} //}
/** /**
* \internal * \internal
@ -180,7 +180,14 @@ static int DetectNocaseSetup (DetectEngineCtx *de_ctx, Signature *s, char *nulls
} }
/* Search for the first previous SigMatch that supports nocase */ /* Search for the first previous SigMatch that supports nocase */
SigMatch *pm = SigMatchGetLastNocasePattern(s); //SigMatch *pm = SigMatchGetLastNocasePattern(s);
SigMatch *pm = SigMatchGetLastSMFromLists(s, 12,
DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH],
DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH],
DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH],
DETECT_AL_HTTP_COOKIE, s->sm_lists_tail[DETECT_SM_LIST_AMATCH],
DETECT_AL_HTTP_HEADER, s->sm_lists_tail[DETECT_SM_LIST_AMATCH],
DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_AMATCH]);
if (pm == NULL) { if (pm == NULL) {
SCLogError(SC_ERR_NOCASE_MISSING_PATTERN, "\"nocase\" needs a preceeding" SCLogError(SC_ERR_NOCASE_MISSING_PATTERN, "\"nocase\" needs a preceeding"
" content, uricontent, http_client_body, http_header, http_method, http_uri, http_cookie option"); " content, uricontent, http_client_body, http_header, http_method, http_uri, http_cookie option");
@ -244,4 +251,3 @@ static int DetectNocaseSetup (DetectEngineCtx *de_ctx, Signature *s, char *nulls
SCReturnInt(0); SCReturnInt(0);
} }

@ -80,12 +80,13 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr)
break; break;
default: default:
pm = SigMatchGetLastSMFromLists(s, 4, pm = SigMatchGetLastSMFromLists(s, 6,
DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH],
DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH]); DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH],
DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH]);
if (pm == NULL) { if (pm == NULL) {
SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "distance needs" SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "offset needs"
"preceeding content or uricontent option"); "preceeding content or uricontent option or http_client_body option");
if (dubbed) if (dubbed)
SCFree(str); SCFree(str);
return -1; return -1;
@ -94,6 +95,7 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr)
break; break;
} }
/* we can remove this switch now with the unified structure */
DetectContentData *ud = NULL; DetectContentData *ud = NULL;
DetectContentData *cd = NULL; DetectContentData *cd = NULL;
switch (pm->type) { switch (pm->type) {
@ -173,6 +175,23 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, char *offsetstr)
break; break;
case DETECT_AL_HTTP_CLIENT_BODY:
cd = (DetectContentData *)pm->ctx;
cd->offset = (uint32_t)atoi(str);
if (cd->depth != 0) {
if (cd->depth < cd->content_len) {
SCLogDebug("depth increased to %"PRIu32" to match pattern len",
cd->content_len);
cd->depth = cd->content_len;
}
/* Updating the depth as is relative to the offset */
cd->depth += cd->offset;
}
cd->flags |= DETECT_CONTENT_OFFSET;
break;
default: default:
SCLogError(SC_ERR_OFFSET_MISSING_CONTENT, "offset needs a preceeding" SCLogError(SC_ERR_OFFSET_MISSING_CONTENT, "offset needs a preceeding"
" content or uricontent option"); " content or uricontent option");

@ -1361,6 +1361,8 @@ Signature *SigInit(DetectEngineCtx *de_ctx, char *sigstr) {
sig->flags |= SIG_FLAG_AMATCH; sig->flags |= SIG_FLAG_AMATCH;
if (sig->sm_lists[DETECT_SM_LIST_AMATCH]) if (sig->sm_lists[DETECT_SM_LIST_AMATCH])
sig->flags |= SIG_FLAG_AMATCH; sig->flags |= SIG_FLAG_AMATCH;
if (sig->sm_lists[DETECT_SM_LIST_HCBDMATCH])
sig->flags |= SIG_FLAG_HCBDMATCH;
SCLogDebug("sig %"PRIu32" SIG_FLAG_APPLAYER: %s, SIG_FLAG_PACKET: %s", SCLogDebug("sig %"PRIu32" SIG_FLAG_APPLAYER: %s, SIG_FLAG_PACKET: %s",
sig->id, sig->flags & SIG_FLAG_APPLAYER ? "set" : "not set", sig->id, sig->flags & SIG_FLAG_APPLAYER ? "set" : "not set",

@ -169,12 +169,13 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi
} }
} }
} else { } else {
pm = SigMatchGetLastSMFromLists(s, 4, pm = SigMatchGetLastSMFromLists(s, 6,
DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH],
DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH]); DETECT_URICONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH],
DETECT_AL_HTTP_CLIENT_BODY, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH]);
if (pm == NULL) { if (pm == NULL) {
SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs" SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs"
"preceeding content or uricontent option"); "preceeding content or uricontent or http_client_body option");
if (dubbed) if (dubbed)
SCFree(str); SCFree(str);
return -1; return -1;
@ -382,8 +383,32 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi
} }
} }
break;
break; case DETECT_AL_HTTP_CLIENT_BODY:
cd = (DetectContentData *)pm->ctx;
cd->within = strtol(str, NULL, 10);
if (cd->within < (int32_t)cd->content_len) {
SCLogError(SC_ERR_WITHIN_INVALID, "within argument \"%"PRIi32"\" is "
"less than the content length \"%"PRIu32"\" which is invalid, since "
"this will never match. Invalidating signature", ud->within,
ud->content_len);
goto error;
}
cd->flags |= DETECT_CONTENT_WITHIN;
pm = SigMatchGetLastSMFromLists(s, 2,
DETECT_AL_HTTP_CLIENT_BODY, pm->prev);
if (pm == NULL) {
SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for http_client_body "
"needs preceeding http_client_body content");
goto error;
}
((DetectContentData *)pm->ctx)->flags |= DETECT_CONTENT_RELATIVE_NEXT;
break;
default: default:
SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs two " SCLogError(SC_ERR_WITHIN_MISSING_CONTENT, "within needs two "

@ -681,7 +681,7 @@ static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx,
/* de_state check, filter out all signatures that already had a match before /* de_state check, filter out all signatures that already had a match before
* or just partially match */ * or just partially match */
if (s->flags & SIG_FLAG_AMATCH || s->flags & SIG_FLAG_UMATCH || if (s->flags & SIG_FLAG_AMATCH || s->flags & SIG_FLAG_UMATCH ||
s->flags & SIG_FLAG_DMATCH) s->flags & SIG_FLAG_DMATCH || s->flags & SIG_FLAG_HCBDMATCH)
{ {
/* we run after DeStateDetectContinueDetection, so we might have /* we run after DeStateDetectContinueDetection, so we might have
* state NEW here. In that case we'd want to continue detection * state NEW here. In that case we'd want to continue detection
@ -1144,7 +1144,10 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
SCLogDebug("s->sm_lists[DETECT_SM_LIST_AMATCH] %p, s->sm_lists[DETECT_SM_LIST_UMATCH] %p, s->sm_lists[DETECT_SM_LIST_DMATCH] %p", SCLogDebug("s->sm_lists[DETECT_SM_LIST_AMATCH] %p, s->sm_lists[DETECT_SM_LIST_UMATCH] %p, s->sm_lists[DETECT_SM_LIST_DMATCH] %p",
s->sm_lists[DETECT_SM_LIST_AMATCH], s->sm_lists[DETECT_SM_LIST_UMATCH], s->sm_lists[DETECT_SM_LIST_DMATCH]); s->sm_lists[DETECT_SM_LIST_AMATCH], s->sm_lists[DETECT_SM_LIST_UMATCH], s->sm_lists[DETECT_SM_LIST_DMATCH]);
if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL || s->sm_lists[DETECT_SM_LIST_UMATCH] != NULL || s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL) { if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL ||
s->sm_lists[DETECT_SM_LIST_UMATCH] != NULL ||
s->sm_lists[DETECT_SM_LIST_DMATCH] != NULL ||
s->sm_lists[DETECT_SM_LIST_HCBDMATCH]) {
if (alstate == NULL) { if (alstate == NULL) {
SCLogDebug("state matches but no state, we can't match"); SCLogDebug("state matches but no state, we can't match");
goto next; goto next;
@ -1451,6 +1454,9 @@ int SignatureIsIPOnly(DetectEngineCtx *de_ctx, Signature *s) {
if (s->sm_lists[DETECT_SM_LIST_UMATCH] != NULL) if (s->sm_lists[DETECT_SM_LIST_UMATCH] != NULL)
return 0; return 0;
if (s->sm_lists[DETECT_SM_LIST_HCBDMATCH] != NULL)
return 0;
if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL)
return 0; return 0;
@ -1522,6 +1528,9 @@ static int SignatureIsDEOnly(DetectEngineCtx *de_ctx, Signature *s) {
if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL)
return 0; return 0;
if (s->sm_lists[DETECT_SM_LIST_HCBDMATCH] != NULL)
return 0;
SigMatch *sm = s->sm_lists[DETECT_SM_LIST_MATCH]; SigMatch *sm = s->sm_lists[DETECT_SM_LIST_MATCH];
/* check for conflicting keywords */ /* check for conflicting keywords */
for ( ;sm != NULL; sm = sm->next) { for ( ;sm != NULL; sm = sm->next) {
@ -1606,7 +1615,12 @@ static int SignatureCreateMask(Signature *s) {
if (s->sm_lists[DETECT_SM_LIST_UMATCH] != NULL) { if (s->sm_lists[DETECT_SM_LIST_UMATCH] != NULL) {
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE; s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
SCLogDebug("sig requires dce http state"); SCLogDebug("sig requires http state");
}
if (s->sm_lists[DETECT_SM_LIST_HCBDMATCH] != NULL) {
s->mask |= SIG_MASK_REQUIRE_HTTP_STATE;
SCLogDebug("sig requires http app state");
} }
SigMatch *sm; SigMatch *sm;

@ -86,6 +86,7 @@ enum {
DETECT_SM_LIST_AMATCH, DETECT_SM_LIST_AMATCH,
DETECT_SM_LIST_DMATCH, DETECT_SM_LIST_DMATCH,
DETECT_SM_LIST_TMATCH, DETECT_SM_LIST_TMATCH,
DETECT_SM_LIST_HCBDMATCH,
DETECT_SM_LIST_MAX, DETECT_SM_LIST_MAX,
}; };
@ -227,13 +228,14 @@ typedef struct DetectPort_ {
#define SIG_FLAG_UMATCH 0x00040000 #define SIG_FLAG_UMATCH 0x00040000
#define SIG_FLAG_AMATCH 0x00080000 #define SIG_FLAG_AMATCH 0x00080000
#define SIG_FLAG_DMATCH 0x00100000 #define SIG_FLAG_DMATCH 0x00100000
#define SIG_FLAG_HCBDMATCH 0x00200000
#define SIG_FLAG_MPM_PACKET 0x00200000 #define SIG_FLAG_MPM_PACKET 0x00400000
#define SIG_FLAG_MPM_STREAM 0x00400000 #define SIG_FLAG_MPM_STREAM 0x00800000
#define SIG_FLAG_MPM_URICONTENT 0x00800000 #define SIG_FLAG_MPM_URICONTENT 0x01000000
#define SIG_FLAG_MPM_URICONTENT_NEG 0x01000000 #define SIG_FLAG_MPM_URICONTENT_NEG 0x02000000
#define SIG_FLAG_HAS_NO_PKT_AND_STREAM_CONTENT 0x02000000 #define SIG_FLAG_HAS_NO_PKT_AND_STREAM_CONTENT 0x04000000
/* signature mask flags */ /* signature mask flags */
#define SIG_MASK_REQUIRE_PAYLOAD 0x01 #define SIG_MASK_REQUIRE_PAYLOAD 0x01

@ -53,6 +53,7 @@
#include "detect-engine-payload.h" #include "detect-engine-payload.h"
#include "detect-engine-dcepayload.h" #include "detect-engine-dcepayload.h"
#include "detect-engine-uri.h" #include "detect-engine-uri.h"
#include "detect-engine-hcbd.h"
#include "detect-engine-state.h" #include "detect-engine-state.h"
#include "detect-engine-tag.h" #include "detect-engine-tag.h"
#include "detect-fast-pattern.h" #include "detect-fast-pattern.h"
@ -942,7 +943,6 @@ int main(int argc, char **argv)
TmqhFlowRegisterTests(); TmqhFlowRegisterTests();
FlowRegisterTests(); FlowRegisterTests();
SCSigRegisterSignatureOrderingTests(); SCSigRegisterSignatureOrderingTests();
SCLogRegisterTests();
SCRadixRegisterTests(); SCRadixRegisterTests();
DefragRegisterTests(); DefragRegisterTests();
SigGroupHeadRegisterTests(); SigGroupHeadRegisterTests();
@ -968,7 +968,9 @@ int main(int argc, char **argv)
DeStateRegisterTests(); DeStateRegisterTests();
DetectRingBufferRegisterTests(); DetectRingBufferRegisterTests();
MemcmpRegisterTests(); MemcmpRegisterTests();
HttpClientBodyRegisterTests();
DetectEngineRegisterTests(); DetectEngineRegisterTests();
SCLogRegisterTests();
if (list_unittests) { if (list_unittests) {
UtListTests(regex_arg); UtListTests(regex_arg);
} }

Loading…
Cancel
Save