From 0f708d427bbee9708601a8a0557af247a4942f9a Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Thu, 27 Oct 2016 17:41:38 +0200 Subject: [PATCH] pkt-var: abuse flowvar postmatch logic for pktvars Flowvars were already using a temporary store in the detect thread ctx. Use the same facility for pktvars. The reasons are: 1. packet is not always available, e.g. when running pcre on http buffers. 2. setting of vars should be done post match. Until now it was also possible that it is done on a partial match. --- src/detect-engine-state.c | 2 +- src/detect-flowvar.c | 37 +++++++++++++++++++++---------------- src/detect-flowvar.h | 16 ++++++++-------- src/detect-pcre.c | 23 ++++++++++++++--------- src/detect.c | 22 ++++++++++------------ src/detect.h | 15 ++++++++------- 6 files changed, 62 insertions(+), 53 deletions(-) diff --git a/src/detect-engine-state.c b/src/detect-engine-state.c index e25accf3fd..687e3b397b 100644 --- a/src/detect-engine-state.c +++ b/src/detect-engine-state.c @@ -715,7 +715,7 @@ static int DoInspectItem(ThreadVars *tv, SCLogDebug("MATCH: tx %u packet %u", (uint)inspect_tx_id, (uint)p->pcap_cnt); } - DetectFlowvarProcessList(det_ctx, f); + DetectVarProcessList(det_ctx, f, p); return 1; } diff --git a/src/detect-flowvar.c b/src/detect-flowvar.c index c5f838bb6c..b0c30d4099 100644 --- a/src/detect-flowvar.c +++ b/src/detect-flowvar.c @@ -33,6 +33,7 @@ #include "threads.h" #include "flow.h" #include "flow-var.h" +#include "pkt-var.h" #include "detect-flowvar.h" #include "util-spm.h" @@ -194,10 +195,10 @@ error: /** \brief Store flowvar in det_ctx so we can exec it post-match */ -int DetectFlowvarStoreMatch(DetectEngineThreadCtx *det_ctx, uint32_t idx, +int DetectVarStoreMatch(DetectEngineThreadCtx *det_ctx, uint32_t idx, uint8_t *buffer, uint16_t len, int type) { - DetectFlowvarList *fs = det_ctx->flowvarlist; + DetectVarList *fs = det_ctx->varlist; /* first check if we have had a previous match for this idx */ for ( ; fs != NULL; fs = fs->next) { @@ -216,8 +217,8 @@ int DetectFlowvarStoreMatch(DetectEngineThreadCtx *det_ctx, uint32_t idx, fs->idx = idx; - fs->next = det_ctx->flowvarlist; - det_ctx->flowvarlist = fs; + fs->next = det_ctx->varlist; + det_ctx->varlist = fs; } fs->len = len; @@ -266,29 +267,33 @@ static int DetectFlowvarPostMatch(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx) { - DetectFlowvarList *fs, *prev; + DetectVarList *fs, *prev; const DetectFlowvarData *fd; - if (det_ctx->flowvarlist == NULL || p->flow == NULL) + if (det_ctx->varlist == NULL) return 1; fd = (const DetectFlowvarData *)ctx; prev = NULL; - fs = det_ctx->flowvarlist; + fs = det_ctx->varlist; while (fs != NULL) { if (fd->idx == fs->idx) { SCLogDebug("adding to the flow %u:", fs->idx); //PrintRawDataFp(stdout, fs->buffer, fs->len); - FlowVarAddStrNoLock(p->flow, fs->idx, fs->buffer, fs->len); - /* memory at fs->buffer is now the responsibility of - * the flowvar code. */ + if (fs->type == DETECT_VAR_TYPE_FLOW_POSTMATCH && p && p->flow) { + FlowVarAddStrNoLock(p->flow, fs->idx, fs->buffer, fs->len); + /* memory at fs->buffer is now the responsibility of + * the flowvar code. */ + } else if (fs->type == DETECT_VAR_TYPE_PKT_POSTMATCH && p) { + PktVarAdd(p, fs->idx, fs->buffer, fs->len); + } - if (fs == det_ctx->flowvarlist) { - det_ctx->flowvarlist = fs->next; + if (fs == det_ctx->varlist) { + det_ctx->varlist = fs->next; SCFree(fs); - fs = det_ctx->flowvarlist; + fs = det_ctx->varlist; } else { prev->next = fs->next; SCFree(fs); @@ -307,14 +312,14 @@ static int DetectFlowvarPostMatch(ThreadVars *tv, * - enforce storage for type ALWAYS (vars set from lua) * Only called from DetectFlowvarProcessList() when flowvarlist is not NULL . */ -void DetectFlowvarProcessListInternal(DetectFlowvarList *fs, Flow *f) +void DetectVarProcessListInternal(DetectVarList *fs, Flow *f, Packet *p) { - DetectFlowvarList *next; + DetectVarList *next; do { next = fs->next; - if (fs->type == DETECT_FLOWVAR_TYPE_ALWAYS) { + if (fs->type == DETECT_VAR_TYPE_ALWAYS) { SCLogDebug("adding to the flow %u:", fs->idx); //PrintRawDataFp(stdout, fs->buffer, fs->len); diff --git a/src/detect-flowvar.h b/src/detect-flowvar.h index 32222372b4..59edfc80bc 100644 --- a/src/detect-flowvar.h +++ b/src/detect-flowvar.h @@ -36,18 +36,18 @@ typedef struct DetectFlowvarData_ { void DetectFlowvarRegister (void); int DetectFlowvarPostMatchSetup(Signature *s, uint32_t idx); -int DetectFlowvarStoreMatch(DetectEngineThreadCtx *, uint32_t, uint8_t *, uint16_t, int); +int DetectVarStoreMatch(DetectEngineThreadCtx *, uint32_t, uint8_t *, uint16_t, int); /* For use only by DetectFlowvarProcessList() */ -void DetectFlowvarProcessListInternal(DetectFlowvarList *fs, Flow *f); -static inline void DetectFlowvarProcessList(DetectEngineThreadCtx *det_ctx, Flow *f) +void DetectVarProcessListInternal(DetectVarList *fs, Flow *f, Packet *p); +static inline void DetectVarProcessList(DetectEngineThreadCtx *det_ctx, Flow *f, Packet *p) { - DetectFlowvarList *fs = det_ctx->flowvarlist; + DetectVarList *fs = det_ctx->varlist; - SCLogDebug("flow %p det_ctx->flowvarlist %p", f, fs); - if (f && fs != NULL) { - det_ctx->flowvarlist = NULL; - DetectFlowvarProcessListInternal(fs, f); + SCLogDebug("flow %p det_ctx->varlist %p", f, fs); + if ((f || p) && fs != NULL) { + det_ctx->varlist = NULL; + DetectVarProcessListInternal(fs, f, p); } } diff --git a/src/detect-pcre.c b/src/detect-pcre.c index 1fe8af2758..0d0a46756e 100644 --- a/src/detect-pcre.c +++ b/src/detect-pcre.c @@ -219,21 +219,28 @@ int DetectPcrePayloadMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, if (ret > 1 && pe->idx != 0) { uint8_t x; for (x = 0; x < pe->idx; x++) { - SCLogDebug("capturing"); + SCLogDebug("capturing %u", x); const char *str_ptr; ret = pcre_get_substring((char *)ptr, ov, MAX_SUBSTRINGS, x+1, &str_ptr); if (unlikely(ret == 0)) continue; - if (pe->captypes[x] == VAR_TYPE_PKT_VAR && p != NULL) { - PktVarAdd(p, pe->capids[x], (uint8_t *)str_ptr, ret); + SCLogDebug("data %p/%u, type %u id %u p %p", + str_ptr, ret, pe->captypes[x], pe->capids[x], p); + + if (pe->captypes[x] == VAR_TYPE_PKT_VAR) { + /* store max 64k. Errors are ignored */ + capture_len = (ret < 0xffff) ? (uint16_t)ret : 0xffff; + (void)DetectVarStoreMatch(det_ctx, pe->capids[x], + (uint8_t *)str_ptr, capture_len, + DETECT_VAR_TYPE_PKT_POSTMATCH); } else if (pe->captypes[x] == VAR_TYPE_FLOW_VAR && f != NULL) { /* store max 64k. Errors are ignored */ capture_len = (ret < 0xffff) ? (uint16_t)ret : 0xffff; - (void)DetectFlowvarStoreMatch(det_ctx, pe->capids[x], + (void)DetectVarStoreMatch(det_ctx, pe->capids[x], (uint8_t *)str_ptr, capture_len, - DETECT_FLOWVAR_TYPE_POSTMATCH); + DETECT_VAR_TYPE_FLOW_POSTMATCH); } } } @@ -717,10 +724,8 @@ static int DetectPcreSetup (DetectEngineCtx *de_ctx, Signature *s, char *regexst uint8_t x; for (x = 0; x < pd->idx; x++) { - if (pd->captypes[x] == VAR_TYPE_FLOW_VAR) { - if (DetectFlowvarPostMatchSetup(s, pd->capids[x]) < 0) - goto error_nofree; - } + if (DetectFlowvarPostMatchSetup(s, pd->capids[x]) < 0) + goto error_nofree; } if (!(pd->flags & DETECT_PCRE_RELATIVE)) diff --git a/src/detect.c b/src/detect.c index 3797a2272c..9207b537c0 100644 --- a/src/detect.c +++ b/src/detect.c @@ -549,21 +549,19 @@ int SigMatchSignaturesRunPostMatch(ThreadVars *tv, const Signature *s) { /* run the packet match functions */ - if (s->sm_arrays[DETECT_SM_LIST_POSTMATCH] != NULL) { + SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_POSTMATCH]; + if (smd != NULL) { KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_POSTMATCH); - SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_POSTMATCH]; SCLogDebug("running match functions, sm %p", smd); - if (smd != NULL) { - while (1) { - KEYWORD_PROFILING_START; - (void)sigmatch_table[smd->type].Match(tv, det_ctx, p, s, smd->ctx); - KEYWORD_PROFILING_END(det_ctx, smd->type, 1); - if (smd->is_last) - break; - smd++; - } + while (1) { + KEYWORD_PROFILING_START; + (void)sigmatch_table[smd->type].Match(tv, det_ctx, p, s, smd->ctx); + KEYWORD_PROFILING_END(det_ctx, smd->type, 1); + if (smd->is_last) + break; + smd++; } } @@ -1472,7 +1470,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh } alerts++; next: - DetectFlowvarProcessList(det_ctx, pflow); + DetectVarProcessList(det_ctx, pflow, p); DetectReplaceFree(det_ctx); RULE_PROFILING_END(det_ctx, s, smatch, p); diff --git a/src/detect.h b/src/detect.h index fd609f056b..2394ab442e 100644 --- a/src/detect.h +++ b/src/detect.h @@ -490,20 +490,21 @@ typedef struct DetectReplaceList_ { } DetectReplaceList; /** only execute flowvar storage if rule matched */ -#define DETECT_FLOWVAR_TYPE_POSTMATCH 1 +#define DETECT_VAR_TYPE_FLOW_POSTMATCH 1 +#define DETECT_VAR_TYPE_PKT_POSTMATCH 2 /** execute flowvar storage even if rule doesn't match (for lua) */ -#define DETECT_FLOWVAR_TYPE_ALWAYS 2 +#define DETECT_VAR_TYPE_ALWAYS 3 /** list for flowvar store candidates, to be stored from * post-match function */ -typedef struct DetectFlowvarList_ { +typedef struct DetectVarList_ { uint32_t idx; /**< flowvar name idx */ uint16_t len; /**< data len */ int type; /**< type of store candidate POSTMATCH or ALWAYS */ uint8_t *buffer; /**< alloc'd buffer, may be freed by post-match, post-non-match */ - struct DetectFlowvarList_ *next; -} DetectFlowvarList; + struct DetectVarList_ *next; +} DetectVarList; typedef struct DetectEngineIPOnlyThreadCtx_ { uint8_t *sig_match_array; /* bit array of sig nums */ @@ -877,8 +878,8 @@ typedef struct DetectEngineThreadCtx_ { /* string to replace */ DetectReplaceList *replist; - /* flowvars to store in post match function */ - DetectFlowvarList *flowvarlist; + /* vars to store in post match function */ + DetectVarList *varlist; /* Array in which the filestore keyword stores file id and tx id. If the * full signature matches, these are processed by a post-match filestore -- 2.47.2