aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/suricata/src/detect-engine-content-inspection.c
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/suricata/src/detect-engine-content-inspection.c')
-rw-r--r--framework/src/suricata/src/detect-engine-content-inspection.c588
1 files changed, 0 insertions, 588 deletions
diff --git a/framework/src/suricata/src/detect-engine-content-inspection.c b/framework/src/suricata/src/detect-engine-content-inspection.c
deleted file mode 100644
index 17df02ce..00000000
--- a/framework/src/suricata/src/detect-engine-content-inspection.c
+++ /dev/null
@@ -1,588 +0,0 @@
-/* Copyright (C) 2007-2011 Open Information Security Foundation
- *
- * You can copy, redistribute or modify this Program under the terms of
- * the GNU General Public License version 2 as published by the Free
- * Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-/**
- * \file
- *
- * \author Anoop Saldanha <anoopsaldanha@gmail.com>
- *
- * Performs content inspection on any buffer supplied.
- */
-
-#include "suricata-common.h"
-#include "suricata.h"
-
-#include "decode.h"
-
-#include "detect.h"
-#include "detect-engine.h"
-#include "detect-parse.h"
-#include "detect-content.h"
-#include "detect-pcre.h"
-#include "detect-isdataat.h"
-#include "detect-bytetest.h"
-#include "detect-bytejump.h"
-#include "detect-byte-extract.h"
-#include "detect-replace.h"
-#include "detect-engine-content-inspection.h"
-#include "detect-uricontent.h"
-#include "detect-urilen.h"
-#include "detect-lua.h"
-#include "detect-base64-decode.h"
-#include "detect-base64-data.h"
-
-#include "app-layer-dcerpc.h"
-
-#include "util-spm.h"
-#include "util-spm-bm.h"
-#include "util-debug.h"
-#include "util-print.h"
-
-#include "util-unittest.h"
-#include "util-unittest-helper.h"
-#include "util-profiling.h"
-
-#ifdef HAVE_LUA
-#include "util-lua.h"
-#endif
-
-/**
- * \brief Run the actual payload match functions
- *
- * The following keywords are inspected:
- * - content, including all the http and dce modified contents
- * - isdaatat
- * - pcre
- * - bytejump
- * - bytetest
- * - byte_extract
- * - urilen
- * -
- *
- * All keywords are evaluated against the buffer with buffer_len.
- *
- * For accounting the last match in relative matching the
- * det_ctx->buffer_offset int is used.
- *
- * \param de_ctx Detection engine context
- * \param det_ctx Detection engine thread context
- * \param s Signature to inspect
- * \param sm SigMatch to inspect
- * \param f Flow (for pcre flowvar storage)
- * \param buffer Ptr to the buffer to inspect
- * \param buffer_len Length of the payload
- * \param stream_start_offset Indicates the start of the current buffer in
- * the whole buffer stream inspected. This
- * applies if the current buffer is inspected
- * in chunks.
- * \param inspection_mode Refers to the engine inspection mode we are currently
- * inspecting. Can be payload, stream, one of the http
- * buffer inspection modes or dce inspection mode.
- * \param data Used to send some custom data. For example in
- * payload inspection mode, data contains packet ptr,
- * and under dce inspection mode, contains dce state.
- *
- * \retval 0 no match
- * \retval 1 match
- */
-int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
- Signature *s, SigMatch *sm,
- Flow *f,
- uint8_t *buffer, uint32_t buffer_len,
- uint32_t stream_start_offset,
- uint8_t inspection_mode, void *data)
-{
- SCEnter();
- KEYWORD_PROFILING_START;
-
- det_ctx->inspection_recursion_counter++;
-
- if (det_ctx->inspection_recursion_counter == de_ctx->inspection_recursion_limit) {
- det_ctx->discontinue_matching = 1;
- KEYWORD_PROFILING_END(det_ctx, sm->type, 0);
- SCReturnInt(0);
- }
-
- if (sm == NULL || buffer_len == 0) {
- KEYWORD_PROFILING_END(det_ctx, sm->type, 0);
- SCReturnInt(0);
- }
-
- /* \todo unify this which is phase 2 of payload inspection unification */
- if (sm->type == DETECT_CONTENT) {
-
- DetectContentData *cd = (DetectContentData *)sm->ctx;
- SCLogDebug("inspecting content %"PRIu32" buffer_len %"PRIu32, cd->id, buffer_len);
-
- /* we might have already have this content matched by the mpm.
- * (if there is any other reason why we'd want to avoid checking
- * it here, please fill it in) */
- //if (cd->flags & DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED) {
- // goto match;
- //}
-
- /* rule parsers should take care of this */
-#ifdef DEBUG
- BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
-#endif
-
- /* search for our pattern, checking the matches recursively.
- * if we match we look for the next SigMatch as well */
- uint8_t *found = NULL;
- uint32_t offset = 0;
- uint32_t depth = buffer_len;
- uint32_t prev_offset = 0; /**< used in recursive searching */
- uint32_t prev_buffer_offset = det_ctx->buffer_offset;
-
- do {
- if ((cd->flags & DETECT_CONTENT_DISTANCE) ||
- (cd->flags & DETECT_CONTENT_WITHIN)) {
- SCLogDebug("det_ctx->buffer_offset %"PRIu32, det_ctx->buffer_offset);
-
- offset = prev_buffer_offset;
- depth = buffer_len;
-
- int distance = cd->distance;
- if (cd->flags & DETECT_CONTENT_DISTANCE) {
- if (cd->flags & DETECT_CONTENT_DISTANCE_BE) {
- distance = det_ctx->bj_values[cd->distance];
- }
- if (distance < 0 && (uint32_t)(abs(distance)) > offset)
- offset = 0;
- else
- offset += distance;
-
- SCLogDebug("cd->distance %"PRIi32", offset %"PRIu32", depth %"PRIu32,
- distance, offset, depth);
- }
-
- if (cd->flags & DETECT_CONTENT_WITHIN) {
- if (cd->flags & DETECT_CONTENT_WITHIN_BE) {
- if ((int32_t)depth > (int32_t)(prev_buffer_offset + det_ctx->bj_values[cd->within] + distance)) {
- depth = prev_buffer_offset + det_ctx->bj_values[cd->within] + distance;
- }
- } else {
- if ((int32_t)depth > (int32_t)(prev_buffer_offset + cd->within + distance)) {
- depth = prev_buffer_offset + cd->within + distance;
- }
-
- SCLogDebug("cd->within %"PRIi32", det_ctx->buffer_offset %"PRIu32", depth %"PRIu32,
- cd->within, prev_buffer_offset, depth);
- }
-
- if (stream_start_offset != 0 && prev_buffer_offset == 0) {
- if (depth <= stream_start_offset) {
- goto no_match;
- } else if (depth >= (stream_start_offset + buffer_len)) {
- ;
- } else {
- depth = depth - stream_start_offset;
- }
- }
- }
-
- if (cd->flags & DETECT_CONTENT_DEPTH_BE) {
- if ((det_ctx->bj_values[cd->depth] + prev_buffer_offset) < depth) {
- depth = prev_buffer_offset + det_ctx->bj_values[cd->depth];
- }
- } else {
- if (cd->depth != 0) {
- if ((cd->depth + prev_buffer_offset) < depth) {
- depth = prev_buffer_offset + cd->depth;
- }
-
- SCLogDebug("cd->depth %"PRIu32", depth %"PRIu32, cd->depth, depth);
- }
- }
-
- if (cd->flags & DETECT_CONTENT_OFFSET_BE) {
- if (det_ctx->bj_values[cd->offset] > offset)
- offset = det_ctx->bj_values[cd->offset];
- } else {
- if (cd->offset > offset) {
- offset = cd->offset;
- SCLogDebug("setting offset %"PRIu32, offset);
- }
- }
- } else { /* implied no relative matches */
- /* set depth */
- if (cd->flags & DETECT_CONTENT_DEPTH_BE) {
- depth = det_ctx->bj_values[cd->depth];
- } else {
- if (cd->depth != 0) {
- depth = cd->depth;
- }
- }
-
- if (stream_start_offset != 0 && cd->flags & DETECT_CONTENT_DEPTH) {
- if (depth <= stream_start_offset) {
- goto no_match;
- } else if (depth >= (stream_start_offset + buffer_len)) {
- ;
- } else {
- depth = depth - stream_start_offset;
- }
- }
-
- /* set offset */
- if (cd->flags & DETECT_CONTENT_OFFSET_BE)
- offset = det_ctx->bj_values[cd->offset];
- else
- offset = cd->offset;
- prev_buffer_offset = 0;
- }
-
- /* update offset with prev_offset if we're searching for
- * matches after the first occurence. */
- SCLogDebug("offset %"PRIu32", prev_offset %"PRIu32, offset, prev_offset);
- if (prev_offset != 0)
- offset = prev_offset;
-
- SCLogDebug("offset %"PRIu32", depth %"PRIu32, offset, depth);
-
- if (depth > buffer_len)
- depth = buffer_len;
-
- /* if offset is bigger than depth we can never match on a pattern.
- * We can however, "match" on a negated pattern. */
- if (offset > depth || depth == 0) {
- if (cd->flags & DETECT_CONTENT_NEGATED) {
- goto match;
- } else {
- goto no_match;
- }
- }
-
- uint8_t *sbuffer = buffer + offset;
- uint32_t sbuffer_len = depth - offset;
- uint32_t match_offset = 0;
- SCLogDebug("sbuffer_len %"PRIu32, sbuffer_len);
-#ifdef DEBUG
- BUG_ON(sbuffer_len > buffer_len);
-#endif
-
- /* \todo Add another optimization here. If cd->content_len is
- * greater than sbuffer_len found is anyways NULL */
-
- /* do the actual search */
- if (cd->flags & DETECT_CONTENT_NOCASE)
- found = BoyerMooreNocase(cd->content, cd->content_len, sbuffer, sbuffer_len, cd->bm_ctx);
- else
- found = BoyerMoore(cd->content, cd->content_len, sbuffer, sbuffer_len, cd->bm_ctx);
-
- /* next we evaluate the result in combination with the
- * negation flag. */
- SCLogDebug("found %p cd negated %s", found, cd->flags & DETECT_CONTENT_NEGATED ? "true" : "false");
-
- if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) {
- goto no_match;
- } else if (found == NULL && (cd->flags & DETECT_CONTENT_NEGATED)) {
- goto match;
- } else if (found != NULL && (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;
-
- /* 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 */
- det_ctx->replist = DetectReplaceAddToList(det_ctx->replist, found, cd);
- } else {
- SCLogWarning(SC_ERR_INVALID_VALUE, "Can't modify payload without packet");
- }
- }
- if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
- SCLogDebug("no relative match coming up, so this is a match");
- goto match;
- }
-
- /* bail out if we have no next match. Technically this is an
- * error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT
- * flag set. */
- if (sm->next == NULL) {
- goto no_match;
- }
-
- SCLogDebug("content %"PRIu32, cd->id);
- KEYWORD_PROFILING_END(det_ctx, sm->type, 1);
-
- /* see if the next buffer keywords match. If not, we will
- * search for another occurence of this content and see
- * if the others match then until we run out of matches */
- int r = DetectEngineContentInspection(de_ctx, det_ctx, s, sm->next, f, buffer, buffer_len, stream_start_offset, inspection_mode, data);
- if (r == 1) {
- SCReturnInt(1);
- }
-
- if (det_ctx->discontinue_matching)
- goto no_match;
-
- /* 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);
-
- } else if (sm->type == DETECT_ISDATAAT) {
- SCLogDebug("inspecting isdataat");
-
- DetectIsdataatData *id = (DetectIsdataatData *)sm->ctx;
- if (id->flags & ISDATAAT_RELATIVE) {
- if (det_ctx->buffer_offset + id->dataat > buffer_len) {
- SCLogDebug("det_ctx->buffer_offset + id->dataat %"PRIu32" > %"PRIu32, det_ctx->buffer_offset + id->dataat, buffer_len);
- if (id->flags & ISDATAAT_NEGATED)
- goto match;
- goto no_match;
- } else {
- SCLogDebug("relative isdataat match");
- if (id->flags & ISDATAAT_NEGATED)
- goto no_match;
- goto match;
- }
- } else {
- if (id->dataat < buffer_len) {
- SCLogDebug("absolute isdataat match");
- if (id->flags & ISDATAAT_NEGATED)
- goto no_match;
- goto match;
- } else {
- SCLogDebug("absolute isdataat mismatch, id->isdataat %"PRIu32", buffer_len %"PRIu32"", id->dataat, buffer_len);
- if (id->flags & ISDATAAT_NEGATED)
- goto match;
- goto no_match;
- }
- }
-
- } else if (sm->type == DETECT_PCRE) {
- SCLogDebug("inspecting pcre");
- DetectPcreData *pe = (DetectPcreData *)sm->ctx;
- uint32_t prev_buffer_offset = det_ctx->buffer_offset;
- uint32_t prev_offset = 0;
- int r = 0;
-
- det_ctx->pcre_match_start_offset = 0;
- do {
- Packet *p = NULL;
- if (inspection_mode == DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD)
- p = (Packet *)data;
- r = DetectPcrePayloadMatch(det_ctx, s, sm, p, f,
- buffer, buffer_len);
- if (r == 0) {
- goto no_match;
- }
-
- if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
- SCLogDebug("no relative match coming up, so this is a match");
- goto match;
- }
- KEYWORD_PROFILING_END(det_ctx, sm->type, 1);
-
- /* save it, in case we need to do a pcre match once again */
- prev_offset = det_ctx->pcre_match_start_offset;
-
- /* see if the next payload keywords match. If not, we will
- * search for another occurence of this pcre and see
- * if the others match, until we run out of matches */
- r = DetectEngineContentInspection(de_ctx, det_ctx, s, sm->next,
- f, buffer, buffer_len, stream_start_offset, inspection_mode, data);
- if (r == 1) {
- SCReturnInt(1);
- }
-
- if (det_ctx->discontinue_matching)
- goto no_match;
-
- det_ctx->buffer_offset = prev_buffer_offset;
- det_ctx->pcre_match_start_offset = prev_offset;
- } while (1);
-
- } else if (sm->type == DETECT_BYTETEST) {
- DetectBytetestData *btd = (DetectBytetestData *)sm->ctx;
- uint8_t flags = btd->flags;
- int32_t offset = btd->offset;
- uint64_t value = btd->value;
- if (flags & DETECT_BYTETEST_OFFSET_BE) {
- offset = det_ctx->bj_values[offset];
- }
- if (flags & DETECT_BYTETEST_VALUE_BE) {
- value = det_ctx->bj_values[value];
- }
-
- /* if we have dce enabled we will have to use the endianness
- * specified by the dce header */
- if (flags & DETECT_BYTETEST_DCE) {
- DCERPCState *dcerpc_state = (DCERPCState *)data;
- /* enable the endianness flag temporarily. once we are done
- * processing we reset the flags to the original value*/
- flags |= ((dcerpc_state->dcerpc.dcerpchdr.packed_drep[0] & 0x10) ?
- DETECT_BYTETEST_LITTLE: 0);
- }
-
- if (DetectBytetestDoMatch(det_ctx, s, sm->ctx, buffer, buffer_len, flags,
- offset, value) != 1) {
- goto no_match;
- }
-
- goto match;
-
- } else if (sm->type == DETECT_BYTEJUMP) {
- DetectBytejumpData *bjd = (DetectBytejumpData *)sm->ctx;
- uint8_t flags = bjd->flags;
- int32_t offset = bjd->offset;
-
- if (flags & DETECT_BYTEJUMP_OFFSET_BE) {
- offset = det_ctx->bj_values[offset];
- }
-
- /* if we have dce enabled we will have to use the endianness
- * specified by the dce header */
- if (flags & DETECT_BYTEJUMP_DCE) {
- DCERPCState *dcerpc_state = (DCERPCState *)data;
- /* enable the endianness flag temporarily. once we are done
- * processing we reset the flags to the original value*/
- flags |= ((dcerpc_state->dcerpc.dcerpchdr.packed_drep[0] & 0x10) ?
- DETECT_BYTEJUMP_LITTLE: 0);
- }
-
- if (DetectBytejumpDoMatch(det_ctx, s, sm->ctx, buffer, buffer_len,
- flags, offset) != 1) {
- goto no_match;
- }
-
- goto match;
-
- } else if (sm->type == DETECT_BYTE_EXTRACT) {
-
- DetectByteExtractData *bed = (DetectByteExtractData *)sm->ctx;
- uint8_t endian = bed->endian;
-
- /* if we have dce enabled we will have to use the endianness
- * specified by the dce header */
- if ((bed->flags & DETECT_BYTE_EXTRACT_FLAG_ENDIAN) &&
- endian == DETECT_BYTE_EXTRACT_ENDIAN_DCE) {
-
- DCERPCState *dcerpc_state = (DCERPCState *)data;
- /* enable the endianness flag temporarily. once we are done
- * processing we reset the flags to the original value*/
- endian |= ((dcerpc_state->dcerpc.dcerpchdr.packed_drep[0] == 0x10) ?
- DETECT_BYTE_EXTRACT_ENDIAN_LITTLE : DETECT_BYTE_EXTRACT_ENDIAN_BIG);
- }
-
- if (DetectByteExtractDoMatch(det_ctx, sm, s, buffer,
- buffer_len,
- &det_ctx->bj_values[bed->local_id],
- endian) != 1) {
- goto no_match;
- }
-
- goto match;
-
- /* we should never get here, but bail out just in case */
- } else if (sm->type == DETECT_AL_URILEN) {
- SCLogDebug("inspecting uri len");
-
- int r = 0;
- DetectUrilenData *urilend = (DetectUrilenData *) sm->ctx;
-
- switch (urilend->mode) {
- case DETECT_URILEN_EQ:
- if (buffer_len == urilend->urilen1)
- r = 1;
- break;
- case DETECT_URILEN_LT:
- if (buffer_len < urilend->urilen1)
- r = 1;
- break;
- case DETECT_URILEN_GT:
- if (buffer_len > urilend->urilen1)
- r = 1;
- break;
- case DETECT_URILEN_RA:
- if (buffer_len > urilend->urilen1 &&
- buffer_len < urilend->urilen2) {
- r = 1;
- }
- break;
- }
-
- if (r == 1) {
- goto match;
- }
-
- det_ctx->discontinue_matching = 0;
-
- goto no_match;
-#ifdef HAVE_LUA
- }
- else if (sm->type == DETECT_LUA) {
- SCLogDebug("lua starting");
- /* for flowvar gets and sets we need to know the flow's lock status */
- int flow_lock = LUA_FLOW_LOCKED_BY_PARENT;
- if (inspection_mode <= DETECT_ENGINE_CONTENT_INSPECTION_MODE_STREAM)
- flow_lock = LUA_FLOW_NOT_LOCKED_BY_PARENT;
-
- if (DetectLuaMatchBuffer(det_ctx, s, sm, buffer, buffer_len,
- det_ctx->buffer_offset, f, flow_lock) != 1)
- {
- SCLogDebug("lua no_match");
- goto no_match;
- }
- SCLogDebug("lua match");
- goto match;
-#endif /* HAVE_LUA */
- } else if (sm->type == DETECT_BASE64_DECODE) {
- if (DetectBase64DecodeDoMatch(det_ctx, s, sm, buffer, buffer_len)) {
- if (s->sm_arrays[DETECT_SM_LIST_BASE64_DATA] != NULL) {
- KEYWORD_PROFILING_END(det_ctx, sm->type, 1);
- if (DetectBase64DataDoMatch(de_ctx, det_ctx, s, f)) {
- /* Base64 is a terminal list. */
- goto final_match;
- }
- }
- }
- } else {
- SCLogDebug("sm->type %u", sm->type);
-#ifdef DEBUG
- BUG_ON(1);
-#endif
- }
-
-no_match:
- KEYWORD_PROFILING_END(det_ctx, sm->type, 0);
- SCReturnInt(0);
-
-match:
- /* this sigmatch matched, inspect the next one. If it was the last,
- * the buffer portion of the signature matched. */
- if (sm->next != NULL) {
- KEYWORD_PROFILING_END(det_ctx, sm->type, 1);
- int r = DetectEngineContentInspection(de_ctx, det_ctx, s, sm->next, f, buffer, buffer_len, stream_start_offset, inspection_mode, data);
- SCReturnInt(r);
- }
-final_match:
- KEYWORD_PROFILING_END(det_ctx, sm->type, 1);
- SCReturnInt(1);
-}