]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect/content: Negated endswith matches
authorJeff Lucovsky <jlucovsky@oisf.net>
Mon, 27 Mar 2023 12:59:46 +0000 (08:59 -0400)
committerVictor Julien <vjulien@oisf.net>
Thu, 20 Apr 2023 09:06:38 +0000 (11:06 +0200)
Issue: 5541

This commit handles negated endswith matches.

(cherry picked from commit c083cbda33a0e01a9e44b59f98525669affb452c)

src/detect-engine-content-inspection.c

index be10b18bd82d9aecfd6ac26489b04e913d841f0e..fdae8b21458012788802cbc94883d6efa9d5c763 100644 (file)
@@ -279,7 +279,8 @@ int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx
             const uint8_t *sbuffer = buffer + offset;
             uint32_t sbuffer_len = depth - offset;
             uint32_t match_offset = 0;
-            SCLogDebug("sbuffer_len %"PRIu32, sbuffer_len);
+            SCLogDebug("sbuffer_len %" PRIu32 " depth: %" PRIu32 ", buffer_len: %" PRIu32,
+                    sbuffer_len, depth, buffer_len);
 #ifdef DEBUG
             BUG_ON(sbuffer_len > buffer_len);
 #endif
@@ -309,66 +310,84 @@ int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx
                 } else {
                     goto match;
                 }
-            } else if (cd->flags & DETECT_CONTENT_NEGATED) {
-                SCLogDebug("content %"PRIu32" matched at offset %"PRIu32", but negated so no match", cd->id, match_offset);
-                /* don't bother carrying recursive matches now, for preceding
-                 * relative keywords */
-                if (DETECT_CONTENT_IS_SINGLE(cd))
-                    det_ctx->discontinue_matching = 1;
-                goto no_match;
             } else {
                 match_offset = (uint32_t)((found - buffer) + cd->content_len);
-                SCLogDebug("content %"PRIu32" matched at offset %"PRIu32"", cd->id, match_offset);
-                det_ctx->buffer_offset = match_offset;
-
-                if ((cd->flags & DETECT_CONTENT_ENDS_WITH) == 0 || match_offset == buffer_len) {
-                    /* Match branch, add replace to the list if needed */
-                    if (cd->flags & DETECT_CONTENT_REPLACE) {
-                        if (inspection_mode == DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD) {
-                            /* we will need to replace content if match is confirmed
-                             * cast to non-const as replace writes to it. */
-                            det_ctx->replist = DetectReplaceAddToList(det_ctx->replist, (uint8_t *)found, cd);
-                        } else {
-                            SCLogWarning(SC_ERR_INVALID_VALUE, "Can't modify payload without packet");
+                if (cd->flags & DETECT_CONTENT_NEGATED) {
+                    SCLogDebug("content %" PRIu32 " matched at offset %" PRIu32
+                               ", but negated so no match",
+                            cd->id, match_offset);
+                    /* don't bother carrying recursive matches now, for preceding
+                     * relative keywords */
+
+                    /* found a match but not at the end of the buffer */
+                    if (cd->flags & DETECT_CONTENT_ENDS_WITH) {
+                        if (sbuffer_len != match_offset) {
+                            SCLogDebug("content \"%s\" %" PRIu32 " matched at offset %" PRIu32
+                                       ", but not at end of buffer so match",
+                                    cd->content, cd->id, match_offset);
+                            goto match;
                         }
                     }
+                    if (DETECT_CONTENT_IS_SINGLE(cd))
+                        det_ctx->discontinue_matching = 1;
+                    goto no_match;
+                } else {
+                    SCLogDebug("content %" PRIu32 " matched at offset %" PRIu32 "", cd->id,
+                            match_offset);
+                    det_ctx->buffer_offset = match_offset;
+
+                    if ((cd->flags & DETECT_CONTENT_ENDS_WITH) == 0 || match_offset == buffer_len) {
+                        /* Match branch, add replace to the list if needed */
+                        if (cd->flags & DETECT_CONTENT_REPLACE) {
+                            if (inspection_mode == DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD) {
+                                /* we will need to replace content if match is confirmed
+                                 * cast to non-const as replace writes to it. */
+                                det_ctx->replist = DetectReplaceAddToList(
+                                        det_ctx->replist, (uint8_t *)found, cd);
+                            } else {
+                                SCLogWarning(SC_ERR_INVALID_VALUE,
+                                        "Can't modify payload without packet");
+                            }
+                        }
 
-                    /* if this is the last match we're done */
-                    if (smd->is_last) {
-                        goto match;
-                    }
+                        /* if this is the last match we're done */
+                        if (smd->is_last) {
+                            goto match;
+                        }
 
-                    SCLogDebug("content %"PRIu32, cd->id);
-                    KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
-
-                    /* see if the next buffer keywords match. If not, we will
-                     * search for another occurrence of this content and see
-                     * if the others match then until we run out of matches */
-                    int r = DetectEngineContentInspection(de_ctx, det_ctx, s, smd+1,
-                            p, f, buffer, buffer_len, stream_start_offset, flags,
-                            inspection_mode);
-                    if (r == 1) {
-                        SCReturnInt(1);
-                    }
-                    SCLogDebug("no match for 'next sm'");
+                        SCLogDebug("content %" PRIu32, cd->id);
+                        KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
 
-                    if (det_ctx->discontinue_matching) {
-                        SCLogDebug("'next sm' said to discontinue this right now");
-                        goto no_match;
-                    }
+                        /* see if the next buffer keywords match. If not, we will
+                         * search for another occurrence of this content and see
+                         * if the others match then until we run out of matches */
+                        uint8_t r = DetectEngineContentInspection(de_ctx, det_ctx, s, smd + 1, p, f,
+                                buffer, buffer_len, stream_start_offset, flags, inspection_mode);
+                        if (r == 1) {
+                            SCReturnInt(1);
+                        }
+                        SCLogDebug("no match for 'next sm'");
 
-                    /* no match and no reason to look for another instance */
-                    if ((cd->flags & DETECT_CONTENT_WITHIN_NEXT) == 0) {
-                        SCLogDebug("'next sm' does not depend on me, so we can give up");
-                        det_ctx->discontinue_matching = 1;
-                        goto no_match;
-                    }
+                        if (det_ctx->discontinue_matching) {
+                            SCLogDebug("'next sm' said to discontinue this right now");
+                            goto no_match;
+                        }
 
-                    SCLogDebug("'next sm' depends on me %p, lets see what we can do (flags %u)", cd, cd->flags);
+                        /* no match and no reason to look for another instance */
+                        if ((cd->flags & DETECT_CONTENT_WITHIN_NEXT) == 0) {
+                            SCLogDebug("'next sm' does not depend on me, so we can give up");
+                            det_ctx->discontinue_matching = 1;
+                            goto no_match;
+                        }
+
+                        SCLogDebug("'next sm' depends on me %p, lets see what we can do (flags %u)",
+                                cd, cd->flags);
+                    }
+                    /* 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);
                 }
-                /* 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);