suricata
detect-dnp3.c
Go to the documentation of this file.
1 /* Copyright (C) 2015-2022 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 #include "suricata-common.h"
19 
20 #include "stream.h"
21 
22 #include "detect.h"
23 #include "detect-parse.h"
24 #include "detect-dnp3.h"
25 #include "detect-engine.h"
26 #include "detect-engine-mpm.h"
29 
30 #include "app-layer-dnp3.h"
31 
32 static int g_dnp3_match_buffer_id = 0;
33 static int g_dnp3_data_buffer_id = 0;
34 
35 /**
36  * The detection struct.
37  */
38 typedef struct DetectDNP3_ {
39  union {
40  struct {
41  /* Function code for function code detection. */
42  uint8_t function_code;
43  };
44  struct {
45  /* Internal indicator flags for IIN detection. */
46  uint16_t ind_flags;
47  };
48  struct {
49  /* Object info for object detection. */
50  uint8_t obj_group;
51  uint8_t obj_variation;
52  };
53  };
55 
56 /**
57  * Indicator names to value mappings (Snort compatible).
58  */
60  {"device_restart", 0x8000},
61  {"device_trouble", 0x4000},
62  {"local_control", 0x2000},
63  {"need_time", 0x1000},
64  {"class_3_events", 0x0800},
65  {"class_2_events", 0x0400},
66  {"class_1_events", 0x0200},
67  {"all_stations", 0x0100},
68 
69  {"reserved_1", 0x0080},
70  {"reserved_2", 0x0040},
71  {"config_corrupt", 0x0020},
72  {"already_executing", 0x0010},
73  {"event_buffer_overflow", 0x0008},
74  {"parameter_error", 0x0004},
75  {"object_unknown", 0x0002},
76  {"no_func_code_support", 0x0001},
77 
78  {NULL, 0},
79 };
80 
81 /**
82  * Application function code name to code mappings (Snort compatible).
83  */
85  {"confirm", 0},
86  {"read", 1},
87  {"write", 2},
88  {"select", 3},
89  {"operate", 4},
90  {"direct_operate", 5},
91  {"direct_operate_nr", 6},
92  {"immed_freeze", 7},
93  {"immed_freeze_nr", 8},
94  {"freeze_clear", 9},
95  {"freeze_clear_nr", 10},
96  {"freeze_at_time", 11},
97  {"freeze_at_time_nr", 12},
98  {"cold_restart", 13},
99  {"warm_restart", 14},
100  {"initialize_data", 15},
101  {"initialize_appl", 16},
102  {"start_appl", 17},
103  {"stop_appl", 18},
104  {"save_config", 19},
105  {"enable_unsolicited", 20},
106  {"disable_unsolicited", 21},
107  {"assign_class", 22},
108  {"delay_measure", 23},
109  {"record_current_time", 24},
110  {"open_file", 25},
111  {"close_file", 26},
112  {"delete_file", 27},
113  {"get_file_info", 28},
114  {"authenticate_file", 29},
115  {"abort_file", 30},
116  {"activate_config", 31},
117  {"authenticate_req", 32},
118  {"authenticate_err", 33},
119  {"response", 129},
120  {"unsolicited_response", 130},
121  {"authenticate_resp", 131}
122 };
123 
124 #ifdef UNITTESTS
125 static void DetectDNP3FuncRegisterTests(void);
126 static void DetectDNP3IndRegisterTests(void);
127 static void DetectDNP3ObjRegisterTests(void);
128 #endif
129 
130 /**
131  * \brief Utility function to trim leading and trailing whitespace
132  * from a string.
133  */
134 static char *TrimString(char *str)
135 {
136  char *end = str + strlen(str) - 1;
137  while (isspace(*str)) {
138  str++;
139  }
140  while (end > str && isspace(*end)) {
141  end--;
142  }
143  *(end + 1) = '\0';
144  return str;
145 }
146 
147 static InspectionBuffer *GetDNP3Data(DetectEngineThreadCtx *det_ctx,
148  const DetectEngineTransforms *transforms,
149  Flow *_f, const uint8_t flow_flags,
150  void *txv, const int list_id)
151 {
152  SCLogDebug("list_id %d", list_id);
153  InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
154  if (buffer->inspect == NULL) {
155  DNP3Transaction *tx = (DNP3Transaction *)txv;
156  SCLogDebug("tx %p", tx);
157 
158  const uint8_t *data = NULL;
159  uint32_t data_len = 0;
160 
161  if (flow_flags & STREAM_TOSERVER) {
162  data = tx->request_buffer;
163  data_len = tx->request_buffer_len;
164  } else if (flow_flags & STREAM_TOCLIENT) {
165  data = tx->response_buffer;
166  data_len = tx->response_buffer_len;
167  }
168  if (data == NULL || data_len == 0)
169  return NULL;
170 
171  SCLogDebug("tx %p data %p data_len %u", tx, data, data_len);
172  InspectionBufferSetup(det_ctx, list_id, buffer, data, data_len);
173  InspectionBufferApplyTransforms(buffer, transforms);
174  }
175  return buffer;
176 }
177 
178 static int DetectEngineInspectDNP3(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
179  const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f,
180  uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
181 {
183  de_ctx, det_ctx, s, engine->smd, f, flags, alstate, txv, tx_id);
184 }
185 
186 /**
187  * \brief Parse the provided function name or code to its integer
188  * value.
189  *
190  * If the value passed is a number, it will be checked that it falls
191  * within the range of valid function codes. If function name is
192  * passed it will be resolved to its function code.
193  *
194  * \retval The function code as an integer if successul, -1 on
195  * failure.
196  */
197 static int DetectDNP3FuncParseFunctionCode(const char *str, uint8_t *fc)
198 {
199  if (StringParseUint8(fc, 10, strlen(str), str) >= 0) {
200  return 1;
201  }
202 
203  /* Lookup by name. */
204  for (size_t i = 0;
205  i < sizeof(DNP3FunctionNameMap) / sizeof(DNP3Mapping); i++) {
206  if (strcasecmp(str, DNP3FunctionNameMap[i].name) == 0) {
207  *fc = DNP3FunctionNameMap[i].value;
208  return 1;
209  }
210  }
211 
212  return 0;
213 }
214 
215 static int DetectDNP3FuncSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
216 {
217  SCEnter();
218  DetectDNP3 *dnp3 = NULL;
219  SigMatch *sm = NULL;
220  uint8_t function_code;
221 
223  return -1;
224 
225  if (!DetectDNP3FuncParseFunctionCode(str, &function_code)) {
227  "Invalid argument \"%s\" supplied to dnp3_func keyword.", str);
228  return -1;
229  }
230 
231  dnp3 = SCCalloc(1, sizeof(DetectDNP3));
232  if (unlikely(dnp3 == NULL)) {
233  goto error;
234  }
236 
237  sm = SigMatchAlloc();
238  if (sm == NULL) {
239  goto error;
240  }
241  sm->type = DETECT_AL_DNP3FUNC;
242  sm->ctx = (void *)dnp3;
243 
244  SigMatchAppendSMToList(s, sm, g_dnp3_match_buffer_id);
245 
246  SCReturnInt(0);
247 error:
248  if (dnp3 != NULL) {
249  SCFree(dnp3);
250  }
251  if (sm != NULL) {
252  SCFree(sm);
253  }
254  SCReturnInt(-1);
255 }
256 
257 static int DetectDNP3IndParseByName(const char *str, uint16_t *flags)
258 {
259  char tmp[strlen(str) + 1];
260  char *p, *last = NULL;
261 
262  strlcpy(tmp, str, sizeof(tmp));
263 
264  for ((p = strtok_r(tmp, ",", &last)); p; (p = strtok_r(NULL, ",", &last))) {
265  p = TrimString(p);
266  int found = 0;
267  int i = 0;
268  while (DNP3IndicatorsMap[i].name != NULL) {
269  if (strcasecmp(p, DNP3IndicatorsMap[i].name) == 0) {
271  found = 1;
272  break;
273  }
274  i++;
275  }
276 
277  if (!found) {
279  "Bad argument \"%s\" supplied to dnp3.ind keyword.", p);
280  return 0;
281  }
282  }
283 
284  return 1;
285 }
286 
287 static int DetectDNP3IndParse(const char *str, uint16_t *flags)
288 {
289  *flags = 0;
290 
291  if (StringParseUint16(flags, 0, strlen(str), str) > 0) {
292  return 1;
293  }
294 
295  /* Parse by name - will log a more specific error message on error. */
296  if (DetectDNP3IndParseByName(str, flags)) {
297  return 1;
298  }
299 
300  return 0;
301 }
302 
303 static int DetectDNP3IndSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
304 {
305  SCEnter();
306  DetectDNP3 *detect = NULL;
307  SigMatch *sm = NULL;
308  uint16_t flags;
309 
311  return -1;
312 
313  if (!DetectDNP3IndParse(str, &flags)) {
315  "Invalid argument \"%s\" supplied to dnp3.ind keyword.", str);
316  return -1;
317  }
318 
319  detect = SCCalloc(1, sizeof(DetectDNP3));
320  if (unlikely(detect == NULL)) {
321  goto error;
322  }
323  detect->ind_flags = flags;
324 
325  sm = SigMatchAlloc();
326  if (sm == NULL) {
327  goto error;
328  }
329  sm->type = DETECT_AL_DNP3IND;
330  sm->ctx = (void *)detect;
331  SigMatchAppendSMToList(s, sm, g_dnp3_match_buffer_id);
332 
333  SCReturnInt(0);
334 error:
335  if (detect != NULL) {
336  SCFree(detect);
337  }
338  if (sm != NULL) {
339  SCFree(sm);
340  }
341  SCReturnInt(-1);
342 }
343 
344 /**
345  * \brief Parse the value of string of the dnp3_obj keyword.
346  *
347  * \param str the input string
348  * \param gout pointer to variable to store the parsed group integer
349  * \param vout pointer to variable to store the parsed variation integer
350  *
351  * \retval 1 if parsing successful otherwise 0.
352  */
353 static int DetectDNP3ObjParse(const char *str, uint8_t *group, uint8_t *var)
354 {
355  size_t size = strlen(str) + 1;
356  char groupstr[size], *varstr, *sep;
357  strlcpy(groupstr, str, size);
358 
359  sep = strchr(groupstr, ',');
360  if (sep == NULL) {
361  return 0;
362  }
363  *sep = '\0';
364  varstr = sep + 1;
365 
366  if (StringParseUint8(group, 0, strlen(groupstr), groupstr) < 0) {
367  return 0;
368  }
369 
370  if (StringParseUint8(var, 0, strlen(varstr), varstr) < 0) {
371  return 0;
372  }
373 
374  return 1;
375 }
376 
377 static int DetectDNP3ObjSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
378 {
379  SCEnter();
380  uint8_t group;
381  uint8_t variation;
382  DetectDNP3 *detect = NULL;
383  SigMatch *sm = NULL;
384 
386  return -1;
387 
388  if (!DetectDNP3ObjParse(str, &group, &variation)) {
389  goto fail;
390  }
391 
392  detect = SCCalloc(1, sizeof(*detect));
393  if (unlikely(detect == NULL)) {
394  goto fail;
395  }
396  detect->obj_group = group;
397  detect->obj_variation = variation;
398 
399  sm = SigMatchAlloc();
400  if (unlikely(sm == NULL)) {
401  goto fail;
402  }
403  sm->type = DETECT_AL_DNP3OBJ;
404  sm->ctx = (void *)detect;
405  SigMatchAppendSMToList(s, sm, g_dnp3_match_buffer_id);
406 
407  SCReturnInt(1);
408 fail:
409  if (detect != NULL) {
410  SCFree(detect);
411  }
412  if (sm != NULL) {
413  SCFree(sm);
414  }
415  SCReturnInt(0);
416 }
417 
418 static void DetectDNP3Free(DetectEngineCtx *de_ctx, void *ptr)
419 {
420  SCEnter();
421  if (ptr != NULL) {
422  SCFree(ptr);
423  }
424  SCReturn;
425 }
426 
427 static int DetectDNP3FuncMatch(DetectEngineThreadCtx *det_ctx,
428  Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
429  const SigMatchCtx *ctx)
430 {
431  DNP3Transaction *tx = (DNP3Transaction *)txv;
432  DetectDNP3 *detect = (DetectDNP3 *)ctx;
433  int match = 0;
434 
435  if (flags & STREAM_TOSERVER) {
436  match = detect->function_code == tx->request_ah.function_code;
437  }
438  else if (flags & STREAM_TOCLIENT) {
439  match = detect->function_code == tx->response_ah.function_code;
440  }
441 
442  return match;
443 }
444 
445 static int DetectDNP3ObjMatch(DetectEngineThreadCtx *det_ctx,
446  Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
447  const SigMatchCtx *ctx)
448 {
449  DNP3Transaction *tx = (DNP3Transaction *)txv;
450  DetectDNP3 *detect = (DetectDNP3 *)ctx;
451  DNP3ObjectList *objects = NULL;
452 
453  if (flags & STREAM_TOSERVER) {
454  objects = &tx->request_objects;
455  }
456  else if (flags & STREAM_TOCLIENT) {
457  objects = &tx->response_objects;
458  }
459 
460  if (objects != NULL) {
461  DNP3Object *object;
462  TAILQ_FOREACH(object, objects, next) {
463  if (object->group == detect->obj_group &&
464  object->variation == detect->obj_variation) {
465  return 1;
466  }
467  }
468  }
469 
470  return 0;
471 }
472 
473 static int DetectDNP3IndMatch(DetectEngineThreadCtx *det_ctx,
474  Flow *f, uint8_t flags, void *state, void *txv, const Signature *s,
475  const SigMatchCtx *ctx)
476 {
477  DNP3Transaction *tx = (DNP3Transaction *)txv;
478  DetectDNP3 *detect = (DetectDNP3 *)ctx;
479 
480  if (flags & STREAM_TOCLIENT) {
481  if ((tx->response_iin.iin1 & (detect->ind_flags >> 8)) ||
482  (tx->response_iin.iin2 & (detect->ind_flags & 0xf))) {
483  return 1;
484  }
485  }
486 
487  return 0;
488 }
489 
490 static void DetectDNP3FuncRegister(void)
491 {
492  SCEnter();
493 
494  sigmatch_table[DETECT_AL_DNP3FUNC].name = "dnp3_func";
495  sigmatch_table[DETECT_AL_DNP3FUNC].alias = "dnp3.func";
496  sigmatch_table[DETECT_AL_DNP3FUNC].desc = "match on the application function code found in DNP3 request and responses";
497  sigmatch_table[DETECT_AL_DNP3FUNC].url = "/rules/dnp3-keywords.html#dnp3-func";
499  sigmatch_table[DETECT_AL_DNP3FUNC].AppLayerTxMatch = DetectDNP3FuncMatch;
500  sigmatch_table[DETECT_AL_DNP3FUNC].Setup = DetectDNP3FuncSetup;
501  sigmatch_table[DETECT_AL_DNP3FUNC].Free = DetectDNP3Free;
502 #ifdef UNITTESTS
504  DetectDNP3FuncRegisterTests;
505 #endif
506  SCReturn;
507 }
508 
509 static void DetectDNP3IndRegister(void)
510 {
511  SCEnter();
512 
513  sigmatch_table[DETECT_AL_DNP3IND].name = "dnp3_ind";
514  sigmatch_table[DETECT_AL_DNP3IND].alias = "dnp3.ind";
515  sigmatch_table[DETECT_AL_DNP3IND].desc = "match on the DNP3 internal indicator flags in the response application header";
516  sigmatch_table[DETECT_AL_DNP3IND].url = "/rules/dnp3-keywords.html#dnp3-ind";
518  sigmatch_table[DETECT_AL_DNP3IND].AppLayerTxMatch = DetectDNP3IndMatch;
519  sigmatch_table[DETECT_AL_DNP3IND].Setup = DetectDNP3IndSetup;
520  sigmatch_table[DETECT_AL_DNP3IND].Free = DetectDNP3Free;
521 #ifdef UNITTESTS
523  DetectDNP3IndRegisterTests;
524 #endif
525  SCReturn;
526 }
527 
528 static void DetectDNP3ObjRegister(void)
529 {
530  SCEnter();
531 
532  sigmatch_table[DETECT_AL_DNP3OBJ].name = "dnp3_obj";
533  sigmatch_table[DETECT_AL_DNP3OBJ].alias = "dnp3.obj";
534  sigmatch_table[DETECT_AL_DNP3OBJ].desc = "match on the DNP3 application data objects";
535  sigmatch_table[DETECT_AL_DNP3OBJ].url = "/rules/dnp3-keywords.html#dnp3-obj";
537  sigmatch_table[DETECT_AL_DNP3OBJ].AppLayerTxMatch = DetectDNP3ObjMatch;
538  sigmatch_table[DETECT_AL_DNP3OBJ].Setup = DetectDNP3ObjSetup;
539  sigmatch_table[DETECT_AL_DNP3OBJ].Free = DetectDNP3Free;
540 #ifdef UNITTESTS
542  DetectDNP3ObjRegisterTests;
543 #endif
544  SCReturn;
545 }
546 
547 static int DetectDNP3DataSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
548 {
549  SCEnter();
551  return -1;
552 
553  if (DetectBufferSetActiveList(s, g_dnp3_data_buffer_id) != 0)
554  return -1;
555 
556  SCReturnInt(0);
557 }
558 
559 static void DetectDNP3DataRegister(void)
560 {
561  SCEnter();
562 
563  sigmatch_table[DETECT_AL_DNP3DATA].name = "dnp3.data";
564  sigmatch_table[DETECT_AL_DNP3DATA].alias = "dnp3_data";
565  sigmatch_table[DETECT_AL_DNP3DATA].desc = "make the following content options to match on the re-assembled application buffer";
566  sigmatch_table[DETECT_AL_DNP3DATA].url = "/rules/dnp3-keywords.html#dnp3-data";
567  sigmatch_table[DETECT_AL_DNP3DATA].Setup = DetectDNP3DataSetup;
569 
573  GetDNP3Data);
575  PrefilterGenericMpmRegister, GetDNP3Data,
576  ALPROTO_DNP3, 0);
577 
581  GetDNP3Data);
583  PrefilterGenericMpmRegister, GetDNP3Data,
584  ALPROTO_DNP3, 0);
585 
586  g_dnp3_data_buffer_id = DetectBufferTypeGetByName("dnp3_data");
587  SCReturn;
588 }
589 
591 {
592  DetectDNP3DataRegister();
593 
594  DetectDNP3FuncRegister();
595  DetectDNP3IndRegister();
596  DetectDNP3ObjRegister();
597 
598  /* Register the list of func, ind and obj. */
600  "dnp3", ALPROTO_DNP3, SIG_FLAG_TOSERVER, 0, DetectEngineInspectDNP3, NULL);
602  "dnp3", ALPROTO_DNP3, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectDNP3, NULL);
603 
604  g_dnp3_match_buffer_id = DetectBufferTypeRegister("dnp3");
605 
606 }
607 
608 #ifdef UNITTESTS
609 
610 #include "util-unittest.h"
611 #include "util-unittest-helper.h"
612 #include "app-layer-parser.h"
613 #include "detect-engine.h"
614 #include "flow-util.h"
615 #include "stream-tcp.h"
616 
617 static int DetectDNP3FuncParseFunctionCodeTest(void)
618 {
619  uint8_t fc;
620 
621  /* Valid. */
622  FAIL_IF_NOT(DetectDNP3FuncParseFunctionCode("0", &fc));
623  FAIL_IF(fc != 0);
624 
625  FAIL_IF_NOT(DetectDNP3FuncParseFunctionCode("1", &fc));
626  FAIL_IF(fc != 1);
627 
628  FAIL_IF_NOT(DetectDNP3FuncParseFunctionCode("254", &fc));
629  FAIL_IF(fc != 254);
630 
631  FAIL_IF_NOT(DetectDNP3FuncParseFunctionCode("255", &fc));
632  FAIL_IF(fc != 255);
633 
634  FAIL_IF_NOT(DetectDNP3FuncParseFunctionCode("confirm", &fc));
635  FAIL_IF(fc != 0);
636 
637  FAIL_IF_NOT(DetectDNP3FuncParseFunctionCode("CONFIRM", &fc));
638  FAIL_IF(fc != 0);
639 
640  /* Invalid. */
641  FAIL_IF(DetectDNP3FuncParseFunctionCode("", &fc));
642  FAIL_IF(DetectDNP3FuncParseFunctionCode("-1", &fc));
643  FAIL_IF(DetectDNP3FuncParseFunctionCode("-2", &fc));
644  FAIL_IF(DetectDNP3FuncParseFunctionCode("256", &fc));
645  FAIL_IF(DetectDNP3FuncParseFunctionCode("unknown_function_code", &fc));
646 
647  PASS;
648 }
649 
650 static int DetectDNP3FuncTest01(void)
651 {
652  DetectEngineCtx *de_ctx = NULL;
653  DetectDNP3 *dnp3func = NULL;
654 
657 
659  "alert dnp3 any any -> any any "
660  "(msg:\"SURICATA DNP3 Write request\"; "
661  "dnp3_func:2; sid:5000009; rev:1;)");
663 
664  FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_dnp3_match_buffer_id]);
665  FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_dnp3_match_buffer_id]->ctx);
666 
667  dnp3func = (DetectDNP3 *)de_ctx->sig_list->sm_lists_tail[g_dnp3_match_buffer_id]->ctx;
668  FAIL_IF(dnp3func->function_code != 2);
669 
670  if (de_ctx != NULL) {
672  }
673  PASS;
674 }
675 
676 static int DetectDNP3IndTestParseAsInteger(void)
677 {
678  uint16_t flags = 0;
679 
680  FAIL_IF(!DetectDNP3IndParse("0", &flags));
681  FAIL_IF(flags != 0);
682  FAIL_IF(!DetectDNP3IndParse("1", &flags));
683  FAIL_IF(flags != 0x0001);
684 
685  FAIL_IF(!DetectDNP3IndParse("0x0", &flags));
686  FAIL_IF(flags != 0);
687  FAIL_IF(!DetectDNP3IndParse("0x0000", &flags));
688  FAIL_IF(flags != 0);
689  FAIL_IF(!DetectDNP3IndParse("0x0001", &flags));
690  FAIL_IF(flags != 0x0001);
691 
692  FAIL_IF(!DetectDNP3IndParse("0x8421", &flags));
693  FAIL_IF(flags != 0x8421);
694 
695  FAIL_IF(DetectDNP3IndParse("a", &flags));
696 
697  PASS;
698 }
699 
700 static int DetectDNP3IndTestParseByName(void)
701 {
702  uint16_t flags = 0;
703 
704  FAIL_IF(!DetectDNP3IndParse("all_stations", &flags));
705  FAIL_IF(!(flags & 0x0100));
706  FAIL_IF(!DetectDNP3IndParse("class_1_events , class_2_events", &flags));
707  FAIL_IF(!(flags & 0x0200));
708  FAIL_IF(!(flags & 0x0400));
709  FAIL_IF((flags & 0xf9ff));
710 
711  FAIL_IF(DetectDNP3IndParse("something", &flags));
712 
713  PASS;
714 }
715 
716 static int DetectDNP3ObjSetupTest(void)
717 {
718  DetectEngineCtx *de_ctx = NULL;
719  DetectDNP3 *detect = NULL;
720 
722  FAIL_IF(de_ctx == NULL);
723 
725  "alert dnp3 any any -> any any "
726  "(msg:\"SURICATA DNP3 Object Test\"; "
727  "dnp3_obj:99,99; sid:1; rev:1;)");
728  FAIL_IF(de_ctx->sig_list == NULL);
729 
730  FAIL_IF(de_ctx->sig_list->sm_lists_tail[g_dnp3_match_buffer_id] == NULL);
731  FAIL_IF(de_ctx->sig_list->sm_lists_tail[g_dnp3_match_buffer_id]->ctx == NULL);
732 
733  detect = (DetectDNP3 *)de_ctx->sig_list->sm_lists_tail[g_dnp3_match_buffer_id]->ctx;
734  FAIL_IF(detect->obj_group != 99);
735  FAIL_IF(detect->obj_variation != 99);
736 
737  if (de_ctx != NULL) {
739  }
740  PASS;
741 }
742 
743 static int DetectDNP3ObjParseTest(void)
744 {
745  uint8_t group, var;
746 
747  FAIL_IF(!DetectDNP3ObjParse("0,0", &group, &var));
748  FAIL_IF(group != 0 || var != 0);
749 
750  FAIL_IF(!DetectDNP3ObjParse("255,255", &group, &var));
751  FAIL_IF(group != 255 || var != 255);
752 
753  FAIL_IF(DetectDNP3ObjParse("-1,-1", &group, &var));
754  FAIL_IF(DetectDNP3ObjParse("256,256", &group, &var));
755  FAIL_IF(DetectDNP3ObjParse("a,1", &group, &var));
756  FAIL_IF(DetectDNP3ObjParse("1,a", &group, &var));
757 
758  PASS;
759 }
760 
761 static void DetectDNP3FuncRegisterTests(void)
762 {
763  UtRegisterTest("DetectDNP3FuncParseFunctionCodeTest",
764  DetectDNP3FuncParseFunctionCodeTest);
765  UtRegisterTest("DetectDNP3FuncTest01", DetectDNP3FuncTest01);
766 }
767 
768 static void DetectDNP3IndRegisterTests(void)
769 {
770  UtRegisterTest("DetectDNP3IndTestParseAsInteger",
771  DetectDNP3IndTestParseAsInteger);
772  UtRegisterTest("DetectDNP3IndTestParseByName",
773  DetectDNP3IndTestParseByName);
774 }
775 
776 static void DetectDNP3ObjRegisterTests(void)
777 {
778  UtRegisterTest("DetectDNP3ObjParseTest", DetectDNP3ObjParseTest);
779  UtRegisterTest("DetectDNP3ObjSetupTest", DetectDNP3ObjSetupTest);
780 }
781 #endif
DETECT_AL_DNP3IND
@ DETECT_AL_DNP3IND
Definition: detect-engine-register.h:236
DetectEngineAppInspectionEngine_
Definition: detect.h:398
SigTableElmt_::url
const char * url
Definition: detect.h:1270
DetectSignatureSetAppProto
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
Definition: detect-parse.c:1490
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SIGMATCH_INFO_STICKY_BUFFER
#define SIGMATCH_INFO_STICKY_BUFFER
Definition: detect.h:1477
SigTableElmt_::desc
const char * desc
Definition: detect.h:1269
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1257
flow-util.h
DetectEngineInspectGenericList
int DetectEngineInspectGenericList(const DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Flow *f, const uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
Do the content inspection & validation for a signature.
Definition: detect-engine.c:1941
SigTableElmt_::name
const char * name
Definition: detect.h:1267
stream-tcp.h
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DetectEngineTransforms
Definition: detect.h:379
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
DetectDNP3Register
void DetectDNP3Register(void)
Definition: detect-dnp3.c:590
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
DNP3Object_
Struct to hold the list of decoded objects.
Definition: app-layer-dnp3.h:191
InspectionBuffer
Definition: detect.h:345
Flow_
Flow data structure.
Definition: flow.h:353
SigInit
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2115
PrefilterGenericMpmRegister
int PrefilterGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistery *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:753
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1261
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:811
StringParseUint16
int StringParseUint16(uint16_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:336
SC_ERR_INVALID_SIGNATURE
@ SC_ERR_INVALID_SIGNATURE
Definition: util-error.h:69
DETECT_AL_DNP3FUNC
@ DETECT_AL_DNP3FUNC
Definition: detect-engine-register.h:235
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:253
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2433
SigTableElmt_::AppLayerTxMatch
int(* AppLayerTxMatch)(DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition: detect.h:1238
DNP3Transaction_::response_buffer
uint8_t * response_buffer
Definition: app-layer-dnp3.h:237
DetectDNP3_
Definition: detect-dnp3.c:38
detect-dnp3.h
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:237
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1252
DetectDNP3_::function_code
uint8_t function_code
Definition: detect-dnp3.c:42
detect-engine-prefilter.h
util-unittest.h
InspectionBufferGet
InspectionBuffer * InspectionBufferGet(DetectEngineThreadCtx *det_ctx, const int list_id)
Definition: detect-engine.c:1360
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1077
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
DNP3IndicatorsMap
DNP3Mapping DNP3IndicatorsMap[]
Definition: detect-dnp3.c:59
StringParseUint8
int StringParseUint8(uint8_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:359
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:236
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DNP3Transaction_::response_iin
DNP3InternalInd response_iin
Definition: app-layer-dnp3.h:236
DetectDNP3_::ind_flags
uint16_t ind_flags
Definition: detect-dnp3.c:46
DetectEngineThreadCtx_
Definition: detect.h:1060
ALPROTO_DNP3
@ ALPROTO_DNP3
Definition: app-layer-protos.h:44
app-layer-dnp3.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:300
detect-engine-mpm.h
detect.h
app-layer-parser.h
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:324
SCReturn
#define SCReturn
Definition: util-debug.h:302
stream.h
DetectEngineInspectBufferGeneric
int DetectEngineInspectBufferGeneric(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
Do the content inspection & validation for a signature.
Definition: detect-engine.c:1983
DNP3Object_::group
uint8_t group
Definition: app-layer-dnp3.h:192
DetectAppLayerInspectEngineRegister2
void DetectAppLayerInspectEngineRegister2(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr2 Callback2, InspectionBufferGetDataPtr GetData)
register inspect engine at start up time
Definition: detect-engine.c:225
DNP3Transaction_::request_buffer_len
uint32_t request_buffer_len
Definition: app-layer-dnp3.h:224
variation
uint8_t variation
Definition: app-layer-dnp3.h:1
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1235
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:235
DNP3Transaction_::request_ah
DNP3ApplicationHeader request_ah
Definition: app-layer-dnp3.h:221
DetectDNP3_::obj_variation
uint8_t obj_variation
Definition: detect-dnp3.c:51
DNP3Transaction_::response_ah
DNP3ApplicationHeader response_ah
Definition: app-layer-dnp3.h:235
detect-engine-content-inspection.h
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:316
DetectEngineAppInspectionEngine_::smd
SigMatchData * smd
Definition: detect.h:415
DetectAppLayerMpmRegister2
void DetectAppLayerMpmRegister2(const char *name, int direction, int priority, int(*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistery *mpm_reg, int list_id), InspectionBufferGetDataPtr GetData, AppProto alproto, int tx_min_progress)
register a MPM engine
Definition: detect-engine-mpm.c:89
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
DetectBufferTypeRegister
int DetectBufferTypeRegister(const char *name)
Definition: detect-engine.c:1023
flags
uint8_t flags
Definition: decode-gre.h:0
SigTableElmt_::alias
const char * alias
Definition: detect.h:1268
group
uint8_t group
Definition: app-layer-dnp3.h:0
suricata-common.h
SigMatch_::type
uint16_t type
Definition: detect.h:322
DetectDNP3_::obj_group
uint8_t obj_group
Definition: detect-dnp3.c:50
InspectionBufferApplyTransforms
void InspectionBufferApplyTransforms(InspectionBuffer *buffer, const DetectEngineTransforms *transforms)
Definition: detect-engine.c:1543
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:73
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
DNP3Mapping_::value
uint16_t value
Definition: detect-dnp3.h:26
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:817
DNP3Mapping_
Definition: detect-dnp3.h:24
DETECT_AL_DNP3DATA
@ DETECT_AL_DNP3DATA
Definition: detect-engine-register.h:234
DNP3Transaction_::request_objects
DNP3ObjectList request_objects
Definition: app-layer-dnp3.h:229
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect.h:346
str
#define str(s)
Definition: suricata-common.h:272
InspectionBufferSetup
void InspectionBufferSetup(DetectEngineThreadCtx *det_ctx, const int list_id, InspectionBuffer *buffer, const uint8_t *data, const uint32_t data_len)
setup the buffer with our initial data
Definition: detect-engine.c:1441
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DNP3Transaction_::request_buffer
uint8_t * request_buffer
Definition: app-layer-dnp3.h:222
DNP3Object_::variation
uint8_t variation
Definition: app-layer-dnp3.h:193
detect-parse.h
Signature_
Signature container.
Definition: detect.h:548
SigMatch_
a single match condition for a signature
Definition: detect.h:321
function_code
uint8_t function_code
Definition: app-layer-dnp3.h:1
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2394
SIGMATCH_NOOPT
#define SIGMATCH_NOOPT
Definition: detect.h:1453
DetectDNP3
struct DetectDNP3_ DetectDNP3
DetectBufferSetActiveList
int DetectBufferSetActiveList(Signature *s, const int list)
Definition: detect-engine.c:1291
DNP3FunctionNameMap
DNP3Mapping DNP3FunctionNameMap[]
Definition: detect-dnp3.c:84
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
DNP3Transaction_::response_buffer_len
uint32_t response_buffer_len
Definition: app-layer-dnp3.h:239
SigMatchAppendSMToList
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:349
DNP3Transaction_
DNP3 transaction.
Definition: app-layer-dnp3.h:210
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1259
DNP3Transaction_::response_objects
DNP3ObjectList response_objects
Definition: app-layer-dnp3.h:244
DETECT_AL_DNP3OBJ
@ DETECT_AL_DNP3OBJ
Definition: detect-engine-register.h:237