From e15995e2d2fafd041c65cc9477cf682a7d12444b Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Tue, 26 May 2020 14:34:57 +0200 Subject: [PATCH] detect: store detect flags in AppLayerTxData --- rust/src/applayer.rs | 6 +++++ src/app-layer-parser.c | 55 +++++++++++++++++++++++++++++++++------ src/detect-engine-state.h | 1 + src/detect.c | 31 +++++++++++++++++++--- 4 files changed, 81 insertions(+), 12 deletions(-) diff --git a/rust/src/applayer.rs b/rust/src/applayer.rs index 7e4d3732b5..1ed11b36e1 100644 --- a/rust/src/applayer.rs +++ b/rust/src/applayer.rs @@ -57,6 +57,10 @@ pub struct AppLayerTxData { /// logger flags for tx logging api logged: LoggerFlags, + + /// detection engine flags for use by detection engine + detect_flags_ts: u64, + detect_flags_tc: u64, } impl AppLayerTxData { @@ -64,6 +68,8 @@ impl AppLayerTxData { Self { config: AppLayerTxConfig::new(), logged: LoggerFlags::new(), + detect_flags_ts: 0, + detect_flags_tc: 0, } } } diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index dae0d24877..e96c827dab 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -745,6 +745,42 @@ uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint SCReturnCT(pstate->inspect_id[direction & STREAM_TOSERVER ? 0 : 1], "uint64_t"); } +static inline uint64_t GetTxDetectFlags(const uint8_t ipproto, const AppProto alproto, void *tx, const uint8_t dir) +{ + uint64_t detect_flags; + AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx); + if (txd != NULL) { + detect_flags = (dir & STREAM_TOSERVER) ? txd->detect_flags_ts : txd->detect_flags_tc; + } else { + detect_flags = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, dir); + } + return detect_flags; +} + +static inline void SetTxDetectFlags(const uint8_t ipproto, const AppProto alproto, void *tx, const uint8_t dir, const uint64_t detect_flags) +{ + AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx); + if (txd != NULL) { + if (dir & STREAM_TOSERVER) { + txd->detect_flags_ts = detect_flags; + } else { + txd->detect_flags_tc = detect_flags; + } + } else { + AppLayerParserSetTxDetectFlags(ipproto, alproto, tx, dir, detect_flags); + } +} + +static inline uint32_t GetTxLogged(const Flow *f, void *alstate, void *tx) +{ + AppLayerTxData *txd = AppLayerParserGetTxData(f->proto, f->alproto, tx); + if (txd) { + return txd->logged.flags; + } else { + return AppLayerParserGetTxLogged(f, alstate, tx); + } +} + void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *pstate, void *alstate, const uint8_t flags, bool tag_txs_as_inspected) @@ -780,10 +816,10 @@ void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *p break; if (tag_txs_as_inspected) { - uint64_t detect_flags = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, flags); + uint64_t detect_flags = GetTxDetectFlags(ipproto, alproto, tx, flags); if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) { detect_flags |= APP_LAYER_TX_INSPECTED_FLAG; - AppLayerParserSetTxDetectFlags(ipproto, alproto, tx, flags, detect_flags); + SetTxDetectFlags(ipproto, alproto, tx, flags, detect_flags); SCLogDebug("%p/%"PRIu64" in-order tx is done for direction %s. Flag %016"PRIx64, tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags); } @@ -817,10 +853,10 @@ void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *p if (state_progress < state_done_progress) break; - uint64_t detect_flags = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, flags); + uint64_t detect_flags = GetTxDetectFlags(ipproto, alproto, tx, flags); if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) { detect_flags |= APP_LAYER_TX_INSPECTED_FLAG; - AppLayerParserSetTxDetectFlags(ipproto, alproto, tx, flags, detect_flags); + SetTxDetectFlags(ipproto, alproto, tx, flags, detect_flags); SCLogDebug("%p/%"PRIu64" out of order tx is done for direction %s. Flag %016"PRIx64, tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags); @@ -895,7 +931,7 @@ void AppLayerParserTransactionsCleanup(Flow *f) if (unlikely(p->StateTransactionFree == NULL)) SCReturn; - const bool has_tx_detect_flags = (p->GetTxDetectFlags != NULL); + const bool has_tx_detect_flags = (p->GetTxDetectFlags != NULL || p->GetTxData != NULL); const uint8_t ipproto = f->proto; const AppProto alproto = f->alproto; void * const alstate = f->alstate; @@ -942,7 +978,7 @@ void AppLayerParserTransactionsCleanup(Flow *f) } if (has_tx_detect_flags) { if (f->sgh_toserver != NULL) { - uint64_t detect_flags_ts = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, STREAM_TOSERVER); + uint64_t detect_flags_ts = GetTxDetectFlags(ipproto, alproto, tx, STREAM_TOSERVER); if (!(detect_flags_ts & APP_LAYER_TX_INSPECTED_FLAG)) { SCLogDebug("%p/%"PRIu64" skipping: TS inspect not done: ts:%"PRIx64, tx, i, detect_flags_ts); @@ -951,7 +987,7 @@ void AppLayerParserTransactionsCleanup(Flow *f) } } if (f->sgh_toclient != NULL) { - uint64_t detect_flags_tc = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, STREAM_TOCLIENT); + uint64_t detect_flags_tc = GetTxDetectFlags(ipproto, alproto, tx, STREAM_TOCLIENT); if (!(detect_flags_tc & APP_LAYER_TX_INSPECTED_FLAG)) { SCLogDebug("%p/%"PRIu64" skipping: TC inspect not done: tc:%"PRIx64, tx, i, detect_flags_tc); @@ -961,7 +997,7 @@ void AppLayerParserTransactionsCleanup(Flow *f) } } if (logger_expectation != 0) { - LoggerId tx_logged = AppLayerParserGetTxLogged(f, alstate, tx); + LoggerId tx_logged = GetTxLogged(f, alstate, tx); if (tx_logged != logger_expectation) { SCLogDebug("%p/%"PRIu64" skipping: logging not done: want:%"PRIx32", have:%"PRIx32, tx, i, logger_expectation, tx_logged); @@ -1147,6 +1183,9 @@ bool AppLayerParserSupportsTxDetectFlags(AppProto alproto) if (alp_ctx.ctxs[p][alproto].GetTxDetectFlags != NULL) { SCReturnBool(true); } + if (alp_ctx.ctxs[p][alproto].GetTxData != NULL) { + SCReturnBool(true); + } } SCReturnBool(false); } diff --git a/src/detect-engine-state.h b/src/detect-engine-state.h index 154f8bbaf3..4491105619 100644 --- a/src/detect-engine-state.h +++ b/src/detect-engine-state.h @@ -97,6 +97,7 @@ typedef struct DetectEngineState_ { typedef struct DetectTransaction_ { void *tx_ptr; const uint64_t tx_id; + struct AppLayerTxData *tx_data_ptr; DetectEngineStateDirection *de_state; const uint64_t detect_flags; /* detect flags get/set from/to applayer */ uint64_t prefilter_flags; /* prefilter flags for direction, to be updated by prefilter code */ diff --git a/src/detect.c b/src/detect.c index 9aa0a279ac..fe0e55406e 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1233,12 +1233,18 @@ static DetectTransaction GetDetectTx(const uint8_t ipproto, const AppProto alpro void *alstate, const uint64_t tx_id, void *tx_ptr, const int tx_end_state, const uint8_t flow_flags) { - const uint64_t detect_flags = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx_ptr, flow_flags); + uint64_t detect_flags; + AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx_ptr); + if (txd != NULL) { + detect_flags = (flow_flags & STREAM_TOSERVER) ? txd->detect_flags_ts : txd->detect_flags_tc; + } else { + detect_flags = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx_ptr, flow_flags); + } if (detect_flags & APP_LAYER_TX_INSPECTED_FLAG) { SCLogDebug("%"PRIu64" tx already fully inspected for %s. Flags %016"PRIx64, tx_id, flow_flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags); - DetectTransaction no_tx = { NULL, 0, NULL, 0, 0, 0, 0, 0, }; + DetectTransaction no_tx = { NULL, 0, NULL, NULL, 0, 0, 0, 0, 0, }; return no_tx; } @@ -1251,6 +1257,7 @@ static DetectTransaction GetDetectTx(const uint8_t ipproto, const AppProto alpro DetectTransaction tx = { .tx_ptr = tx_ptr, .tx_id = tx_id, + .tx_data_ptr = (struct AppLayerTxData *)txd, .de_state = tx_dir_state, .detect_flags = detect_flags, .prefilter_flags = prefilter_flags, @@ -1261,6 +1268,22 @@ static DetectTransaction GetDetectTx(const uint8_t ipproto, const AppProto alpro return tx; } +static inline void StoreDetectFlags(DetectTransaction *tx, const uint8_t flow_flags, + const uint8_t ipproto, const AppProto alproto, const uint64_t detect_flags) +{ + AppLayerTxData *txd = (AppLayerTxData *)tx->tx_data_ptr; + if (txd != NULL) { + if (flow_flags & STREAM_TOSERVER) { + txd->detect_flags_ts = detect_flags; + } else { + txd->detect_flags_tc = detect_flags; + } + } else { + AppLayerParserSetTxDetectFlags(ipproto, alproto, tx->tx_ptr, + flow_flags, detect_flags); + } +} + static void DetectRunTx(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, @@ -1501,8 +1524,8 @@ static void DetectRunTx(ThreadVars *tv, new_detect_flags |= tx.detect_flags; SCLogDebug("%p/%"PRIu64" Storing new flags %016"PRIx64" (was %016"PRIx64")", tx.tx_ptr, tx.tx_id, new_detect_flags, tx.detect_flags); - AppLayerParserSetTxDetectFlags(ipproto, alproto, tx.tx_ptr, - flow_flags, new_detect_flags); + + StoreDetectFlags(&tx, flow_flags, ipproto, alproto, new_detect_flags); } next: InspectionBufferClean(det_ctx);