Bug #202 » 0001-implement-pcre-relative-matching-in-detect-engine-pa.patch
src/detect-engine-payload.c | ||
---|---|---|
#include "util-spm-bm.h"
|
||
#include "util-debug.h"
|
||
#include "util-print.h"
|
||
#include "pkt-var.h"
|
||
#include "flow-var.h"
|
||
#include "util-unittest.h"
|
||
#include "util-unittest-helper.h"
|
||
... | ... | |
{
|
||
SCEnter();
|
||
if (sm == NULL) {
|
||
int punt_matching = 0;
|
||
if (sm == NULL || payload_len == 0) {
|
||
SCReturnInt(0);
|
||
}
|
||
... | ... | |
SCReturnInt(1);
|
||
}
|
||
if (punt_matching == 1) {
|
||
SCReturnInt(0);
|
||
}
|
||
/* set the previous match offset to the start of this match + 1 */
|
||
prev_offset = (match_offset - (cd->content_len - 1));
|
||
SCLogDebug("trying to see if there is another match after prev_offset %"PRIu32, prev_offset);
|
||
... | ... | |
} while(1);
|
||
}
|
||
case DETECT_ISDATAAT:
|
||
{
|
||
SCLogDebug("inspecting isdataat");
|
||
... | ... | |
}
|
||
}
|
||
}
|
||
case DETECT_PCRE:
|
||
{
|
||
SCLogDebug("inspecting pcre");
|
||
int r = DetectPcrePayloadMatch(det_ctx, s, sm, p, f, payload, payload_len);
|
||
if (r == 1) {
|
||
goto match;
|
||
}
|
||
DetectPcreData *pd = (DetectPcreData *)sm->ctx;
|
||
/* search for our pattern, checking the matches recursively.
|
||
* if we match we look for the next SigMatch as well */
|
||
uint32_t offset = 0;
|
||
uint32_t prev_offset = 0; /**< used in recursive searching */
|
||
uint32_t prev_payload_offset = det_ctx->payload_offset;
|
||
#define MAX_SUBSTRINGS 30
|
||
int ov[MAX_SUBSTRINGS];
|
||
uint8_t *ptr = NULL;
|
||
uint16_t len = 0;
|
||
int ret = 0;
|
||
do {
|
||
if (s->flags & SIG_FLAG_RECURSIVE ||
|
||
pd->flags & DETECT_PCRE_RELATIVE) {
|
||
offset = prev_payload_offset;
|
||
} else {
|
||
offset = 0;
|
||
}
|
||
if (prev_offset != 0) {
|
||
offset = prev_offset;
|
||
}
|
||
ptr = payload + offset;
|
||
len = payload_len - offset;
|
||
/* run the actual pcre detection */
|
||
ret = pcre_exec(pd->re, pd->sd, (char *)ptr, len, 0, 0, ov,
|
||
MAX_SUBSTRINGS);
|
||
SCLogDebug("ret %d (negating %s)",
|
||
ret, pd->negate ? "set" : "not set");
|
||
if (ret == PCRE_ERROR_NOMATCH) {
|
||
if (pd->negate == 1) {
|
||
/* regex didn't match with negate option means we
|
||
* consider it a match */
|
||
SCReturnInt(1);
|
||
} else {
|
||
/* we have no matches here. if we don't get a pcre match
|
||
* here, it's pointless carrying our further matches */
|
||
punt_matching = 1;
|
||
SCReturnInt(0);
|
||
}
|
||
} else if (ret >= 0) {
|
||
if (pd->negate == 1) {
|
||
punt_matching = 1;
|
||
/* regex matched but we're negated, so not
|
||
* considering it a match */
|
||
SCReturnInt(0);
|
||
} else {
|
||
/* regex matched and we're not negated,
|
||
* considering it a match */
|
||
/* see if we need to do substring capturing. */
|
||
if (ret > 1 && pd->capidx != 0) {
|
||
const char *str_ptr;
|
||
ret = pcre_get_substring((char *)ptr, ov,
|
||
MAX_SUBSTRINGS, 1, &str_ptr);
|
||
if (ret) {
|
||
if (pd->flags & DETECT_PCRE_CAPTURE_PKT) {
|
||
/* any more indentation, and we'll
|
||
* reach the moon */
|
||
if (p != NULL) {
|
||
PktVarAdd(p, pd->capname,
|
||
(uint8_t *)str_ptr, ret);
|
||
}
|
||
} else if (pd->flags & DETECT_PCRE_CAPTURE_FLOW) {
|
||
if (f != NULL) {
|
||
/* flow will be locked be FlowVarAddStr */
|
||
FlowVarAddStr(f, pd->capidx,
|
||
(uint8_t *)str_ptr, ret);
|
||
}
|
||
}
|
||
} /* if (ret) */
|
||
} /* if (ret > 1 && pd->capidx != 0) */
|
||
/* update offset for pcre RELATIVE */
|
||
det_ctx->payload_offset = (ptr + ov[1]) - payload;
|
||
if ( !(pd->flags & DETECT_PCRE_RELATIVE_NEXT)) {
|
||
SCLogDebug("no relative match coming up, so this "
|
||
"is a match");
|
||
goto match;
|
||
}
|
||
SCReturnInt(0);
|
||
/* see if the next payload keywords match. If not, we will
|
||
* search for another occurence of this pcre and see
|
||
* if the others match, until we run out of matches */
|
||
int r = DoInspectPacketPayload(de_ctx, det_ctx, s,
|
||
sm->next, p, f,
|
||
payload, payload_len);
|
||
if (r == 1) {
|
||
SCReturnInt(1);
|
||
}
|
||
if (punt_matching == 1) {
|
||
SCReturnInt(0);
|
||
}
|
||
/* set the previous match offset to the start of this match + 1 */
|
||
prev_offset = (ptr + ov[0] + 1) - payload;
|
||
}
|
||
} else {
|
||
SCLogDebug("pcre had matching error");
|
||
punt_matching = 1;
|
||
SCReturnInt(0);
|
||
}
|
||
} while (1);
|
||
}
|
||
case DETECT_BYTETEST:
|
||
{
|
||
if (DetectBytetestDoMatch(det_ctx,s,sm,payload,payload_len) != 1) {
|
||
... | ... | |
goto match;
|
||
}
|
||
case DETECT_BYTEJUMP:
|
||
{
|
||
if (DetectBytejumpDoMatch(det_ctx,s,sm,payload,payload_len) != 1) {
|
||
... | ... | |
goto match;
|
||
}
|
||
/* we should never get here, but bail out just in case */
|
||
default:
|
||
{
|
||
... | ... | |
return result;
|
||
}
|
||
/**
|
||
* \test Test pcre recursive matching.
|
||
*/
|
||
static int PayloadTestSig08(void)
|
||
{
|
||
uint8_t *buf = (uint8_t *)"this is a super duper nova in super nova now";
|
||
uint16_t buflen = strlen((char *)buf);
|
||
Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
|
||
int result = 0;
|
||
char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
|
||
"pcre:/super/; content:nova; within:7; sid:1;)";
|
||
if (UTHPacketMatchSigMpm(p, sig, MPM_B2G) == 0) {
|
||
result = 0;
|
||
goto end;
|
||
}
|
||
result = 1;
|
||
end:
|
||
if (p != NULL)
|
||
UTHFreePacket(p);
|
||
return result;
|
||
}
|
||
#endif /* UNITTESTS */
|
||
void PayloadRegisterTests(void) {
|
||
... | ... | |
UtRegisterTest("PayloadTestSig05", PayloadTestSig05, 1);
|
||
UtRegisterTest("PayloadTestSig06", PayloadTestSig06, 1);
|
||
UtRegisterTest("PayloadTestSig07", PayloadTestSig07, 1);
|
||
UtRegisterTest("PayloadTestSig08", PayloadTestSig08, 1);
|
||
#endif /* UNITTESTS */
|
||
}
|