docs/detect: document keywords, lists and helpers for dnp3 detect implementation

pull/16366/head
1bnBattuta 3 weeks ago
parent 698eb42f06
commit 5791f6ba3f

@ -15,6 +15,19 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
/**
* \file
*
* DNP3 rule keywords:
*
* dnp3.data sticky buffer: the reassembled application data
* dnp3_func application function code (uint8, names allowed)
* dnp3_ind internal indication flags, responses only (uint16)
* dnp3_obj object group and variation: dnp3_obj:<group>,<variation>
*
* Each keyword also has a dotted or underscored alias.
*/
#include "suricata-common.h" #include "suricata-common.h"
#include "stream.h" #include "stream.h"
@ -32,15 +45,16 @@
#include "app-layer-dnp3.h" #include "app-layer-dnp3.h"
#include "util-byte.h" #include "util-byte.h"
/* list ids: "dnp3" (func and obj), "dnp3_data", "dnp3_ind" */
static int g_dnp3_match_buffer_id = 0; static int g_dnp3_match_buffer_id = 0;
static int g_dnp3_data_buffer_id = 0; static int g_dnp3_data_buffer_id = 0;
static int g_dnp3_ind_buffer_id = 0; static int g_dnp3_ind_buffer_id = 0;
/** /**
* The detection struct. * dnp3_obj match data.
*/ */
typedef struct DetectDNP3_ { typedef struct DetectDNP3_ {
/* Object info for object detection. */ /* Object to look for in the transaction. */
uint8_t obj_group; uint8_t obj_group;
uint8_t obj_variation; uint8_t obj_variation;
} DetectDNP3; } DetectDNP3;
@ -50,6 +64,9 @@ static void DetectDNP3FuncRegisterTests(void);
static void DetectDNP3ObjRegisterTests(void); static void DetectDNP3ObjRegisterTests(void);
#endif #endif
/** \brief dnp3.data buffer getter: the tx's reassembled application
* data, for requests to server and responses to client only.
* \return the buffer, or NULL if wrong direction or no data */
static InspectionBuffer *GetDNP3Data(DetectEngineThreadCtx *det_ctx, static InspectionBuffer *GetDNP3Data(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, const DetectEngineTransforms *transforms,
Flow *_f, const uint8_t flow_flags, Flow *_f, const uint8_t flow_flags,
@ -82,6 +99,8 @@ static void DetectDNP3FuncFree(DetectEngineCtx *de_ctx, void *ptr)
SCDetectU8Free(ptr); SCDetectU8Free(ptr);
} }
/** \brief dnp3_func setup: parse a uint8 expression or function name.
* \retval 0 ok, -1 error */
static int DetectDNP3FuncSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str) static int DetectDNP3FuncSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
{ {
SCEnter(); SCEnter();
@ -113,6 +132,8 @@ static void DetectDNP3IndFree(DetectEngineCtx *de_ctx, void *ptr)
SCDetectU16Free(ptr); SCDetectU16Free(ptr);
} }
/** \brief dnp3_ind setup: parse a uint16 expression or flag names.
* \retval 0 ok, -1 error */
static int DetectDNP3IndSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str) static int DetectDNP3IndSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
{ {
SCEnter(); SCEnter();
@ -140,13 +161,15 @@ error:
} }
/** /**
* \brief Parse the value of string of the dnp3_obj keyword. * \brief Parse the dnp3_obj value "<group>,<variation>".
*
* Each number is 0-255; hex (0x..) and octal (0..) are accepted.
* *
* \param str the input string * \param str the input string
* \param gout pointer to variable to store the parsed group integer * \param group where to store the parsed group
* \param vout pointer to variable to store the parsed variation integer * \param var where to store the parsed variation
* *
* \retval 1 if parsing successful otherwise 0. * \retval 1 on success, 0 on failure
*/ */
static int DetectDNP3ObjParse(const char *str, uint8_t *group, uint8_t *var) static int DetectDNP3ObjParse(const char *str, uint8_t *group, uint8_t *var)
{ {
@ -172,6 +195,8 @@ static int DetectDNP3ObjParse(const char *str, uint8_t *group, uint8_t *var)
return 1; return 1;
} }
/** \brief dnp3_obj setup.
* \retval 1 ok, 0 error. Note: not the usual 0 / -1 convention. */
static int DetectDNP3ObjSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str) static int DetectDNP3ObjSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
{ {
SCEnter(); SCEnter();
@ -206,6 +231,7 @@ fail:
SCReturnInt(0); SCReturnInt(0);
} }
/** \brief Free dnp3_obj match data. */
static void DetectDNP3Free(DetectEngineCtx *de_ctx, void *ptr) static void DetectDNP3Free(DetectEngineCtx *de_ctx, void *ptr)
{ {
SCEnter(); SCEnter();
@ -215,6 +241,8 @@ static void DetectDNP3Free(DetectEngineCtx *de_ctx, void *ptr)
SCReturn; SCReturn;
} }
/** \brief Match the function code of a request (to server) or a
* response (to client). */
static int DetectDNP3FuncMatch(DetectEngineThreadCtx *det_ctx, static int DetectDNP3FuncMatch(DetectEngineThreadCtx *det_ctx,
Flow *f, uint8_t flags, void *state, void *txv, const Signature *s, Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
const SigMatchCtx *ctx) const SigMatchCtx *ctx)
@ -231,6 +259,8 @@ static int DetectDNP3FuncMatch(DetectEngineThreadCtx *det_ctx,
return 0; return 0;
} }
/** \brief Match if the tx contains an object with the given group and
* variation (same direction rule as dnp3_func). */
static int DetectDNP3ObjMatch(DetectEngineThreadCtx *det_ctx, static int DetectDNP3ObjMatch(DetectEngineThreadCtx *det_ctx,
Flow *f, uint8_t flags, void *state, void *txv, const Signature *s, Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
const SigMatchCtx *ctx) const SigMatchCtx *ctx)
@ -258,6 +288,8 @@ static int DetectDNP3ObjMatch(DetectEngineThreadCtx *det_ctx,
return 0; return 0;
} }
/** \brief Match the IIN flags as one uint16 (IIN1 high byte, IIN2 low).
* No direction check: the dnp3_ind list is only inspected to client. */
static int DetectDNP3IndMatch(DetectEngineThreadCtx *det_ctx, static int DetectDNP3IndMatch(DetectEngineThreadCtx *det_ctx,
Flow *f, uint8_t flags, void *state, void *txv, const Signature *s, Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
const SigMatchCtx *ctx) const SigMatchCtx *ctx)
@ -323,6 +355,8 @@ static void DetectDNP3ObjRegister(void)
SCReturn; SCReturn;
} }
/** \brief dnp3.data setup: make dnp3_data the active buffer.
* \retval 0 ok, -1 error */
static int DetectDNP3DataSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str) static int DetectDNP3DataSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
{ {
SCEnter(); SCEnter();
@ -335,6 +369,7 @@ static int DetectDNP3DataSetup(DetectEngineCtx *de_ctx, Signature *s, const char
SCReturnInt(0); SCReturnInt(0);
} }
/* dnp3.data: inspection and prefilter (mpm) engines, both directions */
static void DetectDNP3DataRegister(void) static void DetectDNP3DataRegister(void)
{ {
SCEnter(); SCEnter();
@ -361,6 +396,7 @@ static void DetectDNP3DataRegister(void)
SCReturn; SCReturn;
} }
/** \brief Register all DNP3 keywords and their inspection lists. */
void DetectDNP3Register(void) void DetectDNP3Register(void)
{ {
DetectDNP3DataRegister(); DetectDNP3DataRegister();
@ -369,7 +405,7 @@ void DetectDNP3Register(void)
DetectDNP3IndRegister(); DetectDNP3IndRegister();
DetectDNP3ObjRegister(); DetectDNP3ObjRegister();
/* Register the list of func, ind and obj. */ /* "dnp3" list, shared by func and obj, inspected in both directions. */
DetectAppLayerInspectEngineRegister( DetectAppLayerInspectEngineRegister(
"dnp3", ALPROTO_DNP3, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL); "dnp3", ALPROTO_DNP3, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL);
DetectAppLayerInspectEngineRegister( DetectAppLayerInspectEngineRegister(
@ -377,6 +413,7 @@ void DetectDNP3Register(void)
g_dnp3_match_buffer_id = DetectBufferTypeRegister("dnp3"); g_dnp3_match_buffer_id = DetectBufferTypeRegister("dnp3");
/* "dnp3_ind" list: IIN flags exist only in responses, so to client only. */
DetectAppLayerInspectEngineRegister( DetectAppLayerInspectEngineRegister(
"dnp3_ind", ALPROTO_DNP3, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectGenericList, NULL); "dnp3_ind", ALPROTO_DNP3, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectGenericList, NULL);
g_dnp3_ind_buffer_id = DetectBufferTypeRegister("dnp3_ind"); g_dnp3_ind_buffer_id = DetectBufferTypeRegister("dnp3_ind");
@ -390,6 +427,7 @@ void DetectDNP3Register(void)
#include "flow-util.h" #include "flow-util.h"
#include "stream-tcp.h" #include "stream-tcp.h"
/** \test dnp3_func:2 lands in the dnp3 list with value 2. */
static int DetectDNP3FuncTest01(void) static int DetectDNP3FuncTest01(void)
{ {
DetectEngineCtx *de_ctx = DetectEngineCtxInit(); DetectEngineCtx *de_ctx = DetectEngineCtxInit();
@ -411,6 +449,7 @@ static int DetectDNP3FuncTest01(void)
PASS; PASS;
} }
/** \test dnp3_obj:99,99 lands in the dnp3 list with group and variation 99. */
static int DetectDNP3ObjSetupTest(void) static int DetectDNP3ObjSetupTest(void)
{ {
DetectEngineCtx *de_ctx = DetectEngineCtxInit(); DetectEngineCtx *de_ctx = DetectEngineCtxInit();
@ -433,6 +472,8 @@ static int DetectDNP3ObjSetupTest(void)
PASS; PASS;
} }
/** \test dnp3_obj parsing: 0-255 accepted; negatives, overflow and
* non-numbers rejected. */
static int DetectDNP3ObjParseTest(void) static int DetectDNP3ObjParseTest(void)
{ {
uint8_t group, var; uint8_t group, var;

Loading…
Cancel
Save