Add pcre negate support.

remotes/origin/master-1.0.x
Victor Julien 16 years ago
parent 1d553c940b
commit ef6ab4efa0

@ -113,6 +113,8 @@ error:
int DetectPcreMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) int DetectPcreMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m)
{ {
SCEnter();
#define MAX_SUBSTRINGS 30 #define MAX_SUBSTRINGS 30
int ret = 0; int ret = 0;
int ov[MAX_SUBSTRINGS]; int ov[MAX_SUBSTRINGS];
@ -120,7 +122,7 @@ int DetectPcreMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, S
uint16_t len = 0; uint16_t len = 0;
if (p->payload_len == 0) if (p->payload_len == 0)
return 0; SCReturnInt(0);
DetectPcreData *pe = (DetectPcreData *)m->ctx; DetectPcreData *pe = (DetectPcreData *)m->ctx;
if (s->flags & SIG_FLAG_RECURSIVE) { if (s->flags & SIG_FLAG_RECURSIVE) {
@ -130,7 +132,7 @@ int DetectPcreMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, S
ptr = det_ctx->pkt_ptr; ptr = det_ctx->pkt_ptr;
len = p->payload_len - det_ctx->pkt_off; len = p->payload_len - det_ctx->pkt_off;
if (ptr == NULL || len == 0) if (ptr == NULL || len == 0)
return 0; SCReturnInt(0);
} else { } else {
ptr = p->payload; ptr = p->payload;
len = p->payload_len; len = p->payload_len;
@ -139,73 +141,88 @@ int DetectPcreMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, S
//printf("DetectPcre: ptr %p, len %" PRIu32 "\n", ptr, len); //printf("DetectPcre: ptr %p, len %" PRIu32 "\n", ptr, len);
ret = pcre_exec(pe->re, pe->sd, (char *)ptr, len, 0, 0, ov, MAX_SUBSTRINGS); ret = pcre_exec(pe->re, pe->sd, (char *)ptr, len, 0, 0, ov, MAX_SUBSTRINGS);
if (ret >= 0) { SCLogDebug("ret %d (negating %s)", ret, pe->negate ? "set" : "not set");
if (ret > 1 && pe->capidx != 0) {
const char *str_ptr; if (ret == PCRE_ERROR_NOMATCH) {
ret = pcre_get_substring((char *)ptr, ov, MAX_SUBSTRINGS, 1, &str_ptr); if (pe->negate == 1) {
if (ret) { /* regex didn't match with negate option means we consider it a match */
if (strcmp(pe->capname,"http_uri") == 0) { ret = 1;
p->http_uri.raw[det_ctx->pkt_cnt] = (uint8_t *)str_ptr; } else {
p->http_uri.raw_size[det_ctx->pkt_cnt] = ret; ret = 0;
p->http_uri.cnt = det_ctx->pkt_cnt + 1; }
} else if (ret >= 0) {
/* count how many uri's we handle for stats */ if (pe->negate == 1) {
det_ctx->uris++; /* regex matched but we're negated, so not considering it a match */
ret = 0;
//printf("DetectPcre: URI det_ctx->sgh %p, det_ctx->mcu %p\n", det_ctx->sgh, det_ctx->mcu); } else {
//PrintRawUriFp(stdout,p->http_uri.raw[det_ctx->pkt_cnt],p->http_uri.raw_size[det_ctx->pkt_cnt]); /* regex matched and we're not negated, considering it a match */
//printf(" (pkt_cnt %" PRIu32 ", mcu %p)\n", det_ctx->pkt_cnt, det_ctx->mcu); if (ret > 1 && pe->capidx != 0) {
const char *str_ptr;
/* don't bother scanning if we don't have a pattern matcher ctx ret = pcre_get_substring((char *)ptr, ov, MAX_SUBSTRINGS, 1, &str_ptr);
* which means we don't have uricontent sigs */ if (ret) {
if (det_ctx->sgh->mpm_uri_ctx != NULL) { if (strcmp(pe->capname,"http_uri") == 0) {
if (det_ctx->sgh->mpm_uricontent_maxlen <= p->http_uri.raw_size[det_ctx->pkt_cnt]) { p->http_uri.raw[det_ctx->pkt_cnt] = (uint8_t *)str_ptr;
if (det_ctx->sgh->mpm_uricontent_maxlen == 1) det_ctx->pkts_uri_scanned1++; p->http_uri.raw_size[det_ctx->pkt_cnt] = ret;
else if (det_ctx->sgh->mpm_uricontent_maxlen == 2) det_ctx->pkts_uri_scanned2++; p->http_uri.cnt = det_ctx->pkt_cnt + 1;
else if (det_ctx->sgh->mpm_uricontent_maxlen == 3) det_ctx->pkts_uri_scanned3++;
else if (det_ctx->sgh->mpm_uricontent_maxlen == 4) det_ctx->pkts_uri_scanned4++; /* count how many uri's we handle for stats */
else det_ctx->pkts_uri_scanned++; det_ctx->uris++;
det_ctx->pmq.mode = PMQ_MODE_SCAN; //printf("DetectPcre: URI det_ctx->sgh %p, det_ctx->mcu %p\n", det_ctx->sgh, det_ctx->mcu);
ret = mpm_table[det_ctx->sgh->mpm_uri_ctx->mpm_type].Scan(det_ctx->sgh->mpm_uri_ctx, &det_ctx->mtcu, &det_ctx->pmq, p->http_uri.raw[det_ctx->pkt_cnt], p->http_uri.raw_size[det_ctx->pkt_cnt]); //PrintRawUriFp(stdout,p->http_uri.raw[det_ctx->pkt_cnt],p->http_uri.raw_size[det_ctx->pkt_cnt]);
if (ret > 0) { //printf(" (pkt_cnt %" PRIu32 ", mcu %p)\n", det_ctx->pkt_cnt, det_ctx->mcu);
if (det_ctx->sgh->mpm_uricontent_maxlen == 1) det_ctx->pkts_uri_searched1++;
else if (det_ctx->sgh->mpm_uricontent_maxlen == 2) det_ctx->pkts_uri_searched2++; /* don't bother scanning if we don't have a pattern matcher ctx
else if (det_ctx->sgh->mpm_uricontent_maxlen == 3) det_ctx->pkts_uri_searched3++; * which means we don't have uricontent sigs */
else if (det_ctx->sgh->mpm_uricontent_maxlen == 4) det_ctx->pkts_uri_searched4++; if (det_ctx->sgh->mpm_uri_ctx != NULL) {
else det_ctx->pkts_uri_searched++; if (det_ctx->sgh->mpm_uricontent_maxlen <= p->http_uri.raw_size[det_ctx->pkt_cnt]) {
if (det_ctx->sgh->mpm_uricontent_maxlen == 1) det_ctx->pkts_uri_scanned1++;
det_ctx->pmq.mode = PMQ_MODE_SEARCH; else if (det_ctx->sgh->mpm_uricontent_maxlen == 2) det_ctx->pkts_uri_scanned2++;
ret += mpm_table[det_ctx->sgh->mpm_uri_ctx->mpm_type].Search(det_ctx->sgh->mpm_uri_ctx, &det_ctx->mtcu, &det_ctx->pmq, p->http_uri.raw[det_ctx->pkt_cnt], p->http_uri.raw_size[det_ctx->pkt_cnt]); else if (det_ctx->sgh->mpm_uricontent_maxlen == 3) det_ctx->pkts_uri_scanned3++;
else if (det_ctx->sgh->mpm_uricontent_maxlen == 4) det_ctx->pkts_uri_scanned4++;
/* indicate to uricontent that we have a uri, else det_ctx->pkts_uri_scanned++;
* we scanned it _AND_ we found pattern matches. */
det_ctx->de_have_httpuri = 1; det_ctx->pmq.mode = PMQ_MODE_SCAN;
ret = mpm_table[det_ctx->sgh->mpm_uri_ctx->mpm_type].Scan(det_ctx->sgh->mpm_uri_ctx, &det_ctx->mtcu, &det_ctx->pmq, p->http_uri.raw[det_ctx->pkt_cnt], p->http_uri.raw_size[det_ctx->pkt_cnt]);
if (ret > 0) {
if (det_ctx->sgh->mpm_uricontent_maxlen == 1) det_ctx->pkts_uri_searched1++;
else if (det_ctx->sgh->mpm_uricontent_maxlen == 2) det_ctx->pkts_uri_searched2++;
else if (det_ctx->sgh->mpm_uricontent_maxlen == 3) det_ctx->pkts_uri_searched3++;
else if (det_ctx->sgh->mpm_uricontent_maxlen == 4) det_ctx->pkts_uri_searched4++;
else det_ctx->pkts_uri_searched++;
det_ctx->pmq.mode = PMQ_MODE_SEARCH;
ret += mpm_table[det_ctx->sgh->mpm_uri_ctx->mpm_type].Search(det_ctx->sgh->mpm_uri_ctx, &det_ctx->mtcu, &det_ctx->pmq, p->http_uri.raw[det_ctx->pkt_cnt], p->http_uri.raw_size[det_ctx->pkt_cnt]);
/* indicate to uricontent that we have a uri,
* we scanned it _AND_ we found pattern matches. */
det_ctx->de_have_httpuri = 1;
}
} }
} }
} } else {
} else { if (pe->flags & DETECT_PCRE_CAPTURE_PKT) {
if (pe->flags & DETECT_PCRE_CAPTURE_PKT) { PktVarAdd(p, pe->capname, (uint8_t *)str_ptr, ret);
PktVarAdd(p, pe->capname, (uint8_t *)str_ptr, ret); } else if (pe->flags & DETECT_PCRE_CAPTURE_FLOW) {
} else if (pe->flags & DETECT_PCRE_CAPTURE_FLOW) { FlowVarAddStr(p->flow, pe->capidx, (uint8_t *)str_ptr, ret);
FlowVarAddStr(p->flow, pe->capidx, (uint8_t *)str_ptr, ret); }
} }
} }
} }
} /* update ptrs for pcre RELATIVE */
det_ctx->pkt_ptr = ptr+ov[1];
det_ctx->pkt_off = (ptr+ov[1]) - p->payload;
//printf("DetectPcre: post match: t->pkt_ptr %p t->pkt_off %" PRIu32 "\n", t->pkt_ptr, t->pkt_off);
/* update ptrs for pcre RELATIVE */ ret = 1;
det_ctx->pkt_ptr = ptr+ov[1]; }
det_ctx->pkt_off = (ptr+ov[1]) - p->payload;
//printf("DetectPcre: post match: t->pkt_ptr %p t->pkt_off %" PRIu32 "\n", t->pkt_ptr, t->pkt_off);
ret = 1;
} else { } else {
SCLogDebug("pcre had matching error");
ret = 0; ret = 0;
} }
//printf("DetectPcreMatch: ret %" PRId32 "\n", ret); SCReturnInt(ret);
return ret;
} }
DetectPcreData *DetectPcreParse (char *regexstr) DetectPcreData *DetectPcreParse (char *regexstr)
@ -220,7 +237,20 @@ DetectPcreData *DetectPcreParse (char *regexstr)
int ret = 0, res = 0; int ret = 0, res = 0;
int ov[MAX_SUBSTRINGS]; int ov[MAX_SUBSTRINGS];
ret = pcre_exec(parse_regex, parse_regex_study, regexstr, strlen(regexstr), 0, 0, ov, MAX_SUBSTRINGS); uint16_t slen = strlen(regexstr);
uint16_t pos = 0;
uint8_t negate = 0;
while (pos < slen && isspace(regexstr[pos])) {
pos++;
}
if (regexstr[pos] == '!') {
negate = 1;
pos++;
}
ret = pcre_exec(parse_regex, parse_regex_study, regexstr+pos, slen-pos, 0, 0, ov, MAX_SUBSTRINGS);
if (ret < 0) { if (ret < 0) {
goto error; goto error;
} }
@ -252,6 +282,9 @@ DetectPcreData *DetectPcreParse (char *regexstr)
} }
memset(pd, 0, sizeof(DetectPcreData)); memset(pd, 0, sizeof(DetectPcreData));
if (negate)
pd->negate = 1;
if (op != NULL) { if (op != NULL) {
while (*op) { while (*op) {
SCLogDebug("regex option %c", *op); SCLogDebug("regex option %c", *op);
@ -759,7 +792,7 @@ static int DetectPcreTestSig03Real(int mpm_type) {
de_ctx->mpm_matcher = mpm_type; de_ctx->mpm_matcher = mpm_type;
de_ctx->flags |= DE_QUIET; de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP TEST\"; content:\"GET\"; pcre:\"!/two/\"; sid:1;)"); de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP TEST\"; content:\"GET\"; pcre:!\"/two/\"; sid:1;)");
if (de_ctx->sig_list == NULL) { if (de_ctx->sig_list == NULL) {
result = 0; result = 0;
goto end; goto end;

@ -28,6 +28,7 @@ typedef struct DetectPcreData_ {
int32_t distance; int32_t distance;
uint16_t flags; uint16_t flags;
uint8_t negate;
char *capname; char *capname;
uint16_t capidx; uint16_t capidx;

Loading…
Cancel
Save