From: Victor Julien Date: Fri, 3 May 2019 12:02:46 +0000 (+0200) Subject: detect/dnp3: add dnp3.data with v2 api support X-Git-Tag: suricata-5.0.0-rc1~515 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=752bb1c41072cf1cedbe8ea9a621eb66f49c48ba;p=thirdparty%2Fsuricata.git detect/dnp3: add dnp3.data with v2 api support Adds MPM support as well. Add TxDetectFlags support to the parser to avoid duplicate matches. --- diff --git a/src/app-layer-dnp3.c b/src/app-layer-dnp3.c index 7f27ce4f54..723f2706de 100644 --- a/src/app-layer-dnp3.c +++ b/src/app-layer-dnp3.c @@ -1568,6 +1568,27 @@ int DNP3PrefixIsSize(uint8_t prefix_code) } } +static uint64_t DNP3GetTxDetectFlags(void *vtx, uint8_t dir) +{ + DNP3Transaction *tx = (DNP3Transaction *)vtx; + if (dir & STREAM_TOSERVER) { + return tx->detect_flags_ts; + } else { + return tx->detect_flags_tc; + } +} + +static void DNP3SetTxDetectFlags(void *vtx, uint8_t dir, uint64_t detect_flags) +{ + DNP3Transaction *tx = (DNP3Transaction *)vtx; + if (dir & STREAM_TOSERVER) { + tx->detect_flags_ts = detect_flags; + } else { + tx->detect_flags_tc = detect_flags; + } + return; +} + /** * \brief Register the DNP3 application protocol parser. */ @@ -1618,6 +1639,8 @@ void RegisterDNP3Parsers(void) DNP3GetEvents); AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTxDetectState, DNP3SetTxDetectState); + AppLayerParserRegisterDetectFlagsFuncs(IPPROTO_TCP, ALPROTO_DNP3, + DNP3GetTxDetectFlags, DNP3SetTxDetectFlags); AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTx); AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTxCnt); diff --git a/src/app-layer-dnp3.h b/src/app-layer-dnp3.h index 13cebc7478..7519b92ff8 100644 --- a/src/app-layer-dnp3.h +++ b/src/app-layer-dnp3.h @@ -207,6 +207,10 @@ typedef TAILQ_HEAD(DNP3ObjectList_, DNP3Object_) DNP3ObjectList; * \brief DNP3 transaction. */ typedef struct DNP3Transaction_ { + /** detection engine flags */ + uint64_t detect_flags_ts; + uint64_t detect_flags_tc; + uint64_t tx_num; /**< Internal transaction ID. */ uint32_t logged; /**< Flags indicating which loggers have logged this tx. */ diff --git a/src/detect-dnp3.c b/src/detect-dnp3.c index b035673507..2ff1b32e95 100644 --- a/src/detect-dnp3.c +++ b/src/detect-dnp3.c @@ -23,6 +23,8 @@ #include "detect-parse.h" #include "detect-dnp3.h" #include "detect-engine.h" +#include "detect-engine-mpm.h" +#include "detect-engine-prefilter.h" #include "detect-engine-content-inspection.h" #include "app-layer-dnp3.h" @@ -141,30 +143,35 @@ static char *TrimString(char *str) return str; } -static int DetectEngineInspectDNP3Data(ThreadVars *tv, DetectEngineCtx *de_ctx, - DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, - Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id) +static InspectionBuffer *GetDNP3Data(DetectEngineThreadCtx *det_ctx, + const DetectEngineTransforms *transforms, + Flow *_f, const uint8_t flow_flags, + void *txv, const int list_id) { - SCEnter(); - DNP3Transaction *tx = (DNP3Transaction *)txv; - - int r = 0; + SCLogDebug("list_id %d", list_id); + InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); + if (buffer->inspect == NULL) { + DNP3Transaction *tx = (DNP3Transaction *)txv; + SCLogDebug("tx %p", tx); + + const uint8_t *data = NULL; + uint32_t data_len = 0; + + if (flow_flags & STREAM_TOSERVER) { + data = tx->request_buffer; + data_len = tx->request_buffer_len; + } else if (flow_flags & STREAM_TOCLIENT) { + data = tx->response_buffer; + data_len = tx->response_buffer_len; + } + if (data == NULL || data_len == 0) + return NULL; - /* Content match - should probably be put into its own file. */ - if (flags & STREAM_TOSERVER && tx->request_buffer != NULL) { - r = DetectEngineContentInspection(de_ctx, det_ctx, s, - smd, NULL, f, tx->request_buffer, - tx->request_buffer_len, 0, DETECT_CI_FLAGS_SINGLE, - DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE); + SCLogDebug("tx %p data %p data_len %u", tx, data, data_len); + InspectionBufferSetup(buffer, data, data_len); + InspectionBufferApplyTransforms(buffer, transforms); } - else if (flags & STREAM_TOCLIENT && tx->response_buffer != NULL) { - r = DetectEngineContentInspection(de_ctx, det_ctx, s, - smd, NULL, f, tx->response_buffer, - tx->response_buffer_len, 0, DETECT_CI_FLAGS_SINGLE, - DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE); - } - - SCReturnInt(r); + return buffer; } static int DetectEngineInspectDNP3(ThreadVars *tv, DetectEngineCtx *de_ctx, @@ -533,7 +540,9 @@ static int DetectDNP3DataSetup(DetectEngineCtx *de_ctx, Signature *s, const char if (DetectSignatureSetAppProto(s, ALPROTO_DNP3) != 0) return -1; - DetectBufferSetActiveList(s, g_dnp3_data_buffer_id); + if (DetectBufferSetActiveList(s, g_dnp3_data_buffer_id) != 0) + return -1; + SCReturnInt(0); } @@ -541,21 +550,29 @@ static void DetectDNP3DataRegister(void) { SCEnter(); - sigmatch_table[DETECT_AL_DNP3DATA].name = "dnp3_data"; - sigmatch_table[DETECT_AL_DNP3DATA].Match = NULL; + sigmatch_table[DETECT_AL_DNP3DATA].name = "dnp3.data"; + sigmatch_table[DETECT_AL_DNP3DATA].alias = "dnp3_data"; sigmatch_table[DETECT_AL_DNP3DATA].Setup = DetectDNP3DataSetup; - sigmatch_table[DETECT_AL_DNP3DATA].Free = NULL; sigmatch_table[DETECT_AL_DNP3DATA].RegisterTests = DetectDNP3DataRegisterTests; - sigmatch_table[DETECT_AL_DNP3DATA].flags |= SIGMATCH_NOOPT; + sigmatch_table[DETECT_AL_DNP3DATA].flags |= SIGMATCH_NOOPT|SIGMATCH_INFO_STICKY_BUFFER; - DetectAppLayerInspectEngineRegister("dnp3_data", + DetectAppLayerInspectEngineRegister2("dnp3_data", ALPROTO_DNP3, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectDNP3Data); - DetectAppLayerInspectEngineRegister("dnp3_data", + DetectEngineInspectBufferGeneric, + GetDNP3Data); + DetectAppLayerMpmRegister2("dnp3_data", SIG_FLAG_TOSERVER, 2, + PrefilterGenericMpmRegister, GetDNP3Data, + ALPROTO_DNP3, 0); + + DetectAppLayerInspectEngineRegister2("dnp3_data", ALPROTO_DNP3, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectDNP3Data); + DetectEngineInspectBufferGeneric, + GetDNP3Data); + DetectAppLayerMpmRegister2("dnp3_data", SIG_FLAG_TOCLIENT, 2, + PrefilterGenericMpmRegister, GetDNP3Data, + ALPROTO_DNP3, 0); g_dnp3_data_buffer_id = DetectBufferTypeGetByName("dnp3_data"); SCReturn;