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