From 951b4d5cf40ca14f7ed5e713aad691edd8775cc9 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Fri, 6 Nov 2009 15:31:47 +0100 Subject: [PATCH] Fix within in some corner cases and add some more tests. --- src/detect-content.c | 74 +++++++++++++++++++++++++++----------------- src/detect.c | 61 ++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 29 deletions(-) diff --git a/src/detect-content.c b/src/detect-content.c index 91d6284fea..d5cb31de36 100644 --- a/src/detect-content.c +++ b/src/detect-content.c @@ -69,27 +69,35 @@ TestOffsetDepth(MpmMatch *m, DetectContentData *co, uint16_t pktoff) { if (co->depth == 0 || (co->depth && (m->offset+co->content_len) <= co->depth)) { - //printf("TestOffsetDepth: depth %" PRIu32 ", offset %" PRIu32 ", m->offset %" PRIu32 ", return 1\n", - // co->depth, co->offset, m->offset); + SCLogDebug("depth %" PRIu32 ", offset %" PRIu32 ", m->offset %" PRIu32 ", return 1", + co->depth, co->offset, m->offset); return 1; } } } - //printf("TestOffsetDepth: depth %" PRIu32 ", offset %" PRIu32 ", m->offset %" PRIu32 ", return 0\n", - // co->depth, co->offset, m->offset); + SCLogDebug("depth %" PRIu32 ", offset %" PRIu32 ", m->offset %" PRIu32 ", return 0", + co->depth, co->offset, m->offset); return 0; } -/* This function is called recursively (if nescessary) to be able - * to determine whether or not a chain of content matches connected - * with 'within' and 'distance' options fully matches. The reason it - * was done like this is to make sure we can handle partial matches - * that turn out to fail being followed by full matches later in the - * packet. This adds some runtime complexity however. */ +/** \brief test the within, distance, offset and depth of a match + * + * This function is called recursively (if nescessary) to be able + * to determine whether or not a chain of content matches connected + * with 'within' and 'distance' options fully matches. The reason it + * was done like this is to make sure we can handle partial matches + * that turn out to fail being followed by full matches later in the + * packet. This adds some runtime complexity however. + * + * \param t thread vars + * \param det_ctx thread local data of the detection engine ctx + * \param m match we are inspecting + * \param nsm sigmatch to work with + * \param pktoff packet offset + */ static inline int TestWithinDistanceOffsetDepth(ThreadVars *t, DetectEngineThreadCtx *det_ctx, MpmMatch *m, SigMatch *nsm, uint16_t pktoff) { - //printf("test_nextsigmatch m:%p, nsm:%p\n", m,nsm); if (nsm == NULL) return 1; @@ -97,35 +105,38 @@ TestWithinDistanceOffsetDepth(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Mpm MpmMatch *nm = det_ctx->mtc.match[co->id].top; for (; nm; nm = nm->next) { - //printf("TestWithinDistanceOffsetDepth: nm->offset %" PRIu32 ", m->offset %" PRIu32 ", pktoff %" PRIu32 "\n", nm->offset, m->offset, pktoff); + SCLogDebug("nm->offset %" PRIu32 ", m->offset %" PRIu32 ", pktoff %" PRIu32 "", nm->offset, m->offset, pktoff); + if (nm->offset >= pktoff) { if ((!(co->flags & DETECT_CONTENT_WITHIN) || (co->within > 0 && (nm->offset > m->offset) && - ((nm->offset - m->offset + co->content_len) <= co->within)))) + ((nm->offset - m->offset) <= co->within)))) { - //printf("TestWithinDistanceOffsetDepth: MATCH: %" PRIu32 " <= WITHIN(%" PRIu32 "), " - // "nm->offset %" PRIu32 ", m->offset %" PRIu32 "\n", nm->offset - m->offset + co->content_len, - // co->within, nm->offset, m->offset); + SCLogDebug("MATCH: %" PRIu32 " <= WITHIN(%" PRIu32 "), " + "nm->offset %" PRIu32 ", m->offset %" PRIu32 "", + nm->offset - m->offset, + co->within, nm->offset, m->offset); if (!(co->flags & DETECT_CONTENT_DISTANCE) || ((nm->offset > m->offset) && ((nm->offset - m->offset) >= co->distance))) { - //printf("TestWithinDistanceOffsetDepth: MATCH: %" PRIu32 " >= DISTANCE(%" PRIu32 "), " - // "nm->offset %" PRIu32 ", m->offset %" PRIu32 "\n", nm->offset - m->offset, - // co->distance, nm->offset, m->offset); + SCLogDebug("MATCH: %" PRIu32 " >= DISTANCE(%" PRIu32 "), " + "nm->offset %" PRIu32 ", m->offset %" PRIu32 "", + nm->offset - m->offset, co->distance, nm->offset, m->offset); if (TestOffsetDepth(nm, co, pktoff) == 1) { return TestWithinDistanceOffsetDepth(t, det_ctx, nm, nsm->next, pktoff); } } else { - //printf("TestWithinDistanceOffsetDepth: NO MATCH: %" PRIu32 " >= DISTANCE(%" PRIu32 "), " - // "nm->offset %" PRIu32 ", m->offset %" PRIu32 "\n", nm->offset - m->offset, - // co->distance, nm->offset, m->offset); + SCLogDebug("NO MATCH: %" PRIu32 " >= DISTANCE(%" PRIu32 "), " + "nm->offset %" PRIu32 ", m->offset %" PRIu32 "", + nm->offset - m->offset, co->distance, nm->offset, m->offset); } } else { - //printf("TestWithinDistanceOffsetDepth: NO MATCH: %" PRIu32 " <= WITHIN(%" PRIu32 "), " - // "nm->offset %" PRIu32 ", m->offset %" PRIu32 "\n", nm->offset - m->offset + co->content_len, - // co->within, nm->offset, m->offset); + SCLogDebug("NO MATCH: %" PRIu32 " > WITHIN(%" PRIu32 "), " + "nm->offset %" PRIu32 ", m->offset %" PRIu32 "", + nm->offset - m->offset, + co->within, nm->offset, m->offset); } } } @@ -141,6 +152,8 @@ DoDetectContent(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signat /* 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); + /* 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. */ @@ -148,8 +161,10 @@ DoDetectContent(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signat co->flags & DETECT_CONTENT_DISTANCE_NEXT) && det_ctx->de_checking_distancewithin == 0) { - //printf("DoDetectContent: Content \""); PrintRawUriFp(stdout, co->content, co->content_len); - //printf("\" DETECT_CONTENT_WITHIN_NEXT or DETECT_CONTENT_DISTANCE_NEXT is true\n"); + SCLogDebug("DETECT_CONTENT_WITHIN_NEXT is %s", + co->flags & DETECT_CONTENT_WITHIN_NEXT ? "true":"false"); + SCLogDebug("DETECT_CONTENT_DISTANCE_NEXT is %s", + co->flags & DETECT_CONTENT_DISTANCE_NEXT ? "true":"false"); /* indicate to the detection engine the next sigmatch(es) * are part of this match chain */ @@ -158,10 +173,11 @@ 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) { - //printf("DoDetectContent: TestOffsetDepth returned 1\n"); + SCLogDebug("TestOffsetDepth returned 1, for co->id %"PRIu32"", co->id); + ret = TestWithinDistanceOffsetDepth(t, det_ctx, m, sm->next, det_ctx->pkt_off); if (ret == 1) { - //printf("DoDetectContent: TestWithinDistanceOffsetDepth returned 1\n"); + SCLogDebug("TestWithinDistanceOffsetDepth returned 1"); det_ctx->pkt_ptr = p->payload + m->offset; det_ctx->pkt_off = m->offset; match = 1; diff --git a/src/detect.c b/src/detect.c index ed4c4252c6..076d2c80eb 100644 --- a/src/detect.c +++ b/src/detect.c @@ -7430,6 +7430,63 @@ static int SigTestContent03Wm (void) { return SigTestContent03Real(MPM_WUMANBER); } +static int SigTestContent04Real (int mpm_type) { + uint8_t *buf = (uint8_t *)"01234567890123456789012345678901abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + uint16_t buflen = strlen((char *)buf); + Packet p; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&p, 0, sizeof(p)); + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = buf; + p.payload_len = buflen; + p.proto = IPPROTO_TCP; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + 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:\"Test 32\"; content:\"01234567890123456789012345678901\"; content:\"abcdefghijklmnopqrstuvwxyzABCDEF\"; distance:0; within:32; sid:1;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + if (PacketAlertCheck(&p, 1)) + result = 1; + else + printf("sig 1 didn't match: "); + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} +static int SigTestContent04B2g (void) { + return SigTestContent04Real(MPM_B2G); +} +static int SigTestContent04B3g (void) { + return SigTestContent04Real(MPM_B3G); +} +static int SigTestContent04Wm (void) { + return SigTestContent04Real(MPM_WUMANBER); +} + #endif /* UNITTESTS */ void SigRegisterTests(void) { @@ -7609,6 +7666,10 @@ void SigRegisterTests(void) { UtRegisterTest("SigTestContent03B2g -- 32 byte pattern, x2 + distance", SigTestContent03B2g, 1); UtRegisterTest("SigTestContent03B3g -- 32 byte pattern, x2 + distance", SigTestContent03B3g, 1); UtRegisterTest("SigTestContent03Wm -- 32 byte pattern, x2 + distance", SigTestContent03Wm, 1); + + UtRegisterTest("SigTestContent04B2g -- 32 byte pattern, x2 + distance/within", SigTestContent04B2g, 1); + UtRegisterTest("SigTestContent04B3g -- 32 byte pattern, x2 + distance/within", SigTestContent04B3g, 1); + UtRegisterTest("SigTestContent04Wm -- 32 byte pattern, x2 + distance/within", SigTestContent04Wm, 1); #endif /* UNITTESTS */ }