Adding actions order and suport for rule action "pass"

remotes/origin/master-1.0.x
Pablo Rincon 16 years ago committed by Victor Julien
parent 6dd5446893
commit 1238668961

@ -192,6 +192,7 @@ app-layer-ftp.c app-layer-ftp.h \
defrag.c defrag.h \
output.c output.h \
win32-misc.c win32-misc.h \
util-action.c util-action.h \
win32-syslog.h
# set the include path found by configure

@ -186,6 +186,8 @@ typedef uint16_t Port;
/* structure to store the sids/gids/etc the detection engine
* found in this packet */
typedef struct PacketAlert_ {
uint16_t num; /* Internal num, used for sorting */
uint8_t action; /* Internal num, used for sorting */
uint32_t gid;
uint32_t sid;
uint8_t rev;

@ -944,6 +944,9 @@ void IPOnlyMatchPacket(DetectEngineCtx *de_ctx,
/* The final results will be at io_tctx */
io_tctx->sig_match_array[u] = dst->array[u] & src->array[u];
/* We have to move the logic of the signature checking
* to the main detect loop, in order to apply the
* priority of actions (pass, drop, reject, alert) */
if (io_tctx->sig_match_array[u] != 0) {
/* We have a match :) Let's see from which signum's */
uint8_t bitarray = io_tctx->sig_match_array[u];
@ -961,10 +964,6 @@ void IPOnlyMatchPacket(DetectEngineCtx *de_ctx,
u * 8 + i, s->id, s->msg);
if (!(s->flags & SIG_FLAG_NOALERT)) {
PacketAlertHandle(de_ctx, det_ctx, s, p);
/* set verdict on packet */
p->action |= s->action;
if (p->flow != NULL) {
if (s->action & ACTION_DROP)
p->flow->flags |= FLOW_ACTION_DROP;
@ -974,7 +973,11 @@ void IPOnlyMatchPacket(DetectEngineCtx *de_ctx,
p->flow->flags |= FLOW_ACTION_DROP;
if (s->action & ACTION_REJECT_BOTH)
p->flow->flags |= FLOW_ACTION_DROP;
if (s->action & ACTION_PASS)
p->flow->flags |= FLOW_ACTION_PASS;
}
p->action |= ACTION_PASS;
PacketAlertHandle(de_ctx, det_ctx, s, p);
}
}
}

@ -36,6 +36,8 @@
#include "util-unittest.h"
#include "util-debug.h"
#include "util-action.h"
#include "action-globals.h"
#define DETECT_FLOWVAR_NOT_USED 1
#define DETECT_FLOWVAR_TYPE_READ 2
@ -270,7 +272,7 @@ static void SCSigOrderByAction(DetectEngineCtx *de_ctx,
while (min != max) {
prev = min;
/* the sorting logic */
if (sw->sig->action <= min->sig->action) {
if (ActionOrderVal(sw->sig->action) >= ActionOrderVal(min->sig->action)) {
min = min->next;
continue;
}
@ -696,7 +698,7 @@ static void SCSigOrderByPriority(DetectEngineCtx *de_ctx,
while (min != max) {
prev = min;
/* the sorting logic */
if (sw->sig->prio >= min->sig->prio) {
if (sw->sig->prio <= min->sig->prio) {
min = min->next;
continue;
}
@ -1550,6 +1552,508 @@ end:
return result;
}
static int SCSigTestSignatureOrdering07(void)
{
int result = 1;
Signature *prevsig = NULL, *sig = NULL;
SCSigSignatureWrapper *sw = NULL;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; sid:1; rev:4;)");
if (sig == NULL) {
goto end;
}
prevsig = sig;
de_ctx->sig_list = sig;
sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; sid:2; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:10; depth:4; sid:3; rev:4; priority:3;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; depth:4; sid:4; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:5; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "drop tcp any !21:902 -> any any (msg:\"Testing sigordering drop\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:6; rev:4; priority:1;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "reject tcp any !21:902 -> any any (msg:\"Testing sigordering reject\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:7; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; sid:8; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbits);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvar);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvar);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriority);
SCSigOrderSignatures(de_ctx);
sw = de_ctx->sc_sig_sig_wrapper;
uint8_t pos = 0;
while (sw != NULL) {
switch (pos) {
case 0:
result &=(sw->sig->id == 2)? 1 : 0;
break;
case 1:
result &=(sw->sig->id == 4)? 1 : 0;
break;
case 2:
result &=(sw->sig->id == 5)? 1 : 0;
break;
case 3:
result &=(sw->sig->id == 6)? 1 : 0;
break;
case 4:
result &=(sw->sig->id == 7)? 1 : 0;
break;
case 5:
result &=(sw->sig->id == 1)? 1 : 0;
break;
case 6:
result &=(sw->sig->id == 3)? 1 : 0;
break;
case 7:
result &=(sw->sig->id == 8)? 1 : 0;
break;
}
sw = sw->next;
pos++;
}
end:
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
/**
* \test Order with a different Action priority
* (as specified from config)
*/
static int SCSigTestSignatureOrdering08(void)
{
int result = 1;
Signature *prevsig = NULL, *sig = NULL;
SCSigSignatureWrapper *sw = NULL;
extern uint8_t action_order_sigs[4];
/* Let's change the order. Default is pass, drop, reject, alert (pass has highest prio) */
action_order_sigs[0] = ACTION_REJECT;
action_order_sigs[1] = ACTION_DROP;
action_order_sigs[2] = ACTION_ALERT;
action_order_sigs[3] = ACTION_PASS;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; sid:1; rev:4;)");
if (sig == NULL) {
goto end;
}
prevsig = sig;
de_ctx->sig_list = sig;
sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; sid:2; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:10; depth:4; sid:3; rev:4; priority:3;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; depth:4; sid:4; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:5; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "drop tcp any !21:902 -> any any (msg:\"Testing sigordering drop\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:6; rev:4; priority:1;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "reject tcp any !21:902 -> any any (msg:\"Testing sigordering reject\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:7; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; sid:8; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbits);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvar);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvar);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriority);
SCSigOrderSignatures(de_ctx);
sw = de_ctx->sc_sig_sig_wrapper;
uint8_t pos = 0;
while (sw != NULL) {
switch (pos) {
case 0:
result &=(sw->sig->id == 7)? 1 : 0;
break;
case 1:
result &=(sw->sig->id == 6)? 1 : 0;
break;
case 2:
result &=(sw->sig->id == 1)? 1 : 0;
break;
case 3:
result &=(sw->sig->id == 3)? 1 : 0;
break;
case 4:
result &=(sw->sig->id == 8)? 1 : 0;
break;
case 5:
result &=(sw->sig->id == 2)? 1 : 0;
break;
case 6:
result &=(sw->sig->id == 4)? 1 : 0;
break;
case 7:
result &=(sw->sig->id == 5)? 1 : 0;
break;
}
sw = sw->next;
pos++;
}
end:
/* Restore the default pre-order definition */
action_order_sigs[0] = ACTION_PASS;
action_order_sigs[1] = ACTION_DROP;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
/**
* \test Order with a different Action priority
* (as specified from config)
*/
static int SCSigTestSignatureOrdering09(void)
{
int result = 1;
Signature *prevsig = NULL, *sig = NULL;
SCSigSignatureWrapper *sw = NULL;
extern uint8_t action_order_sigs[4];
/* Let's change the order. Default is pass, drop, reject, alert (pass has highest prio) */
action_order_sigs[0] = ACTION_DROP;
action_order_sigs[1] = ACTION_REJECT;
action_order_sigs[2] = ACTION_ALERT;
action_order_sigs[3] = ACTION_PASS;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; sid:1; rev:4;)");
if (sig == NULL) {
goto end;
}
prevsig = sig;
de_ctx->sig_list = sig;
sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; sid:2; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:10; depth:4; sid:3; rev:4; priority:3;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; depth:4; sid:4; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:5; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "drop tcp any !21:902 -> any any (msg:\"Testing sigordering drop\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:6; rev:4; priority:1;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "reject tcp any !21:902 -> any any (msg:\"Testing sigordering reject\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:7; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; sid:8; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbits);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvar);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvar);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriority);
SCSigOrderSignatures(de_ctx);
sw = de_ctx->sc_sig_sig_wrapper;
uint8_t pos = 0;
while (sw != NULL) {
switch (pos) {
case 0:
result &=(sw->sig->id == 6)? 1 : 0;
break;
case 1:
result &=(sw->sig->id == 7)? 1 : 0;
break;
case 2:
result &=(sw->sig->id == 1)? 1 : 0;
break;
case 3:
result &=(sw->sig->id == 3)? 1 : 0;
break;
case 4:
result &=(sw->sig->id == 8)? 1 : 0;
break;
case 5:
result &=(sw->sig->id == 2)? 1 : 0;
break;
case 6:
result &=(sw->sig->id == 4)? 1 : 0;
break;
case 7:
result &=(sw->sig->id == 5)? 1 : 0;
break;
}
sw = sw->next;
pos++;
}
end:
/* Restore the default pre-order definition */
action_order_sigs[0] = ACTION_DROP;
action_order_sigs[1] = ACTION_REJECT;
action_order_sigs[2] = ACTION_PASS;
action_order_sigs[3] = ACTION_ALERT;
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
/**
* \test Order with a different Action priority
* (as specified from config)
*/
static int SCSigTestSignatureOrdering10(void)
{
int result = 1;
Signature *prevsig = NULL, *sig = NULL;
SCSigSignatureWrapper *sw = NULL;
extern uint8_t action_order_sigs[4];
/* Let's change the order. Default is pass, drop, reject, alert (pass has highest prio) */
action_order_sigs[0] = ACTION_PASS;
action_order_sigs[1] = ACTION_ALERT;
action_order_sigs[2] = ACTION_DROP;
action_order_sigs[3] = ACTION_REJECT;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; sid:1; rev:4;)");
if (sig == NULL) {
goto end;
}
prevsig = sig;
de_ctx->sig_list = sig;
sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; sid:2; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:10; depth:4; sid:3; rev:4; priority:3;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; depth:4; sid:4; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:5; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "drop tcp any !21:902 -> any any (msg:\"Testing sigordering drop\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:6; rev:4; priority:1;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "reject tcp any !21:902 -> any any (msg:\"Testing sigordering reject\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:7; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; sid:8; rev:4; priority:2;)");
if (sig == NULL) {
goto end;
}
prevsig->next = sig;
prevsig = sig;
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbits);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvar);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvar);
SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriority);
SCSigOrderSignatures(de_ctx);
sw = de_ctx->sc_sig_sig_wrapper;
uint8_t pos = 0;
while (sw != NULL) {
switch (pos) {
case 0:
result &=(sw->sig->id == 2)? 1 : 0;
break;
case 1:
result &=(sw->sig->id == 4)? 1 : 0;
break;
case 2:
result &=(sw->sig->id == 5)? 1 : 0;
break;
case 3:
result &=(sw->sig->id == 1)? 1 : 0;
break;
case 4:
result &=(sw->sig->id == 3)? 1 : 0;
break;
case 5:
result &=(sw->sig->id == 8)? 1 : 0;
break;
case 6:
result &=(sw->sig->id == 6)? 1 : 0;
break;
case 7:
result &=(sw->sig->id == 7)? 1 : 0;
break;
}
sw = sw->next;
pos++;
}
end:
/* Restore the default pre-order definition */
action_order_sigs[0] = ACTION_PASS;
action_order_sigs[1] = ACTION_DROP;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
#endif
void SCSigRegisterSignatureOrderingTests(void)
@ -1563,6 +2067,10 @@ void SCSigRegisterSignatureOrderingTests(void)
UtRegisterTest("SCSigTestSignatureOrdering04", SCSigTestSignatureOrdering04, 1);
UtRegisterTest("SCSigTestSignatureOrdering05", SCSigTestSignatureOrdering05, 1);
UtRegisterTest("SCSigTestSignatureOrdering06", SCSigTestSignatureOrdering06, 1);
UtRegisterTest("SCSigTestSignatureOrdering07", SCSigTestSignatureOrdering07, 1);
UtRegisterTest("SCSigTestSignatureOrdering08", SCSigTestSignatureOrdering08, 1);
UtRegisterTest("SCSigTestSignatureOrdering09", SCSigTestSignatureOrdering09, 1);
UtRegisterTest("SCSigTestSignatureOrdering10", SCSigTestSignatureOrdering10, 1);
#endif

@ -388,6 +388,17 @@ int SigLoadSignatures (DetectEngineCtx *de_ctx, char *sig_file)
SCSigOrderSignatures(de_ctx);
SCSigSignatureOrderingModuleCleanup(de_ctx);
Signature *s = de_ctx->sig_list;
/* Assign the unique id of signatures after sorting,
* so the IP Only engine process them in order too */
uint16_t sig_id = 0;
while (s != NULL) {
s->num = sig_id++;
s = s->next;
}
de_ctx->signum = sig_id;
/* Setup the signature group lookup structure and pattern matchers */
SigGroupBuild(de_ctx);
SCReturnInt(0);
@ -416,22 +427,55 @@ int PacketAlertCheck(Packet *p, uint32_t sid)
int PacketAlertAppend(DetectEngineThreadCtx *det_ctx, Signature *s, Packet *p)
{
int i = 0;
if (p->alerts.cnt == PACKET_ALERT_MAX)
return 0;
SCLogDebug("sid %"PRIu32"", s->id);
if (s->gid > 1)
p->alerts.alerts[p->alerts.cnt].gid = s->gid;
else
p->alerts.alerts[p->alerts.cnt].gid = 1;
p->alerts.alerts[p->alerts.cnt].sid = s->id;
p->alerts.alerts[p->alerts.cnt].rev = s->rev;
p->alerts.alerts[p->alerts.cnt].prio = s->prio;
p->alerts.alerts[p->alerts.cnt].msg = s->msg;
p->alerts.alerts[p->alerts.cnt].class_msg = s->class_msg;
p->alerts.alerts[p->alerts.cnt].references = s->references;
/* It should be usually the last, so check it before iterating */
if (p->alerts.cnt == 0 || (p->alerts.cnt > 0 &&
p->alerts.alerts[p->alerts.cnt - 1].num < s->num)) {
/* We just add it */
if (s->gid > 1)
p->alerts.alerts[p->alerts.cnt].gid = s->gid;
else
p->alerts.alerts[p->alerts.cnt].gid = 1;
p->alerts.alerts[p->alerts.cnt].num= s->num;
p->alerts.alerts[p->alerts.cnt].action = s->action;
p->alerts.alerts[p->alerts.cnt].sid = s->id;
p->alerts.alerts[p->alerts.cnt].rev = s->rev;
p->alerts.alerts[p->alerts.cnt].prio = s->prio;
p->alerts.alerts[p->alerts.cnt].msg = s->msg;
p->alerts.alerts[p->alerts.cnt].class_msg = s->class_msg;
p->alerts.alerts[p->alerts.cnt].references = s->references;
} else {
/* We need to make room for this s->num
(a bit ugly with mamcpy but we are planning changes here)*/
for (i = p->alerts.cnt - 1; i >= 0 && p->alerts.alerts[i].num > s->num; i--) {
memcpy(&p->alerts.alerts[i + 1], &p->alerts.alerts[i], sizeof(PacketAlert));
}
i++; /* The right place to store the alert */
if (s->gid > 1)
p->alerts.alerts[i].gid = s->gid;
else
p->alerts.alerts[i].gid = 1;
p->alerts.alerts[p->alerts.cnt].num= s->num;
p->alerts.alerts[p->alerts.cnt].action = s->action;
p->alerts.alerts[i].sid = s->id;
p->alerts.alerts[i].rev = s->rev;
p->alerts.alerts[i].prio = s->prio;
p->alerts.alerts[i].msg = s->msg;
p->alerts.alerts[i].class_msg = s->class_msg;
p->alerts.alerts[i].references = s->references;
}
/* Update the count */
p->alerts.cnt++;
SCPerfCounterIncr(det_ctx->counter_alerts, det_ctx->tv->sc_perf_pca);
@ -508,6 +552,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
void *alstate = NULL;
uint8_t flags = 0;
uint32_t cnt = 0;
uint16_t i = 0;
SCEnter();
@ -545,6 +590,10 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
(p->flowflags & FLOW_PKT_TOCLIENT &&
(p->flow->flags & FLOW_TOCLIENT_IPONLY_SET)))) {
/* Get the result of the first IPOnlyMatch() */
if (p->flow->flags & FLOW_ACTION_PASS) {
/* if it matched a "pass" rule, we have to let it go */
p->action |= ACTION_PASS;
}
if (p->flow->flags & FLOW_ACTION_DROP) p->action |= ACTION_DROP;
} else {
/* Even without flow we should match the packet src/dst */
@ -708,9 +757,9 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
fmatch = 1;
if (!(s->flags & SIG_FLAG_NOALERT)) {
PacketAlertHandle(de_ctx, det_ctx, s, p);
/* set verdict on packet */
p->action |= s->action;
PacketAlertHandle(de_ctx, det_ctx, s, p);
}
} else {
/* reset offset */
@ -746,9 +795,10 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
if (!(s->flags & SIG_FLAG_NOALERT)) {
/* only add once */
if (rmatch == 0) {
PacketAlertHandle(de_ctx, det_ctx, s, p);
/* set verdict on packet */
p->action |= s->action;
PacketAlertHandle(de_ctx, det_ctx, s, p);
}
}
rmatch = fmatch = 1;
@ -760,11 +810,13 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
rmatch = 0;
}
}
/* Limit the number of times we do this recursive thing.
* XXX is this a sane limit? Should it be configurable? */
if (det_ctx->pkt_cnt == 10)
break;
} while (rmatch);
} else {
sm = s->match;
@ -790,12 +842,10 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
if (sm == NULL) {
fmatch = 1;
if (!(s->flags & SIG_FLAG_NOALERT)) {
/* set flowbit for this match */
PacketAlertHandle(de_ctx, det_ctx, s, p);
/* set verdict on packet */
p->action |= s->action;
PacketAlertHandle(de_ctx, det_ctx, s, p);
}
}
} else {
@ -803,15 +853,31 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
sm = NULL;
}
}
SCLogDebug("match functions done, sm %p", sm);
}
}
}
/* so now let's iterate the alerts and remove the ones after a pass rule
* matched (if any) */
end:
SCLogDebug("(p->action & ation pass)) = %"PRIu8, (p->action & ACTION_PASS));
if (p->action & ACTION_PASS) {
for (; i < p->alerts.cnt; i++) {
SCLogDebug("Sig->num: %"PRIu16, p->alerts.alerts[i].num);
if (p->alerts.alerts[i].action & ACTION_PASS) {
/* Ok, reset the alert cnt to end in the previous of pass
* so we ignore the rest with less prio */
p->alerts.cnt = i;
break;
}
}
}
/* cleanup pkt specific part of the patternmatcher */
PacketPatternCleanup(th_v, det_ctx);
end:
if (p->flow != NULL) {
SCMutexLock(&p->flow->m);
p->flow->use_cnt--;

@ -56,6 +56,8 @@
/** All packets in this flow should be dropped */
#define FLOW_ACTION_DROP 0x0200
/** All packets in this flow should be accepted */
#define FLOW_ACTION_PASS 0x0400
/* pkt flow flags */
#define FLOW_PKT_TOSERVER 0x01

@ -42,6 +42,7 @@
#include "util-pool.h"
#include "util-byte.h"
#include "util-cpu.h"
#include "util-action.h"
#include "util-pidfile.h"
#include "detect-parse.h"
@ -831,6 +832,7 @@ int main(int argc, char **argv)
AppLayerParserRegisterTests();
ThreadMacrosRegisterTests();
UtilSpmSearchRegistertests();
UtilActionRegisterTests();
SCClassConfRegisterTests();
SCThresholdConfRegisterTests();
#ifdef __SC_CUDA_SUPPORT__
@ -931,6 +933,8 @@ int main(int argc, char **argv)
SCClassConfLoadClassficationConfigFile(de_ctx);
ActionInitConfig();
if (SigLoadSignatures(de_ctx, sig_file) < 0) {
if (sig_file == NULL) {
SCLogError(SC_ERR_OPENING_FILE, "Signature file has not been provided");

@ -0,0 +1,995 @@
/**
* Copyright(c) 2009 Open Information Security Foundation.
* \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
*/
#include "suricata-common.h"
#include "action-globals.h"
#include "conf.h"
#include "conf-yaml-loader.h"
#include "detect.h"
#include "detect-engine.h"
#include "detect-engine-sigorder.h"
#include "util-unittest.h"
#include "util-action.h"
#include "util-unittest-helper.h"
#include "util-debug.h"
/* Default order: */
uint8_t action_order_sigs[4] = {ACTION_PASS, ACTION_DROP, ACTION_REJECT, ACTION_ALERT};
/* This order can be changed from config */
/**
* \brief Return the priority associated to an action (to order sigs
* as specified at config)
* action_order_sigs has this priority by index val
* so action_order_sigs[0] has to be inspected first.
* This function is called from detect-engine-sigorder
* \param action can be one of ACTION_PASS, ACTION_DROP,
* ACTION_REJECT or ACTION_ALERT
* \retval uint8_t the priority (order of this actions)
*/
uint8_t ActionOrderVal(uint8_t action) {
/* reject_both and reject_dst have the same prio as reject */
if( action & ACTION_REJECT ||
action & ACTION_REJECT_BOTH ||
action & ACTION_REJECT_BOTH) {
action = ACTION_REJECT;
}
uint8_t i = 0;
for (; i < 4; i++) {
if (action_order_sigs[i] == action)
return i;
}
/* Unknown action, set just a low prio (high val) */
return 10;
}
/**
* \brief Return the ACTION_* bit from their ascii value
* \param action can be one of "pass", "drop",
* "reject" or "alert"
* \retval uint8_t can be one of ACTION_PASS, ACTION_DROP,
* ACTION_REJECT or ACTION_ALERT
*/
uint8_t ActionAsciiToFlag(char *action) {
if (strcmp(action,"pass") == 0)
return ACTION_PASS;
if (strcmp(action,"drop") == 0)
return ACTION_DROP;
if (strcmp(action,"reject") == 0)
return ACTION_REJECT;
if (strcmp(action,"alert") == 0)
return ACTION_ALERT;
return 0;
}
/**
* \brief Load the action order from config. If none is provided,
* it will be default to ACTION_PASS, ACTION_DROP,
* ACTION_REJECT, ACTION_ALERT (pass has the highest prio)
* \retval none
*/
void ActionInitConfig() {
uint8_t actions_used = 0;
uint8_t action_flag = 0;
uint8_t actions_config[4] = {0, 0, 0, 0};
int order = 0;
ConfNode *action_order;
ConfNode *action = NULL;
/* Let's load the order of actions from the general config */
action_order = ConfGetNode("action-order");
if (action_order != NULL) {
TAILQ_FOREACH(action, &action_order->head, next) {
SCLogDebug("Loading action order : %s", action->val);
action_flag = ActionAsciiToFlag(action->val);
if (action_flag == 0) {
SCLogError(SC_ERR_ACTION_ORDER, "action-order, invalid action: \"%s\". Please, use"
" \"pass\",\"drop\",\"alert\",\"reject\". You have"
" to specify all of them, without quotes and without"
" capital letters", action->val);
return;
}
if (actions_used & action_flag) {
SCLogError(SC_ERR_ACTION_ORDER, "action-order, action already set: \"%s\". Please,"
" use \"pass\",\"drop\",\"alert\",\"reject\". You"
" have to specify all of them, without quotes and"
" without capital letters", action->val);
return;
}
if (order >= 4) {
SCLogError(SC_ERR_ACTION_ORDER, "action-order, you have already specified all the "
"possible actions plus \"%s\". Please, use \"pass\","
"\"drop\",\"alert\",\"reject\". You have to specify"
" all of them, without quotes and without capital"
" letters", action->val);
return;
}
actions_used |= action_flag;
actions_config[order++] = action_flag;
}
}
if (order < 4) {
SCLogError(SC_ERR_ACTION_ORDER, "action-order, the config didn't specify all of the "
"actions. Please, use \"pass\",\"drop\",\"alert\","
"\"reject\". You have to specify all of them, without"
" quotes and without capital letters");
return;
}
/* Now, it's a valid config. Override the default preset */
for (order = 0; order < 4; order++) {
action_order_sigs[order] = actions_config[order];
}
}
#ifdef UNITTESTS
#include "util-unittest.h"
/**
* \test Check that we invalidate duplicated actions
* (It should default to pass, drop, reject, alert)
*/
int UtilActionTest01(void)
{
int res = 1;
char config[] = "\
%YAML 1.1\n\
---\n\
action-order:\n\
- alert\n\
- drop\n\
- reject\n\
- alert\n";
ConfCreateContextBackup();
ConfInit();
ConfYamlLoadString(config, strlen(config));
ActionInitConfig();
if (action_order_sigs[0] != ACTION_PASS ||
action_order_sigs[1] != ACTION_DROP ||
action_order_sigs[2] != ACTION_REJECT ||
action_order_sigs[3] != ACTION_ALERT)
{
res = 0;
}
ConfRestoreContextBackup();
/* Restore default values */
action_order_sigs[0] = ACTION_PASS;
action_order_sigs[1] = ACTION_DROP;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
return res;
}
/**
* \test Check that we invalidate with unknown keywords
* (It should default to pass, drop, reject, alert)
*/
int UtilActionTest02(void)
{
int res = 1;
char config[] = "\
%YAML 1.1\n\
---\n\
action-order:\n\
- alert\n\
- drop\n\
- reject\n\
- ftw\n";
ConfCreateContextBackup();
ConfInit();
ConfYamlLoadString(config, strlen(config));
ActionInitConfig();
if (action_order_sigs[0] != ACTION_PASS ||
action_order_sigs[1] != ACTION_DROP ||
action_order_sigs[2] != ACTION_REJECT ||
action_order_sigs[3] != ACTION_ALERT)
{
res = 0;
}
ConfRestoreContextBackup();
/* Restore default values */
action_order_sigs[0] = ACTION_PASS;
action_order_sigs[1] = ACTION_DROP;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
return res;
}
/**
* \test Check that we invalidate if any action is missing
* (It should default to pass, drop, reject, alert)
*/
int UtilActionTest03(void)
{
int res = 1;
char config[] = "\
%YAML 1.1\n\
---\n\
action-order:\n\
- alert\n\
- drop\n\
- reject\n";
ConfCreateContextBackup();
ConfInit();
ConfYamlLoadString(config, strlen(config));
ActionInitConfig();
if (action_order_sigs[0] != ACTION_PASS ||
action_order_sigs[1] != ACTION_DROP ||
action_order_sigs[2] != ACTION_REJECT ||
action_order_sigs[3] != ACTION_ALERT)
{
res = 0;
}
ConfRestoreContextBackup();
/* Restore default values */
action_order_sigs[0] = ACTION_PASS;
action_order_sigs[1] = ACTION_DROP;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
return res;
}
/**
* \test Check that we invalidate if any action is missing
* (It should default to pass, drop, reject, alert)
*/
int UtilActionTest04(void)
{
int res = 1;
char config[] = "\
%YAML 1.1\n\
---\n\
action-order:\n";
ConfCreateContextBackup();
ConfInit();
ConfYamlLoadString(config, strlen(config));
ActionInitConfig();
if (action_order_sigs[0] != ACTION_PASS ||
action_order_sigs[1] != ACTION_DROP ||
action_order_sigs[2] != ACTION_REJECT ||
action_order_sigs[3] != ACTION_ALERT)
{
res = 0;
}
ConfRestoreContextBackup();
/* Restore default values */
action_order_sigs[0] = ACTION_PASS;
action_order_sigs[1] = ACTION_DROP;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
return res;
}
/**
* \test Check that we invalidate with unknown keywords
* and/or more than the expected
* (It should default to pass, drop, reject, alert)
*/
int UtilActionTest05(void)
{
int res = 1;
char config[] = "\
%YAML 1.1\n\
---\n\
action-order:\n\
- alert\n\
- drop\n\
- reject\n\
- pass\n\
- whatever\n";
ConfCreateContextBackup();
ConfInit();
ConfYamlLoadString(config, strlen(config));
ActionInitConfig();
if (action_order_sigs[0] != ACTION_PASS ||
action_order_sigs[1] != ACTION_DROP ||
action_order_sigs[2] != ACTION_REJECT ||
action_order_sigs[3] != ACTION_ALERT)
{
res = 0;
}
ConfRestoreContextBackup();
/* Restore default values */
action_order_sigs[0] = ACTION_PASS;
action_order_sigs[1] = ACTION_DROP;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
return res;
}
/**
* \test Check that we load a valid config
*/
int UtilActionTest06(void)
{
int res = 1;
char config[] = "\
%YAML 1.1\n\
---\n\
action-order:\n\
- alert\n\
- drop\n\
- reject\n\
- pass\n";
ConfCreateContextBackup();
ConfInit();
ConfYamlLoadString(config, strlen(config));
ActionInitConfig();
if (action_order_sigs[0] != ACTION_ALERT ||
action_order_sigs[1] != ACTION_DROP ||
action_order_sigs[2] != ACTION_REJECT ||
action_order_sigs[3] != ACTION_PASS)
{
res = 0;
}
ConfRestoreContextBackup();
/* Restore default values */
action_order_sigs[0] = ACTION_PASS;
action_order_sigs[1] = ACTION_DROP;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
return res;
}
/**
* \test Check that we load a valid config
*/
int UtilActionTest07(void)
{
int res = 1;
char config[] = "\
%YAML 1.1\n\
---\n\
action-order:\n\
- pass\n\
- alert\n\
- drop\n\
- reject\n";
ConfCreateContextBackup();
ConfInit();
ConfYamlLoadString(config, strlen(config));
ActionInitConfig();
if (action_order_sigs[0] != ACTION_PASS ||
action_order_sigs[1] != ACTION_ALERT ||
action_order_sigs[2] != ACTION_DROP ||
action_order_sigs[3] != ACTION_REJECT)
{
res = 0;
}
ConfRestoreContextBackup();
/* Restore default values */
action_order_sigs[0] = ACTION_PASS;
action_order_sigs[1] = ACTION_DROP;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
return res;
}
/**
* \test Check that we handle the "pass" action
* correctly at the IP Only engine in the default case
*/
int UtilActionTest08(void)
{
int res = 0;
uint8_t *buf = (uint8_t *)"Hi all!";
uint16_t buflen = strlen((char *)buf);
Packet *p[3];
p[0] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.5", "192.168.1.1",
41424, 80);
p[1] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.1", "192.168.1.5",
80, 41424);
p[2] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.5", "192.168.1.1",
41424, 80);
if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
goto end;
char *sigs[3];
sigs[0]= "alert ip any any -> any any (msg:\"sig 1\"; sid:1;)";
sigs[1]= "pass ip 192.168.1.1 80 -> any any (msg:\"sig 2\"; sid:2;)";
sigs[2]= "alert ip any any -> any any (msg:\"sig 3\"; sid:3;)";
uint32_t sid[3] = {1, 2, 3};
uint32_t results[3][3] = {
{1, 0, 1},
{0, 0, 0},
{1, 0, 1} };
/* This means that with the second packet, the results will be
* all ({0,0,0}) since, we should match the "pass" rule first
*/
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto cleanup;
de_ctx->flags |= DE_QUIET;
if (UTHAppendSigs(de_ctx, sigs, 3) == 0)
goto cleanup;
SCSigRegisterSignatureOrderingFuncs(de_ctx);
SCSigOrderSignatures(de_ctx);
Signature *s = de_ctx->sig_list;
uint16_t sig_id = 0;
/* Assing the internal id after sorting, so the IP Only engine
* process them in order too */
while (s != NULL) {
s->num = sig_id++;
s = s->next;
}
de_ctx->signum = sig_id;
res = UTHMatchPacketsWithResults(de_ctx, p, 3, sid, (uint32_t *) results, 3);
cleanup:
UTHFreePackets(p, 3);
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
}
end:
return res;
}
/**
* \test Check that we handle the "pass" action
* correctly at the IP Only engine with more
* prio to drop
*/
int UtilActionTest09(void)
{
int res = 1;
uint8_t *buf = (uint8_t *)"Hi all!";
uint16_t buflen = strlen((char *)buf);
Packet *p[3];
action_order_sigs[0] = ACTION_DROP;
action_order_sigs[1] = ACTION_PASS;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
p[0] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.5", "192.168.1.1",
41424, 80);
p[1] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.1", "192.168.1.5",
80, 41424);
p[2] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.5", "192.168.1.1",
41424, 80);
if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
goto end;
char *sigs[3];
sigs[0]= "alert ip any any -> any any (msg:\"sig 1\"; sid:1;)";
sigs[1]= "pass ip 192.168.1.1 80 -> any any (msg:\"sig 2\"; sid:2;)";
sigs[2]= "drop ip any any -> any any (msg:\"sig 3\"; sid:3;)";
uint32_t sid[3] = {1, 2, 3};
uint32_t results[3][3] = {
{1, 0, 1},
{0, 0, 1},
{1, 0, 1} };
/* This means that with the second packet, the results will be
* all ({0,0,1}) since, we should match the "drop" rule first.
* Later the "pass" rule will avoid the "alert" rule match
*/
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto cleanup;
de_ctx->flags |= DE_QUIET;
if (UTHAppendSigs(de_ctx, sigs, 3) == 0)
goto cleanup;
SCSigRegisterSignatureOrderingFuncs(de_ctx);
SCSigOrderSignatures(de_ctx);
Signature *s = de_ctx->sig_list;
uint16_t sig_id = 0;
/* Assing the internal id after sorting, so the IP Only engine
* process them in order too */
while (s != NULL) {
s->num = sig_id++;
s = s->next;
}
de_ctx->signum = sig_id;
res = UTHMatchPacketsWithResults(de_ctx, p, 3, sid, (uint32_t *) results, 3);
cleanup:
UTHFreePackets(p, 3);
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
}
end:
/* Restore default values */
action_order_sigs[0] = ACTION_PASS;
action_order_sigs[1] = ACTION_DROP;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
return res;
}
/**
* \test Check that we handle the "pass" action
* correctly at the detection engine in the default case
*/
int UtilActionTest10(void)
{
int res = 0;
uint8_t *buf = (uint8_t *)"Hi all!";
uint16_t buflen = strlen((char *)buf);
uint8_t *buf2 = (uint8_t *)"wo!";
uint16_t buflen2 = strlen((char *)buf2);
Packet *p[3];
p[0] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.5", "192.168.1.1",
41424, 80);
p[1] = UTHBuildPacketReal((uint8_t *)buf2, buflen2, IPPROTO_TCP,
"192.168.1.1", "192.168.1.5",
80, 41424);
p[2] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.5", "192.168.1.1",
41424, 80);
if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
goto end;
char *sigs[3];
sigs[0]= "alert ip any any -> any any (msg:\"sig 1\"; content:\"Hi all\"; sid:1;)";
sigs[1]= "pass ip any any -> any any (msg:\"sig 2\"; content:\"wo\"; sid:2;)";
sigs[2]= "alert ip any any -> any any (msg:\"sig 3\"; content:\"Hi all\"; sid:3;)";
uint32_t sid[3] = {1, 2, 3};
uint32_t results[3][3] = {
{1, 0, 1},
{0, 0, 0},
{1, 0, 1} };
/* This means that with the second packet, the results will be
* all ({0,0,0}) since, we should match the "pass" rule first
*/
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto cleanup;
de_ctx->flags |= DE_QUIET;
if (UTHAppendSigs(de_ctx, sigs, 3) == 0)
goto cleanup;
SCSigRegisterSignatureOrderingFuncs(de_ctx);
SCSigOrderSignatures(de_ctx);
Signature *s = de_ctx->sig_list;
uint16_t sig_id = 0;
/* Assing the internal id after sorting, so the IP Only engine
* process them in order too */
while (s != NULL) {
s->num = sig_id++;
s = s->next;
}
de_ctx->signum = sig_id;
res = UTHMatchPacketsWithResults(de_ctx, p, 3, sid, (uint32_t *) results, 3);
cleanup:
UTHFreePackets(p, 3);
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
}
end:
return res;
}
/**
* \test Check that we handle the "pass" action
* correctly at the detection engine with more
* prio to drop
*/
int UtilActionTest11(void)
{
int res = 1;
uint8_t *buf = (uint8_t *)"Hi all!";
uint16_t buflen = strlen((char *)buf);
uint8_t *buf2 = (uint8_t *)"Hi all wo!";
uint16_t buflen2 = strlen((char *)buf2);
Packet *p[3];
action_order_sigs[0] = ACTION_DROP;
action_order_sigs[1] = ACTION_PASS;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
p[0] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.5", "192.168.1.1",
41424, 80);
p[1] = UTHBuildPacketReal((uint8_t *)buf2, buflen2, IPPROTO_TCP,
"192.168.1.1", "192.168.1.5",
80, 41424);
p[2] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.5", "192.168.1.1",
41424, 80);
if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
goto end;
char *sigs[3];
sigs[0]= "alert tcp any any -> any any (msg:\"sig 1\"; content:\"Hi all\"; sid:1;)";
sigs[1]= "pass tcp any any -> any any (msg:\"sig 2\"; content:\"wo\"; sid:2;)";
sigs[2]= "drop tcp any any -> any any (msg:\"sig 3\"; content:\"Hi all\"; sid:3;)";
uint32_t sid[3] = {1, 2, 3};
uint32_t results[3][3] = {
{1, 0, 1},
{0, 0, 1},
{1, 0, 1} };
/* This means that with the second packet, the results will be
* all ({0,0,1}) since, we should match the "drop" rule first.
* Later the "pass" rule will avoid the "alert" rule match
*/
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto cleanup;
de_ctx->flags |= DE_QUIET;
if (UTHAppendSigs(de_ctx, sigs, 3) == 0)
goto cleanup;
SCSigRegisterSignatureOrderingFuncs(de_ctx);
SCSigOrderSignatures(de_ctx);
Signature *s = de_ctx->sig_list;
uint16_t sig_id = 0;
/* Assing the internal id after sorting, so the IP Only engine
* process them in order too */
while (s != NULL) {
s->num = sig_id++;
s = s->next;
}
de_ctx->signum = sig_id;
res = UTHMatchPacketsWithResults(de_ctx, p, 3, sid, (uint32_t *) results, 3);
cleanup:
UTHFreePackets(p, 3);
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
}
end:
/* Restore default values */
action_order_sigs[0] = ACTION_PASS;
action_order_sigs[1] = ACTION_DROP;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
return res;
}
/**
* \test Check that we handle the "pass" action
* correctly at the detection engine in the default case
*/
int UtilActionTest12(void)
{
int res = 0;
uint8_t *buf = (uint8_t *)"Hi all!";
uint16_t buflen = strlen((char *)buf);
Packet *p[3];
p[0] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.5", "192.168.1.1",
41424, 80);
p[1] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.1", "192.168.1.5",
80, 41424);
p[2] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.5", "192.168.1.1",
41424, 80);
if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
goto end;
char *sigs[3];
sigs[0]= "alert ip any any -> any any (msg:\"sig 1\"; sid:1;)";
sigs[1]= "pass ip any any -> any any (msg:\"Testing normal 2\"; sid:2;)";
sigs[2]= "alert ip any any -> any any (msg:\"sig 3\"; sid:3;)";
uint32_t sid[3] = {1, 2, 3};
uint32_t results[3][3] = {
{0, 0, 0},
{0, 0, 0},
{0, 0, 0} };
/* All should match the 3 sigs, but the action pass has prio */
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto cleanup;
de_ctx->flags |= DE_QUIET;
if (UTHAppendSigs(de_ctx, sigs, 3) == 0)
goto cleanup;
SCSigRegisterSignatureOrderingFuncs(de_ctx);
SCSigOrderSignatures(de_ctx);
Signature *s = de_ctx->sig_list;
uint16_t sig_id = 0;
/* Assing the internal id after sorting, so the IP Only engine
* process them in order too */
while (s != NULL) {
s->num = sig_id++;
s = s->next;
}
de_ctx->signum = sig_id;
res = UTHMatchPacketsWithResults(de_ctx, p, 3, sid, (uint32_t *) results, 3);
cleanup:
UTHFreePackets(p, 3);
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
}
end:
return res;
}
/**
* \test Check that we handle the "pass" action
* correctly at the detection engine with more
* prio to drop
*/
int UtilActionTest13(void)
{
int res = 1;
uint8_t *buf = (uint8_t *)"Hi all!";
uint16_t buflen = strlen((char *)buf);
Packet *p[3];
action_order_sigs[0] = ACTION_DROP;
action_order_sigs[1] = ACTION_PASS;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
p[0] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.5", "192.168.1.1",
41424, 80);
p[1] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.1", "192.168.1.5",
80, 41424);
p[2] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.5", "192.168.1.1",
41424, 80);
if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
goto end;
char *sigs[3];
sigs[0]= "alert tcp any any -> any any (msg:\"sig 1\"; content:\"Hi all\"; sid:1;)";
sigs[1]= "pass tcp any any -> any any (msg:\"sig 2\"; content:\"Hi all\"; sid:2;)";
sigs[2]= "drop tcp any any -> any any (msg:\"sig 3\"; content:\"Hi all\"; sid:3;)";
uint32_t sid[3] = {1, 2, 3};
uint32_t results[3][3] = {
{0, 0, 1},
{0, 0, 1},
{0, 0, 1} };
/* All the patckets should match the 3 sigs. As drop has more
* priority than pass, it should alert on each packet */
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto cleanup;
de_ctx->flags |= DE_QUIET;
if (UTHAppendSigs(de_ctx, sigs, 3) == 0)
goto cleanup;
SCSigRegisterSignatureOrderingFuncs(de_ctx);
SCSigOrderSignatures(de_ctx);
Signature *s = de_ctx->sig_list;
uint16_t sig_id = 0;
/* Assing the internal id after sorting, so the IP Only engine
* process them in order too */
while (s != NULL) {
s->num = sig_id++;
s = s->next;
}
de_ctx->signum = sig_id;
res = UTHMatchPacketsWithResults(de_ctx, p, 3, sid, (uint32_t *) results, 3);
cleanup:
UTHFreePackets(p, 3);
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
}
end:
/* Restore default values */
action_order_sigs[0] = ACTION_PASS;
action_order_sigs[1] = ACTION_DROP;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
return res;
}
/**
* \test Check that we handle the "pass" action
* correctly at the detection engine with more
* prio to drop and alert
*/
int UtilActionTest14(void)
{
int res = 1;
uint8_t *buf = (uint8_t *)"Hi all!";
uint16_t buflen = strlen((char *)buf);
Packet *p[3];
action_order_sigs[0] = ACTION_DROP;
action_order_sigs[1] = ACTION_ALERT;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_PASS;
p[0] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.5", "192.168.1.1",
41424, 80);
p[1] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.1", "192.168.1.5",
80, 41424);
p[2] = UTHBuildPacketReal((uint8_t *)buf, buflen, IPPROTO_TCP,
"192.168.1.5", "192.168.1.1",
41424, 80);
if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
goto end;
char *sigs[3];
sigs[0]= "alert tcp any any -> any any (msg:\"sig 1\"; content:\"Hi all\"; sid:1;)";
sigs[1]= "pass tcp any any -> any any (msg:\"sig 2\"; content:\"Hi all\"; sid:2;)";
sigs[2]= "drop tcp any any -> any any (msg:\"sig 3\"; content:\"Hi all\"; sid:3;)";
uint32_t sid[3] = {1, 2, 3};
uint32_t results[3][3] = {
{1, 0, 1},
{1, 0, 1},
{1, 0, 1} };
/* All the patckets should match the 3 sigs. As drop
* and alert have more priority than pass, both should
* alert on each packet */
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto cleanup;
de_ctx->flags |= DE_QUIET;
if (UTHAppendSigs(de_ctx, sigs, 3) == 0)
goto cleanup;
SCSigRegisterSignatureOrderingFuncs(de_ctx);
SCSigOrderSignatures(de_ctx);
Signature *s = de_ctx->sig_list;
uint16_t sig_id = 0;
/* Assing the internal id after sorting, so the IP Only engine
* process them in order too */
while (s != NULL) {
s->num = sig_id++;
s = s->next;
}
de_ctx->signum = sig_id;
res = UTHMatchPacketsWithResults(de_ctx, p, 3, sid, (uint32_t *) results, 3);
cleanup:
UTHFreePackets(p, 3);
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
}
end:
/* Restore default values */
action_order_sigs[0] = ACTION_PASS;
action_order_sigs[1] = ACTION_DROP;
action_order_sigs[2] = ACTION_REJECT;
action_order_sigs[3] = ACTION_ALERT;
return res;
}
#endif
/* Register unittests */
void UtilActionRegisterTests(void) {
#ifdef UNITTESTS
/* Generic tests */
UtRegisterTest("UtilActionTest01", UtilActionTest01, 1);
UtRegisterTest("UtilActionTest02", UtilActionTest02, 1);
UtRegisterTest("UtilActionTest02", UtilActionTest02, 1);
UtRegisterTest("UtilActionTest03", UtilActionTest03, 1);
UtRegisterTest("UtilActionTest04", UtilActionTest04, 1);
UtRegisterTest("UtilActionTest05", UtilActionTest05, 1);
UtRegisterTest("UtilActionTest06", UtilActionTest06, 1);
UtRegisterTest("UtilActionTest07", UtilActionTest07, 1);
UtRegisterTest("UtilActionTest08", UtilActionTest08, 1);
UtRegisterTest("UtilActionTest09", UtilActionTest09, 1);
UtRegisterTest("UtilActionTest10", UtilActionTest10, 1);
UtRegisterTest("UtilActionTest11", UtilActionTest11, 1);
UtRegisterTest("UtilActionTest12", UtilActionTest12, 1);
UtRegisterTest("UtilActionTest13", UtilActionTest13, 1);
UtRegisterTest("UtilActionTest15", UtilActionTest13, 1);
#endif
}

