From ef6ab4efa0d980c521550a53ece2f169d1fb48cf Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Thu, 31 Dec 2009 14:55:50 +0100 Subject: [PATCH] Add pcre negate support. --- src/detect-pcre.c | 153 ++++++++++++++++++++++++++++------------------ src/detect-pcre.h | 1 + 2 files changed, 94 insertions(+), 60 deletions(-) diff --git a/src/detect-pcre.c b/src/detect-pcre.c index 3ba2f3a8a7..bb3ff17cb9 100644 --- a/src/detect-pcre.c +++ b/src/detect-pcre.c @@ -113,6 +113,8 @@ error: int DetectPcreMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { + SCEnter(); + #define MAX_SUBSTRINGS 30 int ret = 0; int ov[MAX_SUBSTRINGS]; @@ -120,7 +122,7 @@ int DetectPcreMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, S uint16_t len = 0; if (p->payload_len == 0) - return 0; + SCReturnInt(0); DetectPcreData *pe = (DetectPcreData *)m->ctx; 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; len = p->payload_len - det_ctx->pkt_off; if (ptr == NULL || len == 0) - return 0; + SCReturnInt(0); } else { ptr = p->payload; 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); ret = pcre_exec(pe->re, pe->sd, (char *)ptr, len, 0, 0, ov, MAX_SUBSTRINGS); - if (ret >= 0) { - if (ret > 1 && pe->capidx != 0) { - const char *str_ptr; - ret = pcre_get_substring((char *)ptr, ov, MAX_SUBSTRINGS, 1, &str_ptr); - if (ret) { - if (strcmp(pe->capname,"http_uri") == 0) { - p->http_uri.raw[det_ctx->pkt_cnt] = (uint8_t *)str_ptr; - p->http_uri.raw_size[det_ctx->pkt_cnt] = ret; - p->http_uri.cnt = det_ctx->pkt_cnt + 1; - - /* count how many uri's we handle for stats */ - det_ctx->uris++; - - //printf("DetectPcre: URI det_ctx->sgh %p, det_ctx->mcu %p\n", det_ctx->sgh, det_ctx->mcu); - //PrintRawUriFp(stdout,p->http_uri.raw[det_ctx->pkt_cnt],p->http_uri.raw_size[det_ctx->pkt_cnt]); - //printf(" (pkt_cnt %" PRIu32 ", mcu %p)\n", det_ctx->pkt_cnt, det_ctx->mcu); - - /* don't bother scanning if we don't have a pattern matcher ctx - * which means we don't have uricontent sigs */ - if (det_ctx->sgh->mpm_uri_ctx != NULL) { - 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++; - else if (det_ctx->sgh->mpm_uricontent_maxlen == 2) det_ctx->pkts_uri_scanned2++; - 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++; - else det_ctx->pkts_uri_scanned++; - - 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; + SCLogDebug("ret %d (negating %s)", ret, pe->negate ? "set" : "not set"); + + if (ret == PCRE_ERROR_NOMATCH) { + if (pe->negate == 1) { + /* regex didn't match with negate option means we consider it a match */ + ret = 1; + } else { + ret = 0; + } + } else if (ret >= 0) { + if (pe->negate == 1) { + /* regex matched but we're negated, so not considering it a match */ + ret = 0; + } else { + /* regex matched and we're not negated, considering it a match */ + if (ret > 1 && pe->capidx != 0) { + const char *str_ptr; + ret = pcre_get_substring((char *)ptr, ov, MAX_SUBSTRINGS, 1, &str_ptr); + if (ret) { + if (strcmp(pe->capname,"http_uri") == 0) { + p->http_uri.raw[det_ctx->pkt_cnt] = (uint8_t *)str_ptr; + p->http_uri.raw_size[det_ctx->pkt_cnt] = ret; + p->http_uri.cnt = det_ctx->pkt_cnt + 1; + + /* count how many uri's we handle for stats */ + det_ctx->uris++; + + //printf("DetectPcre: URI det_ctx->sgh %p, det_ctx->mcu %p\n", det_ctx->sgh, det_ctx->mcu); + //PrintRawUriFp(stdout,p->http_uri.raw[det_ctx->pkt_cnt],p->http_uri.raw_size[det_ctx->pkt_cnt]); + //printf(" (pkt_cnt %" PRIu32 ", mcu %p)\n", det_ctx->pkt_cnt, det_ctx->mcu); + + /* don't bother scanning if we don't have a pattern matcher ctx + * which means we don't have uricontent sigs */ + if (det_ctx->sgh->mpm_uri_ctx != NULL) { + 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++; + else if (det_ctx->sgh->mpm_uricontent_maxlen == 2) det_ctx->pkts_uri_scanned2++; + 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++; + else det_ctx->pkts_uri_scanned++; + + 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 { - if (pe->flags & DETECT_PCRE_CAPTURE_PKT) { - PktVarAdd(p, pe->capname, (uint8_t *)str_ptr, ret); - } else if (pe->flags & DETECT_PCRE_CAPTURE_FLOW) { - FlowVarAddStr(p->flow, pe->capidx, (uint8_t *)str_ptr, ret); + } else { + if (pe->flags & DETECT_PCRE_CAPTURE_PKT) { + PktVarAdd(p, pe->capname, (uint8_t *)str_ptr, ret); + } else if (pe->flags & DETECT_PCRE_CAPTURE_FLOW) { + 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 */ - 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; + } - ret = 1; } else { + SCLogDebug("pcre had matching error"); ret = 0; } - //printf("DetectPcreMatch: ret %" PRId32 "\n", ret); - return ret; + SCReturnInt(ret); } DetectPcreData *DetectPcreParse (char *regexstr) @@ -220,7 +237,20 @@ DetectPcreData *DetectPcreParse (char *regexstr) int ret = 0, res = 0; 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) { goto error; } @@ -252,6 +282,9 @@ DetectPcreData *DetectPcreParse (char *regexstr) } memset(pd, 0, sizeof(DetectPcreData)); + if (negate) + pd->negate = 1; + if (op != NULL) { while (*op) { SCLogDebug("regex option %c", *op); @@ -759,7 +792,7 @@ static int DetectPcreTestSig03Real(int mpm_type) { de_ctx->mpm_matcher = mpm_type; 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) { result = 0; goto end; diff --git a/src/detect-pcre.h b/src/detect-pcre.h index 8fa4a2cc54..259f58d8a5 100644 --- a/src/detect-pcre.h +++ b/src/detect-pcre.h @@ -28,6 +28,7 @@ typedef struct DetectPcreData_ { int32_t distance; uint16_t flags; + uint8_t negate; char *capname; uint16_t capidx;