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 */
|
||
|
}
|
||