@ -0,0 +1,12 @@
/**
* Copyright(c) 2009 Open Information Security Foundation.
* \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
*/
#ifndef __ACTION_ORDER_H__
#define __ACTION_ORDER_H__
#include "suricata-common.h"
void ActionInitConfig();
uint8_t ActionOrderVal(uint8_t);
void UtilActionRegisterTests(void);
#endif /* __ACTION_ORDER_H__ */

@ -42,6 +42,7 @@ const char * SCErrorToString(SCError err)
switch (err) {
CASE_CODE (SC_OK);
CASE_CODE (SC_ERR_MEM_ALLOC);
CASE_CODE (SC_ERR_ACTION_ORDER);
CASE_CODE (SC_ERR_PCRE_MATCH);
CASE_CODE (SC_ERR_PCRE_GET_SUBSTRING);
CASE_CODE (SC_ERR_PCRE_COMPILE);

@ -30,6 +30,7 @@ typedef enum {
SC_OK,
SC_ERR_MEM_ALLOC,
SC_ERR_PCRE_MATCH,
SC_ERR_ACTION_ORDER,
SC_ERR_PCRE_GET_SUBSTRING,
SC_ERR_PCRE_COMPILE,
SC_ERR_PCRE_STUDY,

@ -5,6 +5,15 @@
# conservative 50.
#max-pending-packets: 50
# Set the order of alerts bassed on actions
# The default order is pass, drop, reject, alert
action-order:
- pass
- drop
- reject
- alert
# The default logging directory. Any log or output file will be
# placed here if its not specified with a full path name. This can be
# overridden with the -l command line parameter.

Loading…
Cancel
Save