diff --git a/src/Makefile.am b/src/Makefile.am index 69eb2a4938e..6e1666bc34b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -74,6 +74,7 @@ detect-engine-port.c detect-engine-port.h \ detect-engine-siggroup.c detect-engine-siggroup.h \ detect-engine-mpm.c detect-engine-mpm.h \ detect-engine-iponly.c detect-engine-iponly.h \ +detect-engine-content-inspection.c detect-engine-content-inspection.h \ detect-engine-payload.c detect-engine-payload.h \ detect-engine-dcepayload.c detect-engine-dcepayload.h \ detect-engine-uri.c detect-engine-uri.h \ diff --git a/src/detect-distance.c b/src/detect-distance.c index a55dcaa4db6..1e146c4db76 100644 --- a/src/detect-distance.c +++ b/src/detect-distance.c @@ -685,7 +685,7 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, /* reassigning pm */ pm = SigMatchGetLastSMFromLists(s, 4, DETECT_AL_HTTP_METHOD, pm->prev, - DETECT_PCRE_HTTPMETHOD, pm->prev); + DETECT_PCRE, pm->prev); if (pm == NULL) { SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for " "http_method needs preceeding http_method " @@ -693,7 +693,7 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, goto error; } - if (pm->type == DETECT_PCRE_HTTPMETHOD) { + if (pm->type == DETECT_PCRE) { DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx; tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT; } else { @@ -747,7 +747,7 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, /* reassigning pm */ pm = SigMatchGetLastSMFromLists(s, 4, DETECT_AL_HTTP_COOKIE, pm->prev, - DETECT_PCRE_HTTPCOOKIE, pm->prev); + DETECT_PCRE, pm->prev); if (pm == NULL) { SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for " "http_cookie needs preceeding http_cookie " @@ -755,7 +755,7 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, goto error; } - if (pm->type == DETECT_PCRE_HTTPCOOKIE) { + if (pm->type == DETECT_PCRE) { DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx; tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT; } else { diff --git a/src/detect-engine-content-inspection.c b/src/detect-engine-content-inspection.c new file mode 100644 index 00000000000..24347efa825 --- /dev/null +++ b/src/detect-engine-content-inspection.c @@ -0,0 +1,491 @@ +/* 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 + * + * 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 "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" + +int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, + Signature *s, SigMatch *sm, + Flow *f, + uint8_t *buffer, uint32_t buffer_len, + uint8_t inspection_mode, void *data) +{ + SCEnter(); + + det_ctx->inspection_recursion_counter++; + + if (det_ctx->inspection_recursion_counter == de_ctx->inspection_recursion_limit) { + det_ctx->discontinue_matching = 1; + SCReturnInt(0); + } + + if (sm == NULL || buffer_len == 0) { + SCReturnInt(0); + } + + /* \todo unify this which is phase 2 of payload inspection unification */ + if (sm->type == DETECT_CONTENT || + sm->type == DETECT_URICONTENT || + sm->type == DETECT_AL_HTTP_RAW_URI || + sm->type == DETECT_AL_HTTP_HEADER || + sm->type == DETECT_AL_HTTP_RAW_HEADER || + sm->type == DETECT_AL_HTTP_CLIENT_BODY || + sm->type == DETECT_AL_HTTP_SERVER_BODY || + sm->type == DETECT_AL_HTTP_COOKIE || + sm->type == DETECT_AL_HTTP_METHOD) { + + 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 (inspection_mode == DETECT_ENGINE_CONTENT_INSPECTION_MODE_STREAM) { + if (cd->flags & DETECT_CONTENT_STREAM_MPM && !(cd->flags & DETECT_CONTENT_NEGATED)) { + 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->payload_offset; + + do { + if (cd->flags & DETECT_CONTENT_DISTANCE || + cd->flags & DETECT_CONTENT_WITHIN) { + SCLogDebug("det_ctx->payload_offset %"PRIu32, det_ctx->payload_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->payload_offset %"PRIu32", depth %"PRIu32, + cd->within, prev_buffer_offset, depth); + } + } + + 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; + } + } + + /* 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 { + SCReturnInt(0); + } + } + + 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->bmGs, cd->bm_ctx->bmBc); + else + found = BoyerMoore(cd->content, cd->content_len, sbuffer, sbuffer_len, cd->bm_ctx->bmGs, cd->bm_ctx->bmBc); + + /* 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)) { + SCReturnInt(0); + } 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 */ + det_ctx->discontinue_matching = 1; + SCReturnInt(0); + } else { + match_offset = (uint32_t)((found - buffer) + cd->content_len); + SCLogDebug("content %"PRIu32" matched at offset %"PRIu32"", cd->id, match_offset); + det_ctx->payload_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) { + SCReturnInt(0); + } + + SCLogDebug("content %"PRIu32, cd->id); + + /* 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, inspection_mode, data); + if (r == 1) { + SCReturnInt(1); + } + + if (det_ctx->discontinue_matching) + SCReturnInt(0); + + /* 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->payload_offset + id->dataat > buffer_len) { + SCLogDebug("det_ctx->payload_offset + id->dataat %"PRIu32" > %"PRIu32, det_ctx->payload_offset + id->dataat, buffer_len); + if (id->flags & ISDATAAT_NEGATED) + goto match; + SCReturnInt(0); + } else { + SCLogDebug("relative isdataat match"); + if (id->flags & ISDATAAT_NEGATED) + SCReturnInt(0); + goto match; + } + } else { + if (id->dataat < buffer_len) { + SCLogDebug("absolute isdataat match"); + if (id->flags & ISDATAAT_NEGATED) + SCReturnInt(0); + goto match; + } else { + SCLogDebug("absolute isdataat mismatch, id->isdataat %"PRIu32", buffer_len %"PRIu32"", id->dataat, buffer_len); + if (id->flags & ISDATAAT_NEGATED) + goto match; + SCReturnInt(0); + } + } + + } else if (sm->type == DETECT_PCRE) { + SCLogDebug("inspecting pcre"); + DetectPcreData *pe = (DetectPcreData *)sm->ctx; + uint32_t prev_buffer_offset = det_ctx->payload_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) { + det_ctx->discontinue_matching = 1; + SCReturnInt(0); + } + + if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) { + SCLogDebug("no relative match coming up, so this is a match"); + goto match; + } + + /* 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, inspection_mode, data); + if (r == 1) { + SCReturnInt(1); + } + + if (det_ctx->discontinue_matching) + SCReturnInt(0); + + det_ctx->payload_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, buffer, buffer_len, flags, + offset, value) != 1) { + SCReturnInt(0); + } + + 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, buffer, buffer_len, + flags, offset) != 1) { + SCReturnInt(0); + } + + 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) { + SCReturnInt(0); + } + + 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; + } + + SCReturnInt(0); + } else { + SCLogDebug("sm->type %u", sm->type); +#ifdef DEBUG + BUG_ON(1); +#endif + } + + 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) { + int r = DetectEngineContentInspection(de_ctx, det_ctx, s, sm->next, f, buffer, buffer_len, inspection_mode, data); + SCReturnInt(r); + } else { + SCReturnInt(1); + } +} diff --git a/src/detect-engine-content-inspection.h b/src/detect-engine-content-inspection.h new file mode 100644 index 00000000000..d7d4e249b6f --- /dev/null +++ b/src/detect-engine-content-inspection.h @@ -0,0 +1,49 @@ +/* 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 + */ + +#ifndef __DETECT_ENGINE_CONTENT_INSPECTION_H__ +#define __DETECT_ENGINE_CONTENT_INSPECTION_H__ + +enum { + DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD = 0, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_STREAM, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_DCE, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_URI, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HRUD, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HHD, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HRHD, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HCBD, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HSBD, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HCD, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HMD, +}; + +int DetectEngineContentInspection(DetectEngineCtx *, + DetectEngineThreadCtx *, + Signature *, SigMatch *, + Flow *, + uint8_t *, uint32_t, + uint8_t, + void *data); + +#endif /* __DETECT_ENGINE_CONTENT_INSPECTION_H__ */ diff --git a/src/detect-engine-dcepayload.c b/src/detect-engine-dcepayload.c index 7eee54f62bf..7e558f4bde9 100644 --- a/src/detect-engine-dcepayload.c +++ b/src/detect-engine-dcepayload.c @@ -35,6 +35,7 @@ #include "detect-bytetest.h" #include "detect-bytejump.h" #include "detect-byte-extract.h" +#include "detect-engine-content-inspection.h" #include "util-spm.h" #include "util-spm-bm.h" @@ -504,8 +505,13 @@ int DetectEngineInspectDcePayload(DetectEngineCtx *de_ctx, det_ctx->discontinue_matching = 0; det_ctx->inspection_recursion_counter = 0; - r = DoInspectDcePayload(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_DMATCH], f, - dce_stub_data, dce_stub_data_len, dcerpc_state); + r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_DMATCH], + f, + dce_stub_data, + dce_stub_data_len, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_DCE, dcerpc_state); + //r = DoInspectDcePayload(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_DMATCH], f, + //dce_stub_data, dce_stub_data_len, dcerpc_state); if (r == 1) { SCReturnInt(1); } @@ -521,8 +527,13 @@ int DetectEngineInspectDcePayload(DetectEngineCtx *de_ctx, det_ctx->discontinue_matching = 0; det_ctx->inspection_recursion_counter = 0; - r = DoInspectDcePayload(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_DMATCH], f, - dce_stub_data, dce_stub_data_len, dcerpc_state); + r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_DMATCH], + f, + dce_stub_data, + dce_stub_data_len, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_DCE, dcerpc_state); + //r = DoInspectDcePayload(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_DMATCH], f, + //dce_stub_data, dce_stub_data_len, dcerpc_state); if (r == 1) { SCReturnInt(1); } diff --git a/src/detect-engine-hcbd.c b/src/detect-engine-hcbd.c index a5d1f300495..a351ef3cc65 100644 --- a/src/detect-engine-hcbd.c +++ b/src/detect-engine-hcbd.c @@ -44,6 +44,7 @@ #include "detect-isdataat.h" #include "detect-bytetest.h" #include "detect-bytejump.h" +#include "detect-engine-content-inspection.h" #include "flow-util.h" #include "util-spm.h" @@ -505,8 +506,13 @@ int DetectEngineInspectHttpClientBody(DetectEngineCtx *de_ctx, if (hcbd_buffer == NULL) continue; - r = DoInspectHttpClientBody(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HCBDMATCH], - hcbd_buffer, hcbd_buffer_len); + r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HCBDMATCH], + f, + hcbd_buffer, + hcbd_buffer_len, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HCBD, NULL); + //r = DoInspectHttpClientBody(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HCBDMATCH], + //hcbd_buffer, hcbd_buffer_len); if (r == 1) { break; } diff --git a/src/detect-engine-hcd.c b/src/detect-engine-hcd.c index 433d965517a..d5e42a1e8e9 100644 --- a/src/detect-engine-hcd.c +++ b/src/detect-engine-hcd.c @@ -44,6 +44,7 @@ #include "detect-isdataat.h" #include "detect-bytetest.h" #include "detect-bytejump.h" +#include "detect-engine-content-inspection.h" #include "flow-util.h" #include "util-spm.h" @@ -413,9 +414,14 @@ int DetectEngineInspectHttpCookie(DetectEngineCtx *de_ctx, continue; } - r = DoInspectHttpCookie(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HCDMATCH], - (uint8_t *)bstr_ptr(h->value), - bstr_len(h->value)); + r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HCDMATCH], + f, + (uint8_t *)bstr_ptr(h->value), + bstr_len(h->value), + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HCD, NULL); + //r = DoInspectHttpCookie(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HCDMATCH], + //(uint8_t *)bstr_ptr(h->value), + //bstr_len(h->value)); if (r == 1) { break; } diff --git a/src/detect-engine-hhd.c b/src/detect-engine-hhd.c index 175d407fe50..431b116e667 100644 --- a/src/detect-engine-hhd.c +++ b/src/detect-engine-hhd.c @@ -44,6 +44,7 @@ #include "detect-isdataat.h" #include "detect-bytetest.h" #include "detect-bytejump.h" +#include "detect-engine-content-inspection.h" #include "flow-util.h" #include "util-spm.h" @@ -527,8 +528,13 @@ int DetectEngineInspectHttpHeader(DetectEngineCtx *de_ctx, if (hhd_buffer == NULL) continue; - r = DoInspectHttpHeader(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HHDMATCH], - hhd_buffer, hhd_buffer_len); + r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HHDMATCH], + f, + hhd_buffer, + hhd_buffer_len, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HHD, NULL); + //r = DoInspectHttpHeader(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HHDMATCH], + //hhd_buffer, hhd_buffer_len); if (r == 1) { break; } diff --git a/src/detect-engine-hmd.c b/src/detect-engine-hmd.c index 39806f66bca..dd57e71ce3b 100644 --- a/src/detect-engine-hmd.c +++ b/src/detect-engine-hmd.c @@ -44,6 +44,7 @@ #include "detect-isdataat.h" #include "detect-bytetest.h" #include "detect-bytejump.h" +#include "detect-engine-content-inspection.h" #include "flow-util.h" #include "util-spm.h" @@ -401,9 +402,14 @@ int DetectEngineInspectHttpMethod(DetectEngineCtx *de_ctx, if (tx == NULL || tx->request_method == NULL) continue; - r = DoInspectHttpMethod(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HMDMATCH], - (uint8_t *)bstr_ptr(tx->request_method), - bstr_len(tx->request_method)); + r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HMDMATCH], + f, + (uint8_t *)bstr_ptr(tx->request_method), + bstr_len(tx->request_method), + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HMD, NULL); + //r = DoInspectHttpMethod(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HMDMATCH], + //(uint8_t *)bstr_ptr(tx->request_method), + //bstr_len(tx->request_method)); if (r == 1) { break; } diff --git a/src/detect-engine-hrhd.c b/src/detect-engine-hrhd.c index b1044ead1ea..a2234110677 100644 --- a/src/detect-engine-hrhd.c +++ b/src/detect-engine-hrhd.c @@ -44,6 +44,7 @@ #include "detect-isdataat.h" #include "detect-bytetest.h" #include "detect-bytejump.h" +#include "detect-engine-content-inspection.h" #include "flow-util.h" #include "util-spm.h" @@ -421,9 +422,14 @@ int DetectEngineInspectHttpRawHeader(DetectEngineCtx *de_ctx, if (raw_headers == NULL) continue; - r = DoInspectHttpRawHeader(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HRHDMATCH], - (uint8_t *)bstr_ptr(raw_headers), - bstr_len(raw_headers)); + r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HRHDMATCH], + f, + (uint8_t *)bstr_ptr(raw_headers), + bstr_len(raw_headers), + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HRHD, NULL); + //r = DoInspectHttpRawHeader(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HRHDMATCH], + //(uint8_t *)bstr_ptr(raw_headers), + //bstr_len(raw_headers)); if (r == 1) { break; } diff --git a/src/detect-engine-hrud.c b/src/detect-engine-hrud.c index dc580a082be..a9a61c1ecde 100644 --- a/src/detect-engine-hrud.c +++ b/src/detect-engine-hrud.c @@ -44,6 +44,7 @@ #include "detect-isdataat.h" #include "detect-bytetest.h" #include "detect-bytejump.h" +#include "detect-engine-content-inspection.h" #include "flow-util.h" #include "util-spm.h" @@ -479,10 +480,15 @@ int DetectEngineInspectHttpRawUri(DetectEngineCtx *de_ctx, /* Inspect all the uricontents fetched on each * transaction at the app layer */ - r = DoInspectHttpRawUri(de_ctx, det_ctx, s, - s->sm_lists[DETECT_SM_LIST_HRUDMATCH], - (uint8_t *)bstr_ptr(tx->request_uri), - bstr_len(tx->request_uri)); + r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HRUDMATCH], + f, + (uint8_t *)bstr_ptr(tx->request_uri), + bstr_len(tx->request_uri), + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HRUD, NULL); + //r = DoInspectHttpRawUri(de_ctx, det_ctx, s, + // s->sm_lists[DETECT_SM_LIST_HRUDMATCH], + // (uint8_t *)bstr_ptr(tx->request_uri), + // bstr_len(tx->request_uri)); if (r == 1) { goto end; } diff --git a/src/detect-engine-hsbd.c b/src/detect-engine-hsbd.c index fa2debd36bb..59598ebfa08 100644 --- a/src/detect-engine-hsbd.c +++ b/src/detect-engine-hsbd.c @@ -46,6 +46,7 @@ #include "detect-bytetest.h" #include "detect-bytejump.h" #include "detect-byte-extract.h" +#include "detect-engine-content-inspection.h" #include "flow-util.h" #include "util-spm.h" @@ -580,8 +581,13 @@ int DetectEngineInspectHttpServerBody(DetectEngineCtx *de_ctx, if (hsbd_buffer == NULL) continue; - r = DoInspectHttpServerBody(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HSBDMATCH], - hsbd_buffer, hsbd_buffer_len); + r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HSBDMATCH], + f, + hsbd_buffer, + hsbd_buffer_len, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_HSBD, NULL); + //r = DoInspectHttpServerBody(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HSBDMATCH], + //hsbd_buffer, hsbd_buffer_len); if (r == 1) { break; } diff --git a/src/detect-engine-payload.c b/src/detect-engine-payload.c index 2da7ba62e0c..3136fb6fa63 100644 --- a/src/detect-engine-payload.c +++ b/src/detect-engine-payload.c @@ -38,6 +38,7 @@ #include "detect-bytejump.h" #include "detect-byte-extract.h" #include "detect-replace.h" +#include "detect-engine-content-inspection.h" #include "util-spm.h" #include "util-spm-bm.h" @@ -478,7 +479,10 @@ int DetectEngineInspectPacketPayload(DetectEngineCtx *de_ctx, det_ctx->replist = NULL; //det_ctx->flags |= DETECT_ENGINE_THREAD_CTX_INSPECTING_PACKET; - r = DoInspectPacketPayload(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_PMATCH], p, f, p->payload, p->payload_len); + r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_PMATCH], + f, p->payload, p->payload_len, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD, p); + //r = DoInspectPacketPayload(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_PMATCH], p, f, p->payload, p->payload_len); //det_ctx->flags &= ~DETECT_ENGINE_THREAD_CTX_INSPECTING_PACKET; if (r == 1) { SCReturnInt(1); @@ -517,10 +521,14 @@ int DetectEngineInspectStreamPayload(DetectEngineCtx *de_ctx, det_ctx->payload_offset = 0; det_ctx->discontinue_matching = 0; det_ctx->inspection_recursion_counter = 0; - det_ctx->flags |= DETECT_ENGINE_THREAD_CTX_INSPECTING_STREAM; + //det_ctx->flags |= DETECT_ENGINE_THREAD_CTX_INSPECTING_STREAM; - r = DoInspectPacketPayload(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_PMATCH], NULL, f, payload, payload_len); - det_ctx->flags &= ~DETECT_ENGINE_THREAD_CTX_INSPECTING_STREAM; + r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_PMATCH], + f, payload, payload_len, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_STREAM, NULL); + + //r = DoInspectPacketPayload(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_PMATCH], NULL, f, payload, payload_len); + //det_ctx->flags &= ~DETECT_ENGINE_THREAD_CTX_INSPECTING_STREAM; if (r == 1) { SCReturnInt(1); } diff --git a/src/detect-engine-uri.c b/src/detect-engine-uri.c index 7c965da14d7..8ec08df88d6 100644 --- a/src/detect-engine-uri.c +++ b/src/detect-engine-uri.c @@ -38,6 +38,7 @@ #include "detect-bytetest.h" #include "detect-bytejump.h" #include "detect-byte-extract.h" +#include "detect-engine-content-inspection.h" #include "flow-util.h" #include "util-spm.h" @@ -481,9 +482,14 @@ int DetectEngineInspectPacketUris(DetectEngineCtx *de_ctx, /* Inspect all the uricontents fetched on each * transaction at the app layer */ - r = DoInspectPacketUri(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_UMATCH], - (uint8_t *)bstr_ptr(tx->request_uri_normalized), - bstr_len(tx->request_uri_normalized)); + r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_UMATCH], + f, + (uint8_t *)bstr_ptr(tx->request_uri_normalized), + bstr_len(tx->request_uri_normalized), + DETECT_ENGINE_CONTENT_INSPECTION_MODE_URI, NULL); + //r = DoInspectPacketUri(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_UMATCH], + //(uint8_t *)bstr_ptr(tx->request_uri_normalized), + //bstr_len(tx->request_uri_normalized)); if (r == 1) { break; } diff --git a/src/detect-http-cookie.c b/src/detect-http-cookie.c index b8c5d8f45cd..067c9c492d0 100644 --- a/src/detect-http-cookie.c +++ b/src/detect-http-cookie.c @@ -148,7 +148,7 @@ static int DetectHttpCookieSetup (DetectEngineCtx *de_ctx, Signature *s, char *s if (cd->flags & DETECT_CONTENT_WITHIN || cd->flags & DETECT_CONTENT_DISTANCE) { SigMatch *pm = SigMatchGetLastSMFromLists(s, 4, DETECT_CONTENT, sm->prev, - DETECT_PCRE_HTTPCOOKIE, sm->prev); + DETECT_PCRE, sm->prev); if (pm != NULL) { /* pm is never NULL. So no NULL check */ if (pm->type == DETECT_CONTENT) { @@ -164,7 +164,7 @@ static int DetectHttpCookieSetup (DetectEngineCtx *de_ctx, Signature *s, char *s pm = SigMatchGetLastSMFromLists(s, 4, DETECT_AL_HTTP_COOKIE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], - DETECT_PCRE_HTTPCOOKIE, + DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_HTTP_COOKIE_RELATIVE_MISSING, "http_cookie with " diff --git a/src/detect-http-method.c b/src/detect-http-method.c index 9b97ae426e4..0fe7e2280ca 100644 --- a/src/detect-http-method.c +++ b/src/detect-http-method.c @@ -131,7 +131,7 @@ static int DetectHttpMethodSetup(DetectEngineCtx *de_ctx, Signature *s, char *st if (cd->flags & DETECT_CONTENT_WITHIN || cd->flags & DETECT_CONTENT_DISTANCE) { SigMatch *pm = SigMatchGetLastSMFromLists(s, 4, DETECT_CONTENT, sm->prev, - DETECT_PCRE_HTTPMETHOD, sm->prev); + DETECT_PCRE, sm->prev); if (pm != NULL) { /* pm is never NULL. So no NULL check */ if (pm->type == DETECT_CONTENT) { @@ -147,7 +147,7 @@ static int DetectHttpMethodSetup(DetectEngineCtx *de_ctx, Signature *s, char *st pm = SigMatchGetLastSMFromLists(s, 4, DETECT_AL_HTTP_METHOD, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], - DETECT_PCRE_HTTPMETHOD, + DETECT_PCRE, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH]); if (pm == NULL) { SCLogError(SC_ERR_HTTP_METHOD_RELATIVE_MISSING, "http_method with " @@ -155,7 +155,7 @@ static int DetectHttpMethodSetup(DetectEngineCtx *de_ctx, Signature *s, char *st "content, but none was found"); goto error; } - if (pm->type == DETECT_PCRE_HTTPMETHOD) { + if (pm->type == DETECT_PCRE) { DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx; tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT; } else { diff --git a/src/detect-pcre.c b/src/detect-pcre.c index 6ddd7ab3bc9..b63bb3428d7 100644 --- a/src/detect-pcre.c +++ b/src/detect-pcre.c @@ -1107,36 +1107,42 @@ static int DetectPcreSetup (DetectEngineCtx *de_ctx, Signature *s, char *regexst if (pd->flags & DETECT_PCRE_HEADER) { SCLogDebug("Header inspection modifier set"); s->flags |= SIG_FLAG_APPLAYER; + s->alproto = ALPROTO_HTTP; SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HHDMATCH); } else if (pd->flags & DETECT_PCRE_RAW_HEADER) { SCLogDebug("Raw header inspection modifier set"); s->flags |= SIG_FLAG_APPLAYER; + s->alproto = ALPROTO_HTTP; SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HRHDMATCH); } else if (pd->flags & DETECT_PCRE_COOKIE) { - sm->type = DETECT_PCRE_HTTPCOOKIE; + //sm->type = DETECT_PCRE_HTTPCOOKIE; SCLogDebug("Cookie inspection modifier set"); s->flags |= SIG_FLAG_APPLAYER; + s->alproto = ALPROTO_HTTP; SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HCDMATCH); } else if (pd->flags & DETECT_PCRE_METHOD) { - sm->type = DETECT_PCRE_HTTPMETHOD; + //sm->type = DETECT_PCRE_HTTPMETHOD; SCLogDebug("Method inspection modifier set"); s->flags |= SIG_FLAG_APPLAYER; + s->alproto = ALPROTO_HTTP; SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HMDMATCH); } else if (pd->flags & DETECT_PCRE_HTTP_CLIENT_BODY) { SCLogDebug("Request body inspection modifier set"); s->flags |= SIG_FLAG_APPLAYER; + s->alproto = ALPROTO_HTTP; AppLayerHtpEnableRequestBodyCallback(); SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HCBDMATCH); } else if (pd->flags & DETECT_PCRE_HTTP_SERVER_BODY) { SCLogDebug("Response body inspection modifier set"); s->flags |= SIG_FLAG_APPLAYER; + s->alproto = ALPROTO_HTTP; AppLayerHtpEnableResponseBodyCallback(); SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HSBDMATCH); @@ -1222,7 +1228,7 @@ static int DetectPcreSetup (DetectEngineCtx *de_ctx, Signature *s, char *regexst SCReturnInt(0); } - prev_sm = SigMatchGetLastSMFromLists(s, 28, + prev_sm = SigMatchGetLastSMFromLists(s, 24, DETECT_CONTENT, sm->prev, DETECT_URICONTENT, sm->prev, DETECT_AL_HTTP_CLIENT_BODY, sm->prev, @@ -1233,8 +1239,6 @@ static int DetectPcreSetup (DetectEngineCtx *de_ctx, Signature *s, char *regexst DETECT_AL_HTTP_COOKIE, sm->prev, DETECT_AL_HTTP_METHOD, sm->prev, DETECT_PCRE, sm->prev, - DETECT_PCRE_HTTPCOOKIE, sm->prev, - DETECT_PCRE_HTTPMETHOD, sm->prev, DETECT_AL_HTTP_STAT_MSG, sm->prev, DETECT_AL_HTTP_STAT_CODE, sm->prev); if (prev_sm == NULL) { @@ -1281,8 +1285,6 @@ static int DetectPcreSetup (DetectEngineCtx *de_ctx, Signature *s, char *regexst break; case DETECT_PCRE: - case DETECT_PCRE_HTTPCOOKIE: - case DETECT_PCRE_HTTPMETHOD: pe = (DetectPcreData *) prev_sm->ctx; if (pe == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "pcre not setup properly"); diff --git a/src/detect-within.c b/src/detect-within.c index adde569fe7c..c5beb3a5a8e 100644 --- a/src/detect-within.c +++ b/src/detect-within.c @@ -730,14 +730,14 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi /* reassigning pm */ pm = SigMatchGetLastSMFromLists(s, 4, DETECT_AL_HTTP_METHOD, pm->prev, - DETECT_PCRE_HTTPMETHOD, pm->prev); + DETECT_PCRE, pm->prev); if (pm == NULL) { SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for http_method " "needs preceeding http_method content"); goto error; } - if (pm->type == DETECT_PCRE_HTTPMETHOD) { + if (pm->type == DETECT_PCRE) { DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx; tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT; } else { @@ -798,14 +798,14 @@ static int DetectWithinSetup (DetectEngineCtx *de_ctx, Signature *s, char *withi /* reassigning pm */ pm = SigMatchGetLastSMFromLists(s, 4, DETECT_AL_HTTP_COOKIE, pm->prev, - DETECT_PCRE_HTTPCOOKIE, pm->prev); + DETECT_PCRE, pm->prev); if (pm == NULL) { SCLogError(SC_ERR_DISTANCE_MISSING_CONTENT, "distance for http_cookie " "needs preceeding http_cookie content"); goto error; } - if (pm->type == DETECT_PCRE_HTTPCOOKIE) { + if (pm->type == DETECT_PCRE) { DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx; tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT; } else { diff --git a/src/detect.c b/src/detect.c index e33976bf3f2..0af421be0e1 100644 --- a/src/detect.c +++ b/src/detect.c @@ -2205,9 +2205,7 @@ static int SignatureCreateMask(Signature *s) { case DETECT_AL_HTTP_URI: case DETECT_AL_HTTP_RAW_URI: case DETECT_PCRE_HTTPBODY: - case DETECT_PCRE_HTTPCOOKIE: case DETECT_PCRE_HTTPHEADER: - case DETECT_PCRE_HTTPMETHOD: s->mask |= SIG_MASK_REQUIRE_HTTP_STATE; SCLogDebug("sig requires dce http state"); break; diff --git a/src/detect.h b/src/detect.h index 7e8590694b1..717f603cc3f 100644 --- a/src/detect.h +++ b/src/detect.h @@ -694,6 +694,7 @@ typedef struct DetectionEngineThreadCtx_ { /** offset into the payload of the last match by: * content, pcre, etc */ + uint32_t buffer_offset; uint32_t payload_offset; /* used by pcre match function alone */ uint32_t pcre_match_start_offset;