diff --git a/src/detect-content.c b/src/detect-content.c index 043ec2bf33..ab5c88538b 100644 --- a/src/detect-content.c +++ b/src/detect-content.c @@ -71,6 +71,35 @@ uint32_t DetectContentMaxId(DetectEngineCtx *de_ctx) { return de_ctx->content_max_id; } +#ifdef DEBUG +static void DetectContentDebugPrint(DetectContentData *co) { + char buf[2048] = ""; + char tmp[4] = ""; + uint16_t u = 0; + + for (u = 0; u < co->content_len; u++) { + if (isprint((char)co->content[u])) { + snprintf(tmp,sizeof(tmp),"%c", (char)co->content[u]); + } else { + snprintf(tmp,sizeof(tmp),"\\%02x", co->content[u]); + } + strncat(buf,tmp,sizeof(buf)); + } + + SCLogDebug("content \"%s\"",buf); +} + +static void DetectContentPrintMatches(DetectEngineThreadCtx *det_ctx, DetectContentData *co) { + DetectContentDebugPrint(co); + SCLogDebug("matched %" PRIu32 " time(s) at offsets: ", det_ctx->mtc.match[co->id].len); + + MpmMatch *tmpm = NULL; + for (tmpm = det_ctx->mtc.match[co->id].top; tmpm != NULL; tmpm = tmpm->next) { + SCLogDebug("%" PRIu32 " ", tmpm->offset); + } +} +#endif + static inline int TestOffsetDepth(MpmMatch *m, DetectContentData *co, uint16_t pktoff) { if (m->offset >= pktoff) { @@ -126,13 +155,26 @@ TestOffsetDepth(MpmMatch *m, DetectContentData *co, uint16_t pktoff) { static inline int TestWithinDistanceOffsetDepth(ThreadVars *t, DetectEngineThreadCtx *det_ctx, MpmMatch *m, SigMatch *sm, SigMatch *nsm, uint16_t pktoff) { - if (nsm == NULL) + if (nsm == NULL) { + SCLogDebug("No next sigmatch, all sigmatches matched."); return 1; + } /** content match of current pattern */ DetectContentData *co = (DetectContentData *)sm->ctx; + + if (!(co->flags & DETECT_CONTENT_DISTANCE_NEXT) && !(co->flags & DETECT_CONTENT_WITHIN_NEXT)) { + SCLogDebug("Next content is does not need distance/within checking."); + return 1; + } + /** content match of next pattern */ DetectContentData *nco = (DetectContentData *)nsm->ctx; +#ifdef DEBUG + if (SCLogDebugEnabled()) { + DetectContentPrintMatches(det_ctx, nco); + } +#endif /** list of matches of the next pattern */ MpmMatch *nm = det_ctx->mtc.match[nco->id].top; @@ -178,8 +220,11 @@ TestWithinDistanceOffsetDepth(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Mpm (nco->within + co->content_len)); } } + } else { + SCLogDebug("pktoff %"PRIu16" > nm->offset %"PRIu32"", pktoff, nm->offset); } } + SCLogDebug("no match found, returning 0"); return 0; } @@ -188,12 +233,26 @@ DoDetectContent(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signat { int ret = 0; char match = 0; + uint16_t pkt_off = det_ctx->pkt_off; /* Get the top match, we already know we have one. */ MpmMatch *m = det_ctx->mtc.match[co->id].top; SCLogDebug("det_ctx->mtc.match[co->id].len %"PRIu32"", det_ctx->mtc.match[co->id].len); + /* reset de_checking_distancewithin */ + if (!(co->flags & DETECT_CONTENT_WITHIN) && + !(co->flags & DETECT_CONTENT_DISTANCE)) + { + det_ctx->de_checking_distancewithin = 0; + + /* only use pkt offset of previous matches + * on relative matches. */ + pkt_off = 0; + } + + SCLogDebug("using pkt_off %"PRIu16"", pkt_off); + /* if we have within or distance coming up next, check this match * for distance and/or within and check the rest of this match * chain as well. */ @@ -212,19 +271,22 @@ DoDetectContent(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signat for (; m != NULL; m = m->next) { /* first check our match for offset and depth */ - if (TestOffsetDepth(m, co, det_ctx->pkt_off) == 1) { + if (TestOffsetDepth(m, co, pkt_off) == 1) { SCLogDebug("TestOffsetDepth returned 1, for co->id %"PRIu32"", co->id); SigMatch *real_sm_next = DetectContentFindNextApplicableSM(sm->next); - ret = TestWithinDistanceOffsetDepth(t, det_ctx, m, sm, real_sm_next, det_ctx->pkt_off); + ret = TestWithinDistanceOffsetDepth(t, det_ctx, m, sm, real_sm_next, pkt_off); if (ret == 1) { SCLogDebug("TestWithinDistanceOffsetDepth returned 1"); det_ctx->pkt_ptr = p->payload + m->offset; - det_ctx->pkt_off = m->offset; + /* update both the local and ctx pkt_off */ + pkt_off = det_ctx->pkt_off = m->offset; match = 1; break; } + } else { + SCLogDebug("TestOffsetDepth returned 0, for co->id %"PRIu32"", co->id); } } @@ -318,16 +380,9 @@ int DetectContentMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p if (len == 0) return 0; -#if 0 +#ifdef DEBUG if (SCLogDebugEnabled()) { - SCLogDebug("content \""); PrintRawUriFp(stdout, co->content, co->content_len); - SCLogDebug("\" matched %" PRIu32 " time(s) at offsets: ", len); - - MpmMatch *tmpm = NULL; - for (tmpm = det_ctx->mtc.match[co->id].top; tmpm != NULL; tmpm = tmpm->next) { - SCLogDebug("%" PRIu32 " ", tmpm->offset); - } - SCLogDebug(""); + DetectContentPrintMatches(det_ctx, co); } #endif @@ -2262,6 +2317,24 @@ int DetectContentChunkMatchTest08() return DetectContentChunkMatchTestWrp(sig, 1); } +/** + * \test Check if we match contents that are in the payload + * but not in the same order as specified in the signature + */ +int DetectContentChunkMatchTest09() +{ + char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; " + " content:\"ent matches\"; " + " content:\"of splitted patterns between multiple\"; " + " within:38; distance:1; offset:47; depth:85; " + " content:\"chunks!\"; within: 8; distance:1; " + " depth:94; offset: 50; " + " content:\"Hi, this is a big test to chec\"; depth:36;" + " content:\"k cont\"; distance:0; within:6;" + " sid:1;)"; + return DetectContentChunkMatchTestWrp(sig, 1); +} + #endif /* UNITTESTS */ /** @@ -2294,5 +2367,6 @@ void DetectContentRegisterTests(void) { UtRegisterTest("DetectContentChunkMatchTest06", DetectContentChunkMatchTest06, 1); UtRegisterTest("DetectContentChunkMatchTest07", DetectContentChunkMatchTest07, 1); UtRegisterTest("DetectContentChunkMatchTest08", DetectContentChunkMatchTest08, 1); + UtRegisterTest("DetectContentChunkMatchTest09", DetectContentChunkMatchTest09, 1); #endif /* UNITTESTS */ }