suricata
detect-parse.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2020 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 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  * signature parser
24  */
25 
26 #include "suricata-common.h"
27 #include "debug.h"
28 
29 #include "detect.h"
30 #include "detect-engine.h"
31 #include "detect-engine-address.h"
32 #include "detect-engine-port.h"
33 #include "detect-engine-mpm.h"
34 #include "detect-engine-state.h"
35 
36 #include "detect-content.h"
37 #include "detect-pcre.h"
38 #include "detect-uricontent.h"
39 #include "detect-reference.h"
40 #include "detect-ipproto.h"
41 #include "detect-flow.h"
43 #include "detect-lua.h"
44 #include "detect-app-layer-event.h"
45 #include "detect-http-method.h"
46 
47 #include "pkt-var.h"
48 #include "host.h"
49 #include "util-profiling.h"
50 #include "decode.h"
51 
52 #include "flow.h"
53 
54 #include "util-rule-vars.h"
55 #include "conf.h"
56 #include "conf-yaml-loader.h"
57 
58 #include "app-layer.h"
59 #include "app-layer-protos.h"
60 #include "app-layer-parser.h"
61 #include "app-layer-htp.h"
62 
64 #include "util-unittest.h"
65 #include "util-unittest-helper.h"
66 #include "util-debug.h"
67 #include "string.h"
68 #include "detect-parse.h"
69 #include "detect-engine-iponly.h"
70 #include "app-layer-detect-proto.h"
71 
72 /* Table with all SigMatch registrations */
74 
75 extern int sc_set_caps;
76 
77 static void SigMatchTransferSigMatchAcrossLists(SigMatch *sm,
78  SigMatch **src_sm_list, SigMatch **src_sm_list_tail,
79  SigMatch **dst_sm_list, SigMatch **dst_sm_list_tail);
80 
81 /**
82  * \brief We use this as data to the hash table DetectEngineCtx->dup_sig_hash_table.
83  */
84 typedef struct SigDuplWrapper_ {
85  /* the signature we want to wrap */
87  /* the signature right before the above signatue in the det_ctx->sig_list */
90 
91 #define CONFIG_PARTS 8
92 
93 #define CONFIG_ACTION 0
94 #define CONFIG_PROTO 1
95 #define CONFIG_SRC 2
96 #define CONFIG_SP 3
97 #define CONFIG_DIREC 4
98 #define CONFIG_DST 5
99 #define CONFIG_DP 6
100 #define CONFIG_OPTS 7
101 
102 /** helper structure for sig parsing */
103 typedef struct SignatureParser_ {
113 
114 const char *DetectListToHumanString(int list)
115 {
116 #define CASE_CODE_STRING(E, S) case E: return S; break
117  switch (list) {
124  CASE_CODE_STRING(DETECT_SM_LIST_MAX, "max (internal)");
125  }
126 #undef CASE_CODE_STRING
127  return "unknown";
128 }
129 
130 #define CASE_CODE(E) case E: return #E
131 const char *DetectListToString(int list)
132 {
133  switch (list) {
141  }
142  return "unknown";
143 }
144 
145 /** \param arg NULL or empty string */
147  Signature *s, const char *arg, int sm_type, int sm_list,
148  AppProto alproto)
149 {
150  SigMatch *sm = NULL;
151  int ret = -1;
152 
153  if (arg != NULL && strcmp(arg, "") != 0) {
154  SCLogError(SC_ERR_INVALID_ARGUMENT, "%s shouldn't be supplied "
155  "with an argument", sigmatch_table[sm_type].name);
156  goto end;
157  }
158 
159  if (s->init_data->list != DETECT_SM_LIST_NOTSET) {
160  SCLogError(SC_ERR_INVALID_SIGNATURE, "\"%s\" keyword seen "
161  "with a sticky buffer still set. Reset sticky buffer "
162  "with pkt_data before using the modifier.",
163  sigmatch_table[sm_type].name);
164  goto end;
165  }
166  if (s->alproto != ALPROTO_UNKNOWN && s->alproto != alproto) {
167  SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting "
168  "alprotos set");
169  goto end;
170  }
171 
174  if (sm == NULL) {
175  SCLogError(SC_ERR_INVALID_SIGNATURE, "\"%s\" keyword "
176  "found inside the rule without a content context. "
177  "Please use a \"content\" keyword before using the "
178  "\"%s\" keyword", sigmatch_table[sm_type].name,
179  sigmatch_table[sm_type].name);
180  goto end;
181  }
183  if (cd->flags & DETECT_CONTENT_RAWBYTES) {
184  SCLogError(SC_ERR_INVALID_SIGNATURE, "%s rule can not "
185  "be used with the rawbytes rule keyword",
186  sigmatch_table[sm_type].name);
187  goto end;
188  }
189  if (cd->flags & DETECT_CONTENT_REPLACE) {
190  SCLogError(SC_ERR_INVALID_SIGNATURE, "%s rule can not "
191  "be used with the replace rule keyword",
192  sigmatch_table[sm_type].name);
193  goto end;
194  }
198  if (pm != NULL) {
199  if (pm->type == DETECT_CONTENT) {
200  DetectContentData *tmp_cd = (DetectContentData *)pm->ctx;
202  } else {
203  DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx;
204  tmp_pd->flags &= ~DETECT_PCRE_RELATIVE_NEXT;
205  }
206  }
207 
208  pm = DetectGetLastSMByListId(s, sm_list,
210  if (pm != NULL) {
211  if (pm->type == DETECT_CONTENT) {
212  DetectContentData *tmp_cd = (DetectContentData *)pm->ctx;
214  } else {
215  DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx;
216  tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT;
217  }
218  }
219  }
220  s->alproto = alproto;
221  s->flags |= SIG_FLAG_APPLAYER;
222 
223  /* transfer the sm from the pmatch list to sm_list */
224  SigMatchTransferSigMatchAcrossLists(sm,
227  &s->init_data->smlists[sm_list],
228  &s->init_data->smlists_tail[sm_list]);
229 
230  ret = 0;
231  end:
232  return ret;
233 }
234 
236 {
237  SigMatch *sm = SCMalloc(sizeof(SigMatch));
238  if (unlikely(sm == NULL))
239  return NULL;
240 
241  memset(sm, 0, sizeof(SigMatch));
242  sm->prev = NULL;
243  sm->next = NULL;
244  return sm;
245 }
246 
247 /** \brief free a SigMatch
248  * \param sm SigMatch to free.
249  */
251 {
252  if (sm == NULL)
253  return;
254 
255  /** free the ctx, for that we call the Free func */
256  if (sm->ctx != NULL) {
257  if (sigmatch_table[sm->type].Free != NULL) {
258  sigmatch_table[sm->type].Free(sm->ctx);
259  }
260  }
261  SCFree(sm);
262 }
263 
264 static enum DetectKeywordId SigTableGetIndex(const SigTableElmt *e)
265 {
266  const SigTableElmt *table = &sigmatch_table[0];
267  ptrdiff_t offset = e - table;
269  return (enum DetectKeywordId)offset;
270 }
271 
272 /* Get the detection module by name */
273 static SigTableElmt *SigTableGet(char *name)
274 {
275  SigTableElmt *st = NULL;
276  int i = 0;
277 
278  for (i = 0; i < DETECT_TBLSIZE; i++) {
279  st = &sigmatch_table[i];
280 
281  if (st->name != NULL) {
282  if (strcasecmp(name,st->name) == 0)
283  return st;
284  if (st->alias != NULL && strcasecmp(name,st->alias) == 0)
285  return st;
286  }
287  }
288 
289  return NULL;
290 }
291 
293  const enum DetectKeywordId id)
294 {
295  return de_ctx->sm_types_silent_error[id];
296 }
297 
299 {
300  if (id < DETECT_TBLSIZE) {
301  return ((sigmatch_table[id].flags & SIGMATCH_STRICT_PARSING) != 0);
302  }
303  return false;
304 }
305 
307 {
308  if (str == NULL) {
309  /* nothing to be done */
310  return;
311  }
312 
313  /* "all" just sets the flag for each keyword */
314  if (strcmp(str, "all") == 0) {
315  for (int i = 0; i < DETECT_TBLSIZE; i++) {
316  SigTableElmt *st = &sigmatch_table[i];
318  }
319  return;
320  }
321 
322  char *copy = SCStrdup(str);
323  if (copy == NULL)
324  FatalError(SC_ERR_MEM_ALLOC, "could not duplicate opt string");
325 
326  char *xsaveptr = NULL;
327  char *key = strtok_r(copy, ",", &xsaveptr);
328  while (key != NULL) {
329  SigTableElmt *st = SigTableGet(key);
330  if (st != NULL) {
332  } else {
333  SCLogWarning(SC_ERR_CMD_LINE, "'strict' command line "
334  "argument '%s' not found", key);
335  }
336  key = strtok_r(NULL, ",", &xsaveptr);
337  }
338 
339  SCFree(copy);
340 }
341 
342 /**
343  * \brief Append a SigMatch to the list type.
344  *
345  * \param s Signature.
346  * \param new The sig match to append.
347  * \param list The list to append to.
348  */
349 void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
350 {
351  if (list > 0 && (uint32_t)list >= s->init_data->smlists_array_size)
352  {
353  uint32_t old_size = s->init_data->smlists_array_size;
354  uint32_t new_size = (uint32_t)list + 1;
355  void *ptr = SCRealloc(s->init_data->smlists, (new_size * sizeof(SigMatch *)));
356  if (ptr == NULL)
357  abort();
358  s->init_data->smlists = ptr;
359  ptr = SCRealloc(s->init_data->smlists_tail, (new_size * sizeof(SigMatch *)));
360  if (ptr == NULL)
361  abort();
362  s->init_data->smlists_tail = ptr;
363  for (uint32_t i = old_size; i < new_size; i++) {
364  s->init_data->smlists[i] = NULL;
365  s->init_data->smlists_tail[i] = NULL;
366  }
367  s->init_data->smlists_array_size = new_size;
368  }
369 
370  if (s->init_data->smlists[list] == NULL) {
371  s->init_data->smlists[list] = new;
372  s->init_data->smlists_tail[list] = new;
373  new->next = NULL;
374  new->prev = NULL;
375  } else {
376  SigMatch *cur = s->init_data->smlists_tail[list];
377  cur->next = new;
378  new->prev = cur;
379  new->next = NULL;
380  s->init_data->smlists_tail[list] = new;
381  }
382 
383  new->idx = s->init_data->sm_cnt;
384  s->init_data->sm_cnt++;
385 }
386 
387 void SigMatchRemoveSMFromList(Signature *s, SigMatch *sm, int sm_list)
388 {
389  if (sm == s->init_data->smlists[sm_list]) {
390  s->init_data->smlists[sm_list] = sm->next;
391  }
392  if (sm == s->init_data->smlists_tail[sm_list]) {
393  s->init_data->smlists_tail[sm_list] = sm->prev;
394  }
395  if (sm->prev != NULL)
396  sm->prev->next = sm->next;
397  if (sm->next != NULL)
398  sm->next->prev = sm->prev;
399 
400  return;
401 }
402 
403 /**
404  * \brief Returns a pointer to the last SigMatch instance of a particular type
405  * in a Signature of the payload list.
406  *
407  * \param s Pointer to the tail of the sigmatch list
408  * \param type SigMatch type which has to be searched for in the Signature.
409  *
410  * \retval match Pointer to the last SigMatch instance of type 'type'.
411  */
412 static SigMatch *SigMatchGetLastSMByType(SigMatch *sm, int type)
413 {
414  while (sm != NULL) {
415  if (sm->type == type) {
416  return sm;
417  }
418  sm = sm->prev;
419  }
420 
421  return NULL;
422 }
423 
424 /** \brief get the last SigMatch from lists that support
425  * MPM.
426  * \note only supports the lists that are registered through
427  * DetectBufferTypeSupportsMpm().
428  */
430 {
431  SigMatch *sm_last = NULL;
432  SigMatch *sm_new;
433  uint32_t sm_type;
434 
435  /* if we have a sticky buffer, use that */
436  if (s->init_data->list != DETECT_SM_LIST_NOTSET) {
438  return NULL;
439  }
440 
441  sm_last = DetectGetLastSMByListPtr(s,
443  DETECT_CONTENT, -1);
444  return sm_last;
445  }
446 
447  /* otherwise brute force it */
448  for (sm_type = 0; sm_type < s->init_data->smlists_array_size; sm_type++) {
450  continue;
451  SigMatch *sm_list = s->init_data->smlists_tail[sm_type];
452  sm_new = SigMatchGetLastSMByType(sm_list, DETECT_CONTENT);
453  if (sm_new == NULL)
454  continue;
455  if (sm_last == NULL || sm_new->idx > sm_last->idx)
456  sm_last = sm_new;
457  }
458 
459  return sm_last;
460 }
461 
462 /**
463  * \brief Returns the sm with the largest index (added latest) from the lists
464  * passed to us.
465  *
466  * \retval Pointer to Last sm.
467  */
469 {
470  SigMatch *sm_last = NULL;
471  SigMatch *sm_new;
472 
473  /* otherwise brute force it */
474  for (int buf_type = 0; buf_type < (int)s->init_data->smlists_array_size; buf_type++) {
475  if (s->init_data->smlists[buf_type] == NULL)
476  continue;
477  if (s->init_data->list != DETECT_SM_LIST_NOTSET &&
478  buf_type != s->init_data->list)
479  continue;
480 
481  int sm_type;
482  va_list ap;
483  va_start(ap, s);
484 
485  for (sm_type = va_arg(ap, int); sm_type != -1; sm_type = va_arg(ap, int))
486  {
487  sm_new = SigMatchGetLastSMByType(s->init_data->smlists_tail[buf_type], sm_type);
488  if (sm_new == NULL)
489  continue;
490  if (sm_last == NULL || sm_new->idx > sm_last->idx)
491  sm_last = sm_new;
492  }
493  va_end(ap);
494  }
495 
496  return sm_last;
497 }
498 
499 /**
500  * \brief Returns the sm with the largest index (added last) from the list
501  * passed to us as a pointer.
502  *
503  * \param sm_list pointer to the SigMatch we should look before
504  * \param va_args list of keyword types terminated by -1
505  *
506  * \retval sm_last to last sm.
507  */
509 {
510  SigMatch *sm_last = NULL;
511  SigMatch *sm_new;
512  int sm_type;
513 
514  va_list ap;
515  va_start(ap, sm_list);
516 
517  for (sm_type = va_arg(ap, int); sm_type != -1; sm_type = va_arg(ap, int))
518  {
519  sm_new = SigMatchGetLastSMByType(sm_list, sm_type);
520  if (sm_new == NULL)
521  continue;
522  if (sm_last == NULL || sm_new->idx > sm_last->idx)
523  sm_last = sm_new;
524  }
525 
526  va_end(ap);
527 
528  return sm_last;
529 }
530 
531 /**
532  * \brief Returns the sm with the largest index (added last) from the list
533  * passed to us as an id.
534  *
535  * \param list_id id of the list to be searched
536  * \param va_args list of keyword types terminated by -1
537  *
538  * \retval sm_last to last sm.
539  */
540 SigMatch *DetectGetLastSMByListId(const Signature *s, int list_id, ...)
541 {
542  SigMatch *sm_last = NULL;
543  SigMatch *sm_new;
544  int sm_type;
545 
546  SigMatch *sm_list = s->init_data->smlists_tail[list_id];
547  if (sm_list == NULL)
548  return NULL;
549 
550  va_list ap;
551  va_start(ap, list_id);
552 
553  for (sm_type = va_arg(ap, int); sm_type != -1; sm_type = va_arg(ap, int))
554  {
555  sm_new = SigMatchGetLastSMByType(sm_list, sm_type);
556  if (sm_new == NULL)
557  continue;
558  if (sm_last == NULL || sm_new->idx > sm_last->idx)
559  sm_last = sm_new;
560  }
561 
562  va_end(ap);
563 
564  return sm_last;
565 }
566 
567 /**
568  * \brief Returns the sm with the largest index (added latest) from this sig
569  *
570  * \retval sm_last Pointer to last sm
571  */
573 {
574  const int nlists = s->init_data->smlists_array_size;
575  SigMatch *sm_last = NULL;
576  SigMatch *sm_new;
577  int i;
578 
579  for (i = 0; i < nlists; i ++) {
580  sm_new = s->init_data->smlists_tail[i];
581  if (sm_new == NULL)
582  continue;
583  if (sm_last == NULL || sm_new->idx > sm_last->idx)
584  sm_last = sm_new;
585  }
586 
587  return sm_last;
588 }
589 
590 static void SigMatchTransferSigMatchAcrossLists(SigMatch *sm,
591  SigMatch **src_sm_list, SigMatch **src_sm_list_tail,
592  SigMatch **dst_sm_list, SigMatch **dst_sm_list_tail)
593 {
594  /* we won't do any checks for args */
595 
596  if (sm->prev != NULL)
597  sm->prev->next = sm->next;
598  if (sm->next != NULL)
599  sm->next->prev = sm->prev;
600 
601  if (sm == *src_sm_list)
602  *src_sm_list = sm->next;
603  if (sm == *src_sm_list_tail)
604  *src_sm_list_tail = sm->prev;
605 
606  if (*dst_sm_list == NULL) {
607  *dst_sm_list = sm;
608  *dst_sm_list_tail = sm;
609  sm->next = NULL;
610  sm->prev = NULL;
611  } else {
612  SigMatch *cur = *dst_sm_list_tail;
613  cur->next = sm;
614  sm->prev = cur;
615  sm->next = NULL;
616  *dst_sm_list_tail = sm;
617  }
618 
619  return;
620 }
621 
622 int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
623 {
624  const int nlists = s->init_data->smlists_array_size;
625  int list = 0;
626 
627  for (list = 0; list < nlists; list++) {
628  const SigMatch *sm = s->init_data->smlists[list];
629  while (sm != NULL) {
630  if (sm == key_sm)
631  return list;
632  sm = sm->next;
633  }
634  }
635 
636  SCLogError(SC_ERR_INVALID_SIGNATURE, "Unable to find the sm in any of the "
637  "sm lists");
638  return -1;
639 }
640 
641 static int SigParseOptions(DetectEngineCtx *de_ctx, Signature *s, char *optstr, char *output, size_t output_size)
642 {
643  SigTableElmt *st = NULL;
644  char *optname = NULL;
645  char *optvalue = NULL;
646 
647  /* Trim leading space. */
648  while (isblank(*optstr)) {
649  optstr++;
650  }
651 
652  /* Look for the end of this option, handling escaped semicolons. */
653  char *optend = optstr;
654  for (;;) {
655  optend = strchr(optend, ';');
656  if (optend == NULL) {
657  SCLogError(SC_ERR_INVALID_SIGNATURE, "no terminating \";\" found");
658  goto error;
659  }
660  else if (optend > optstr && *(optend -1 ) == '\\') {
661  optend++;
662  } else {
663  break;
664  }
665  }
666  *(optend++) = '\0';
667 
668  /* Find the start of the option value. */
669  char *optvalptr = strchr(optstr, ':');
670  if (optvalptr) {
671  *(optvalptr++) = '\0';
672 
673  /* Trim trailing space from name. */
674  for (size_t i = strlen(optvalptr); i > 0; i--) {
675  if (isblank(optvalptr[i - 1])) {
676  optvalptr[i - 1] = '\0';
677  } else {
678  break;
679  }
680  }
681 
682  optvalue = optvalptr;
683  }
684 
685  /* Trim trailing space from name. */
686  for (size_t i = strlen(optstr); i > 0; i--) {
687  if (isblank(optstr[i - 1])) {
688  optstr[i - 1] = '\0';
689  } else {
690  break;
691  }
692  }
693  optname = optstr;
694 
695  /* Call option parsing */
696  st = SigTableGet(optname);
697  if (st == NULL || st->Setup == NULL) {
698  SCLogError(SC_ERR_RULE_KEYWORD_UNKNOWN, "unknown rule keyword '%s'.", optname);
699  goto error;
700  }
701 
702  if (!(st->flags & (SIGMATCH_NOOPT|SIGMATCH_OPTIONAL_OPT))) {
703  if (optvalue == NULL || strlen(optvalue) == 0) {
704  SCLogError(SC_ERR_INVALID_SIGNATURE, "invalid formatting or malformed option to %s keyword: \'%s\'",
705  optname, optstr);
706  goto error;
707  }
708  }
709  s->init_data->negated = false;
710 
711  if (st->flags & SIGMATCH_INFO_DEPRECATED) {
712 #define URL "https://suricata-ids.org/about/deprecation-policy/"
713  if (st->alternative == 0)
714  SCLogWarning(SC_WARN_DEPRECATED, "keyword '%s' is deprecated "
715  "and will be removed soon. See %s", st->name, URL);
716  else
717  SCLogWarning(SC_WARN_DEPRECATED, "keyword '%s' is deprecated "
718  "and will be removed soon. Use '%s' instead. "
719  "See %s", st->name, sigmatch_table[st->alternative].name, URL);
720 #undef URL
721  }
722 
723  int setup_ret = 0;
724 
725  /* Validate double quoting, trimming trailing white space along the way. */
726  if (optvalue != NULL && strlen(optvalue) > 0) {
727  size_t ovlen = strlen(optvalue);
728  char *ptr = optvalue;
729 
730  /* skip leading whitespace */
731  while (ovlen > 0) {
732  if (!isblank(*ptr))
733  break;
734  ptr++;
735  ovlen--;
736  }
737  if (ovlen == 0) {
738  SCLogError(SC_ERR_INVALID_SIGNATURE, "invalid formatting or malformed option to %s keyword: \'%s\'",
739  optname, optstr);
740  goto error;
741  }
742 
743  /* see if value is negated */
744  if ((st->flags & SIGMATCH_HANDLE_NEGATION) && *ptr == '!') {
745  s->init_data->negated = true;
746  ptr++;
747  ovlen--;
748  }
749  /* skip more whitespace */
750  while (ovlen > 0) {
751  if (!isblank(*ptr))
752  break;
753  ptr++;
754  ovlen--;
755  }
756  if (ovlen == 0) {
757  SCLogError(SC_ERR_INVALID_SIGNATURE, "invalid formatting or malformed option to %s keyword: \'%s\'",
758  optname, optstr);
759  goto error;
760  }
761  /* if quoting is mandatory, enforce it */
762  if (st->flags & SIGMATCH_QUOTES_MANDATORY && ovlen && *ptr != '"') {
763  SCLogError(SC_ERR_INVALID_SIGNATURE, "invalid formatting to %s keyword: "
764  "value must be double quoted \'%s\'", optname, optstr);
765  goto error;
766  }
767 
769  && ovlen && *ptr == '"')
770  {
771  for (; ovlen > 0; ovlen--) {
772  if (isblank(ptr[ovlen - 1])) {
773  ptr[ovlen - 1] = '\0';
774  } else {
775  break;
776  }
777  }
778  if (ovlen && ptr[ovlen - 1] != '"') {
780  "bad option value formatting (possible missing semicolon) "
781  "for keyword %s: \'%s\'", optname, optvalue);
782  goto error;
783  }
784  if (ovlen > 1) {
785  /* strip leading " */
786  ptr++;
787  ovlen--;
788  ptr[ovlen - 1] = '\0';
789  ovlen--;
790  }
791  if (ovlen == 0) {
793  "bad input "
794  "for keyword %s: \'%s\'", optname, optvalue);
795  goto error;
796  }
797  } else {
798  if (*ptr == '"') {
799  SCLogError(SC_ERR_INVALID_SIGNATURE, "quotes on %s keyword that doesn't support them: \'%s\'",
800  optname, optstr);
801  goto error;
802  }
803  }
804  /* setup may or may not add a new SigMatch to the list */
805  setup_ret = st->Setup(de_ctx, s, ptr);
806  } else {
807  /* setup may or may not add a new SigMatch to the list */
808  setup_ret = st->Setup(de_ctx, s, NULL);
809  }
810  if (setup_ret < 0) {
811  SCLogDebug("\"%s\" failed to setup", st->name);
812 
813  /* handle 'silent' error case */
814  if (setup_ret == -2) {
815  enum DetectKeywordId idx = SigTableGetIndex(st);
816  if (de_ctx->sm_types_silent_error[idx] == false) {
817  de_ctx->sm_types_silent_error[idx] = true;
818  return -1;
819  }
820  return -2;
821  }
822  return setup_ret;
823  }
824  s->init_data->negated = false;
825 
826  if (strlen(optend) > 0) {
827  strlcpy(output, optend, output_size);
828  return 1;
829  }
830 
831  return 0;
832 
833 error:
834  return -1;
835 }
836 
837 /** \brief Parse address string and update signature
838  *
839  * \retval 0 ok, -1 error
840  */
841 static int SigParseAddress(DetectEngineCtx *de_ctx,
842  Signature *s, const char *addrstr, char flag)
843 {
844  SCLogDebug("Address Group \"%s\" to be parsed now", addrstr);
845 
846  /* pass on to the address(list) parser */
847  if (flag == 0) {
848  if (strcasecmp(addrstr, "any") == 0)
849  s->flags |= SIG_FLAG_SRC_ANY;
850 
851  s->init_data->src = DetectParseAddress(de_ctx, addrstr,
853  if (s->init_data->src == NULL)
854  goto error;
855  } else {
856  if (strcasecmp(addrstr, "any") == 0)
857  s->flags |= SIG_FLAG_DST_ANY;
858 
859  s->init_data->dst = DetectParseAddress(de_ctx, addrstr,
861  if (s->init_data->dst == NULL)
862  goto error;
863  }
864 
865  return 0;
866 
867 error:
868  return -1;
869 }
870 
871 /**
872  * \brief Parses the protocol supplied by the Signature.
873  *
874  * http://www.iana.org/assignments/protocol-numbers
875  *
876  * \param s Pointer to the Signature instance to which the parsed
877  * protocol has to be added.
878  * \param protostr Pointer to the character string containing the protocol name.
879  *
880  * \retval 0 On successfully parsing the protocl sent as the argument.
881  * \retval -1 On failure
882  */
883 static int SigParseProto(Signature *s, const char *protostr)
884 {
885  SCEnter();
886 
887  int r = DetectProtoParse(&s->proto, (char *)protostr);
888  if (r < 0) {
889  s->alproto = AppLayerGetProtoByName((char *)protostr);
890  /* indicate that the signature is app-layer */
891  if (s->alproto != ALPROTO_UNKNOWN) {
892  s->flags |= SIG_FLAG_APPLAYER;
893 
895  }
896  else {
897  SCLogError(SC_ERR_UNKNOWN_PROTOCOL, "protocol \"%s\" cannot be used "
898  "in a signature. Either detection for this protocol "
899  "is not yet supported OR detection has been disabled for "
900  "protocol through the yaml option "
901  "app-layer.protocols.%s.detection-enabled", protostr,
902  protostr);
903  SCReturnInt(-1);
904  }
905  }
906 
907  /* if any of these flags are set they are set in a mutually exclusive
908  * manner */
909  if (s->proto.flags & DETECT_PROTO_ONLY_PKT) {
911  } else if (s->proto.flags & DETECT_PROTO_ONLY_STREAM) {
913  }
914 
915  SCReturnInt(0);
916 }
917 
918 /**
919  * \brief Parses the port(source or destination) field, from a Signature.
920  *
921  * \param s Pointer to the signature which has to be updated with the
922  * port information.
923  * \param portstr Pointer to the character string containing the port info.
924  * \param Flag which indicates if the portstr received is src or dst
925  * port. For src port: flag = 0, dst port: flag = 1.
926  *
927  * \retval 0 On success.
928  * \retval -1 On failure.
929  */
930 static int SigParsePort(const DetectEngineCtx *de_ctx,
931  Signature *s, const char *portstr, char flag)
932 {
933  int r = 0;
934 
935  /* XXX VJ exclude handling this for none UDP/TCP proto's */
936 
937  SCLogDebug("Port group \"%s\" to be parsed", portstr);
938 
939  if (flag == 0) {
940  if (strcasecmp(portstr, "any") == 0)
941  s->flags |= SIG_FLAG_SP_ANY;
942 
943  r = DetectPortParse(de_ctx, &s->sp, (char *)portstr);
944  } else if (flag == 1) {
945  if (strcasecmp(portstr, "any") == 0)
946  s->flags |= SIG_FLAG_DP_ANY;
947 
948  r = DetectPortParse(de_ctx, &s->dp, (char *)portstr);
949  }
950 
951  if (r < 0)
952  return -1;
953 
954  return 0;
955 }
956 
957 /** \retval 1 valid
958  * \retval 0 invalid
959  */
960 static int SigParseActionRejectValidate(const char *action)
961 {
962 #ifdef HAVE_LIBNET11
963 #if defined HAVE_LIBCAP_NG && !defined HAVE_LIBNET_CAPABILITIES
964  if (sc_set_caps == TRUE) {
966  "incompatible with POSIX based capabilities with privs dropping. "
967  "For rejects to work, run as root/super user.");
968  return 0;
969  }
970 #endif
971 #else /* no libnet 1.1 */
973  "required for action \"%s\" but is not compiled into Suricata",
974  action);
975  return 0;
976 #endif
977  return 1;
978 }
979 
980 /**
981  * \brief Parses the action that has been used by the Signature and allots it
982  * to its Signature instance.
983  *
984  * \param s Pointer to the Signature instance to which the action belongs.
985  * \param action Pointer to the action string used by the Signature.
986  *
987  * \retval 0 On successfully parsing the action string and adding it to the
988  * Signature.
989  * \retval -1 On failure.
990  */
991 static int SigParseAction(Signature *s, const char *action)
992 {
993  if (strcasecmp(action, "alert") == 0) {
994  s->action = ACTION_ALERT;
995  return 0;
996  } else if (strcasecmp(action, "drop") == 0) {
997  s->action = ACTION_DROP;
998  return 0;
999  } else if (strcasecmp(action, "pass") == 0) {
1000  s->action = ACTION_PASS;
1001  return 0;
1002  } else if (strcasecmp(action, "reject") == 0) {
1003  if (!(SigParseActionRejectValidate(action)))
1004  return -1;
1006  return 0;
1007  } else if (strcasecmp(action, "rejectsrc") == 0) {
1008  if (!(SigParseActionRejectValidate(action)))
1009  return -1;
1011  return 0;
1012  } else if (strcasecmp(action, "rejectdst") == 0) {
1013  if (!(SigParseActionRejectValidate(action)))
1014  return -1;
1016  return 0;
1017  } else if (strcasecmp(action, "rejectboth") == 0) {
1018  if (!(SigParseActionRejectValidate(action)))
1019  return -1;
1021  return 0;
1022  } else {
1023  SCLogError(SC_ERR_INVALID_ACTION,"An invalid action \"%s\" was given",action);
1024  return -1;
1025  }
1026 }
1027 
1028 /**
1029  * \brief Parse the next token in rule.
1030  *
1031  * For rule parsing a token is considered to be a string of characters
1032  * separated by white space.
1033  *
1034  * \param input double pointer to input buffer, will be advanced as input is
1035  * parsed.
1036  * \param output buffer to copy token into.
1037  * \param output_size length of output buffer.
1038  */
1039 static inline int SigParseToken(char **input, char *output,
1040  const size_t output_size)
1041 {
1042  size_t len = *input == NULL ? 0 : strlen(*input);
1043 
1044  if (!len) {
1045  return 0;
1046  }
1047 
1048  while (len && isblank(**input)) {
1049  (*input)++;
1050  len--;
1051  }
1052 
1053  char *endptr = strpbrk(*input, " \t\n\r");
1054  if (endptr != NULL) {
1055  *(endptr++) = '\0';
1056  }
1057  strlcpy(output, *input, output_size);
1058  *input = endptr;
1059 
1060  return 1;
1061 }
1062 
1063 /**
1064  * \brief Parse the next rule "list" token.
1065  *
1066  * Parses rule tokens that may be lists such as addresses and ports
1067  * handling the case when they may not be lists.
1068  *
1069  * \param input ouble pointer to input buffer, will be advanced as input is
1070  * parsed.
1071  * \param output buffer to copy token into.
1072  * \param output_size length of output buffer.
1073  */
1074 static inline int SigParseList(char **input, char *output,
1075  const size_t output_size)
1076 {
1077  int in_list = 0;
1078  size_t len = *input != NULL ? strlen(*input) : 0;
1079 
1080  if (len == 0) {
1081  return 0;
1082  }
1083 
1084  while (len && isblank(**input)) {
1085  (*input)++;
1086  len--;
1087  }
1088 
1089  size_t i = 0;
1090  for (i = 0; i < len; i++) {
1091  char c = (*input)[i];
1092  if (c == '[') {
1093  in_list++;
1094  } else if (c == ']') {
1095  in_list--;
1096  } else if (c == ' ') {
1097  if (!in_list) {
1098  break;
1099  }
1100  }
1101  }
1102  if (i == len) {
1103  *input = NULL;
1104  return 0;
1105  }
1106  (*input)[i] = '\0';
1107  strlcpy(output, *input, output_size);
1108  *input = *input + i + 1;
1109 
1110  return 1;
1111 }
1112 
1113 /**
1114  * \internal
1115  * \brief split a signature string into a few blocks for further parsing
1116  */
1117 static int SigParseBasics(DetectEngineCtx *de_ctx,
1118  Signature *s, const char *sigstr, SignatureParser *parser, uint8_t addrs_direction)
1119 {
1120  char *index, dup[DETECT_MAX_RULE_SIZE];
1121 
1122  strlcpy(dup, sigstr, DETECT_MAX_RULE_SIZE);
1123  index = dup;
1124 
1125  /* Action. */
1126  SigParseToken(&index, parser->action, sizeof(parser->action));
1127 
1128  /* Protocol. */
1129  SigParseList(&index, parser->protocol, sizeof(parser->protocol));
1130 
1131  /* Source. */
1132  SigParseList(&index, parser->src, sizeof(parser->src));
1133 
1134  /* Source port(s). */
1135  SigParseList(&index, parser->sp, sizeof(parser->sp));
1136 
1137  /* Direction. */
1138  SigParseToken(&index, parser->direction, sizeof(parser->direction));
1139 
1140  /* Destination. */
1141  SigParseList(&index, parser->dst, sizeof(parser->dst));
1142 
1143  /* Destination port(s). */
1144  SigParseList(&index, parser->dp, sizeof(parser->dp));
1145 
1146  /* Options. */
1147  if (index == NULL) {
1148  SCLogError(SC_ERR_INVALID_RULE_ARGUMENT, "no rule options.");
1149  goto error;
1150  }
1151  while (isspace(*index) || *index == '(') {
1152  index++;
1153  }
1154  for (size_t i = strlen(index); i > 0; i--) {
1155  if (isspace(index[i - 1]) || index[i - 1] == ')') {
1156  index[i - 1] = '\0';
1157  } else {
1158  break;
1159  }
1160  }
1161  strlcpy(parser->opts, index, sizeof(parser->opts));
1162 
1163  /* Parse Action */
1164  if (SigParseAction(s, parser->action) < 0)
1165  goto error;
1166 
1167  if (SigParseProto(s, parser->protocol) < 0)
1168  goto error;
1169 
1170  if (strcmp(parser->direction, "<>") == 0) {
1172  } else if (strcmp(parser->direction, "->") != 0) {
1174  "\"%s\" is not a valid direction modifier, "
1175  "\"->\" and \"<>\" are supported.", parser->direction);
1176  goto error;
1177  }
1178 
1179  /* Parse Address & Ports */
1180  if (SigParseAddress(de_ctx, s, parser->src, SIG_DIREC_SRC ^ addrs_direction) < 0)
1181  goto error;
1182 
1183  if (SigParseAddress(de_ctx, s, parser->dst, SIG_DIREC_DST ^ addrs_direction) < 0)
1184  goto error;
1185 
1186  /* By AWS - Traditionally we should be doing this only for tcp/udp/sctp,
1187  * but we do it for regardless of ip proto, since the dns/dnstcp/dnsudp
1188  * changes that we made sees to it that at this point of time we don't
1189  * set the ip proto for the sig. We do it a bit later. */
1190  if (SigParsePort(de_ctx, s, parser->sp, SIG_DIREC_SRC ^ addrs_direction) < 0)
1191  goto error;
1192  if (SigParsePort(de_ctx, s, parser->dp, SIG_DIREC_DST ^ addrs_direction) < 0)
1193  goto error;
1194 
1195  return 0;
1196 
1197 error:
1198  return -1;
1199 }
1200 
1201 /**
1202  * \brief parse a signature
1203  *
1204  * \param de_ctx detection engine ctx to add it to
1205  * \param s memory structure to store the signature in
1206  * \param sigstr the raw signature as a null terminated string
1207  * \param addrs_direction direction (for bi-directional sigs)
1208  *
1209  * \param -1 parse error
1210  * \param 0 ok
1211  */
1212 static int SigParse(DetectEngineCtx *de_ctx, Signature *s,
1213  const char *sigstr, uint8_t addrs_direction, SignatureParser *parser)
1214 {
1215  SCEnter();
1216 
1217  s->sig_str = SCStrdup(sigstr);
1218  if (unlikely(s->sig_str == NULL)) {
1219  SCReturnInt(-1);
1220  }
1221 
1222  int ret = SigParseBasics(de_ctx, s, sigstr, parser, addrs_direction);
1223  if (ret < 0) {
1224  SCLogDebug("SigParseBasics failed");
1225  SCReturnInt(-1);
1226  }
1227 
1228  /* we can have no options, so make sure we have them */
1229  if (strlen(parser->opts) > 0) {
1230  size_t buffer_size = strlen(parser->opts) + 1;
1231  char input[buffer_size];
1232  char output[buffer_size];
1233  memset(input, 0x00, buffer_size);
1234  memcpy(input, parser->opts, strlen(parser->opts)+1);
1235 
1236  /* loop the option parsing. Each run processes one option
1237  * and returns the rest of the option string through the
1238  * output variable. */
1239  do {
1240  memset(output, 0x00, buffer_size);
1241  ret = SigParseOptions(de_ctx, s, input, output, buffer_size);
1242  if (ret == 1) {
1243  memcpy(input, output, buffer_size);
1244  }
1245 
1246  } while (ret == 1);
1247  }
1248 
1250 
1251  SCReturnInt(ret);
1252 }
1253 
1255 {
1256  Signature *sig = SCMalloc(sizeof(Signature));
1257  if (unlikely(sig == NULL))
1258  return NULL;
1259  memset(sig, 0, sizeof(Signature));
1260 
1261  sig->init_data = SCCalloc(1, sizeof(SignatureInitData));
1262  if (sig->init_data == NULL) {
1263  SCFree(sig);
1264  return NULL;
1265  }
1266 
1268  SCLogDebug("smlists size %u", sig->init_data->smlists_array_size);
1269  sig->init_data->smlists = SCCalloc(sig->init_data->smlists_array_size, sizeof(SigMatch *));
1270  if (sig->init_data->smlists == NULL) {
1271  SCFree(sig->init_data);
1272  SCFree(sig);
1273  return NULL;
1274  }
1275 
1277  if (sig->init_data->smlists_tail == NULL) {
1278  SCFree(sig->init_data->smlists_tail);
1279  SCFree(sig->init_data);
1280  SCFree(sig);
1281  return NULL;
1282  }
1283 
1284  /* assign it to -1, so that we can later check if the value has been
1285  * overwritten after the Signature has been parsed, and if it hasn't been
1286  * overwritten, we can then assign the default value of 3 */
1287  sig->prio = -1;
1288 
1290  return sig;
1291 }
1292 
1293 /**
1294  * \internal
1295  * \brief Free Medadata list
1296  *
1297  * \param s Pointer to the signature
1298  */
1299 static void SigMetadataFree(Signature *s)
1300 {
1301  SCEnter();
1302 
1303  DetectMetadata *mdata = NULL;
1304  DetectMetadata *next_mdata = NULL;
1305 
1306  if (s == NULL) {
1307  SCReturn;
1308  }
1309 
1310  SCLogDebug("s %p, s->metadata %p", s, s->metadata);
1311 
1312  for (mdata = s->metadata; mdata != NULL;) {
1313  next_mdata = mdata->next;
1314  DetectMetadataFree(mdata);
1315  mdata = next_mdata;
1316  }
1317 
1318  s->metadata = NULL;
1319 
1320  SCReturn;
1321 }
1322 
1323 /**
1324  * \internal
1325  * \brief Free Reference list
1326  *
1327  * \param s Pointer to the signature
1328  */
1329 static void SigRefFree (Signature *s)
1330 {
1331  SCEnter();
1332 
1333  DetectReference *ref = NULL;
1334  DetectReference *next_ref = NULL;
1335 
1336  if (s == NULL) {
1337  SCReturn;
1338  }
1339 
1340  SCLogDebug("s %p, s->references %p", s, s->references);
1341 
1342  for (ref = s->references; ref != NULL;) {
1343  next_ref = ref->next;
1344  DetectReferenceFree(ref);
1345  ref = next_ref;
1346  }
1347 
1348  s->references = NULL;
1349 
1350  SCReturn;
1351 }
1352 
1353 static void SigMatchFreeArrays(Signature *s, int ctxs)
1354 {
1355  if (s != NULL) {
1356  int type;
1357  for (type = 0; type < DETECT_SM_LIST_MAX; type++) {
1358  if (s->sm_arrays[type] != NULL) {
1359  if (ctxs) {
1360  SigMatchData *smd = s->sm_arrays[type];
1361  while(1) {
1362  if (sigmatch_table[smd->type].Free != NULL) {
1363  sigmatch_table[smd->type].Free(smd->ctx);
1364  }
1365  if (smd->is_last)
1366  break;
1367  smd++;
1368  }
1369  }
1370 
1371  SCFree(s->sm_arrays[type]);
1372  }
1373  }
1374  }
1375 }
1376 
1378 {
1379  if (s == NULL)
1380  return;
1381 
1382  if (s->CidrDst != NULL)
1384 
1385  if (s->CidrSrc != NULL)
1387 
1388  int i;
1389  if (s->init_data) {
1390  const int nlists = s->init_data->smlists_array_size;
1391  for (i = 0; i < nlists; i++) {
1392  SigMatch *sm = s->init_data->smlists[i];
1393  while (sm != NULL) {
1394  SigMatch *nsm = sm->next;
1395  SigMatchFree(sm);
1396  sm = nsm;
1397  }
1398  }
1399  }
1400  SigMatchFreeArrays(s, (s->init_data == NULL));
1401  if (s->init_data) {
1402  SCFree(s->init_data->smlists);
1404  SCFree(s->init_data);
1405  s->init_data = NULL;
1406  }
1407 
1408  if (s->sp != NULL) {
1409  DetectPortCleanupList(NULL, s->sp);
1410  }
1411  if (s->dp != NULL) {
1412  DetectPortCleanupList(NULL, s->dp);
1413  }
1414 
1415  if (s->msg != NULL)
1416  SCFree(s->msg);
1417 
1418  if (s->addr_src_match4 != NULL) {
1419  SCFree(s->addr_src_match4);
1420  }
1421  if (s->addr_dst_match4 != NULL) {
1422  SCFree(s->addr_dst_match4);
1423  }
1424  if (s->addr_src_match6 != NULL) {
1425  SCFree(s->addr_src_match6);
1426  }
1427  if (s->addr_dst_match6 != NULL) {
1428  SCFree(s->addr_dst_match6);
1429  }
1430  if (s->sig_str != NULL) {
1431  SCFree(s->sig_str);
1432  }
1433 
1434  SigRefFree(s);
1435  SigMetadataFree(s);
1436 
1438 
1439  SCFree(s);
1440 }
1441 
1443 {
1444  /* we only support buffers */
1445  if (s->init_data->list == 0) {
1446  SCReturnInt(-1);
1447  }
1448  if (!s->init_data->list_set) {
1449  SCLogError(SC_ERR_INVALID_SIGNATURE, "transforms must directly follow stickybuffers");
1450  SCReturnInt(-1);
1451  }
1453  SCReturnInt(-1);
1454  }
1455  s->init_data->transforms[s->init_data->transform_cnt++] = transform;
1456  SCReturnInt(0);
1457 }
1458 
1460 {
1461  if (alproto == ALPROTO_UNKNOWN ||
1462  alproto >= ALPROTO_FAILED) {
1463  SCLogError(SC_ERR_INVALID_ARGUMENT, "invalid alproto %u", alproto);
1464  return -1;
1465  }
1466 
1467  if (s->alproto != ALPROTO_UNKNOWN && s->alproto != alproto) {
1469  "can't set rule app proto to %s: already set to %s",
1470  AppProtoToString(alproto), AppProtoToString(s->alproto));
1471  return -1;
1472  }
1473 
1474  s->alproto = alproto;
1475  s->flags |= SIG_FLAG_APPLAYER;
1476  return 0;
1477 }
1478 
1479 /**
1480  * \internal
1481  * \brief build address match array for cache efficient matching
1482  *
1483  * \param s the signature
1484  */
1485 static void SigBuildAddressMatchArray(Signature *s)
1486 {
1487  /* source addresses */
1488  uint16_t cnt = 0;
1489  uint16_t idx = 0;
1490  DetectAddress *da = s->init_data->src->ipv4_head;
1491  for ( ; da != NULL; da = da->next) {
1492  cnt++;
1493  }
1494  if (cnt > 0) {
1495  s->addr_src_match4 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv4));
1496  if (s->addr_src_match4 == NULL) {
1497  exit(EXIT_FAILURE);
1498  }
1499 
1500  for (da = s->init_data->src->ipv4_head; da != NULL; da = da->next) {
1501  s->addr_src_match4[idx].ip = SCNtohl(da->ip.addr_data32[0]);
1502  s->addr_src_match4[idx].ip2 = SCNtohl(da->ip2.addr_data32[0]);
1503  idx++;
1504  }
1505  s->addr_src_match4_cnt = cnt;
1506  }
1507 
1508  /* destination addresses */
1509  cnt = 0;
1510  idx = 0;
1511  da = s->init_data->dst->ipv4_head;
1512  for ( ; da != NULL; da = da->next) {
1513  cnt++;
1514  }
1515  if (cnt > 0) {
1516  s->addr_dst_match4 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv4));
1517  if (s->addr_dst_match4 == NULL) {
1518  exit(EXIT_FAILURE);
1519  }
1520 
1521  for (da = s->init_data->dst->ipv4_head; da != NULL; da = da->next) {
1522  s->addr_dst_match4[idx].ip = SCNtohl(da->ip.addr_data32[0]);
1523  s->addr_dst_match4[idx].ip2 = SCNtohl(da->ip2.addr_data32[0]);
1524  idx++;
1525  }
1526  s->addr_dst_match4_cnt = cnt;
1527  }
1528 
1529  /* source addresses IPv6 */
1530  cnt = 0;
1531  idx = 0;
1532  da = s->init_data->src->ipv6_head;
1533  for ( ; da != NULL; da = da->next) {
1534  cnt++;
1535  }
1536  if (cnt > 0) {
1537  s->addr_src_match6 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv6));
1538  if (s->addr_src_match6 == NULL) {
1539  exit(EXIT_FAILURE);
1540  }
1541 
1542  for (da = s->init_data->src->ipv6_head; da != NULL; da = da->next) {
1543  s->addr_src_match6[idx].ip[0] = SCNtohl(da->ip.addr_data32[0]);
1544  s->addr_src_match6[idx].ip[1] = SCNtohl(da->ip.addr_data32[1]);
1545  s->addr_src_match6[idx].ip[2] = SCNtohl(da->ip.addr_data32[2]);
1546  s->addr_src_match6[idx].ip[3] = SCNtohl(da->ip.addr_data32[3]);
1547  s->addr_src_match6[idx].ip2[0] = SCNtohl(da->ip2.addr_data32[0]);
1548  s->addr_src_match6[idx].ip2[1] = SCNtohl(da->ip2.addr_data32[1]);
1549  s->addr_src_match6[idx].ip2[2] = SCNtohl(da->ip2.addr_data32[2]);
1550  s->addr_src_match6[idx].ip2[3] = SCNtohl(da->ip2.addr_data32[3]);
1551  idx++;
1552  }
1553  s->addr_src_match6_cnt = cnt;
1554  }
1555 
1556  /* destination addresses IPv6 */
1557  cnt = 0;
1558  idx = 0;
1559  da = s->init_data->dst->ipv6_head;
1560  for ( ; da != NULL; da = da->next) {
1561  cnt++;
1562  }
1563  if (cnt > 0) {
1564  s->addr_dst_match6 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv6));
1565  if (s->addr_dst_match6 == NULL) {
1566  exit(EXIT_FAILURE);
1567  }
1568 
1569  for (da = s->init_data->dst->ipv6_head; da != NULL; da = da->next) {
1570  s->addr_dst_match6[idx].ip[0] = SCNtohl(da->ip.addr_data32[0]);
1571  s->addr_dst_match6[idx].ip[1] = SCNtohl(da->ip.addr_data32[1]);
1572  s->addr_dst_match6[idx].ip[2] = SCNtohl(da->ip.addr_data32[2]);
1573  s->addr_dst_match6[idx].ip[3] = SCNtohl(da->ip.addr_data32[3]);
1574  s->addr_dst_match6[idx].ip2[0] = SCNtohl(da->ip2.addr_data32[0]);
1575  s->addr_dst_match6[idx].ip2[1] = SCNtohl(da->ip2.addr_data32[1]);
1576  s->addr_dst_match6[idx].ip2[2] = SCNtohl(da->ip2.addr_data32[2]);
1577  s->addr_dst_match6[idx].ip2[3] = SCNtohl(da->ip2.addr_data32[3]);
1578  idx++;
1579  }
1580  s->addr_dst_match6_cnt = cnt;
1581  }
1582 }
1583 
1584 static int SigMatchListLen(SigMatch *sm)
1585 {
1586  int len = 0;
1587  for (; sm != NULL; sm = sm->next)
1588  len++;
1589 
1590  return len;
1591 }
1592 
1593 /** \brief convert SigMatch list to SigMatchData array
1594  * \note ownership of sm->ctx is transfered to smd->ctx
1595  */
1597 {
1598  int len = SigMatchListLen(head);
1599  if (len == 0)
1600  return NULL;
1601 
1602  SigMatchData *smd = (SigMatchData *)SCCalloc(len, sizeof(SigMatchData));
1603  if (smd == NULL) {
1604  SCLogError(SC_ERR_DETECT_PREPARE, "initializing the detection engine failed");
1605  exit(EXIT_FAILURE);
1606  }
1607  SigMatchData *out = smd;
1608 
1609  /* Copy sm type and Context into array */
1610  SigMatch *sm = head;
1611  for (; sm != NULL; sm = sm->next, smd++) {
1612  smd->type = sm->type;
1613  smd->ctx = sm->ctx;
1614  sm->ctx = NULL; // SigMatch no longer owns the ctx
1615  smd->is_last = (sm->next == NULL);
1616  }
1617  return out;
1618 }
1619 
1620 /**
1621  * \internal
1622  * \brief validate a just parsed signature for internal inconsistencies
1623  *
1624  * \param s just parsed signature
1625  *
1626  * \retval 0 invalid
1627  * \retval 1 valid
1628  */
1629 static int SigValidate(DetectEngineCtx *de_ctx, Signature *s)
1630 {
1631  uint32_t sig_flags = 0;
1632  SigMatch *sm;
1633  const int nlists = s->init_data->smlists_array_size;
1634 
1635  SCEnter();
1636 
1637  /* check for sticky buffers that were set w/o matches
1638  * e.g. alert ... (file_data; sid:1;) */
1639  if (s->init_data->list != DETECT_SM_LIST_NOTSET) {
1640  if (s->init_data->smlists[s->init_data->list] == NULL) {
1641  SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u setup buffer %s but didn't add matches to it",
1643  SCReturnInt(0);
1644  }
1645  }
1646 
1647  /* run buffer type validation callbacks if any */
1650  SCReturnInt(0);
1651  }
1652 
1653  struct BufferVsDir {
1654  int ts;
1655  int tc;
1656  } bufdir[nlists];
1657  memset(&bufdir, 0, nlists * sizeof(struct BufferVsDir));
1658 
1659  int x;
1660  for (x = 0; x < nlists; x++) {
1661  if (s->init_data->smlists[x]) {
1663  for ( ; app != NULL; app = app->next) {
1664  if (app->sm_list == x && ((s->alproto == app->alproto) || s->alproto == 0)) {
1665  SCLogDebug("engine %s dir %d alproto %d",
1667  app->dir, app->alproto);
1668 
1669  bufdir[x].ts += (app->dir == 0);
1670  bufdir[x].tc += (app->dir == 1);
1671  }
1672  }
1673 
1675  SCReturnInt(0);
1676  }
1677  }
1678  }
1679 
1680  int ts_excl = 0;
1681  int tc_excl = 0;
1682  int dir_amb = 0;
1683  for (x = 0; x < nlists; x++) {
1684  if (bufdir[x].ts == 0 && bufdir[x].tc == 0)
1685  continue;
1686  ts_excl += (bufdir[x].ts > 0 && bufdir[x].tc == 0);
1687  tc_excl += (bufdir[x].ts == 0 && bufdir[x].tc > 0);
1688  dir_amb += (bufdir[x].ts > 0 && bufdir[x].tc > 0);
1689 
1690  SCLogDebug("%s/%d: %d/%d", DetectBufferTypeGetNameById(de_ctx, x),
1691  x, bufdir[x].ts, bufdir[x].tc);
1692  }
1693  if (ts_excl && tc_excl) {
1694  SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id);
1695  SCReturnInt(0);
1696  } else if (ts_excl) {
1697  SCLogDebug("%u: implied rule direction is toserver", s->id);
1699  SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id);
1700  SCReturnInt(0);
1701  }
1702  } else if (tc_excl) {
1703  SCLogDebug("%u: implied rule direction is toclient", s->id);
1705  SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id);
1706  SCReturnInt(0);
1707  }
1708  } else if (dir_amb) {
1709  SCLogDebug("%u: rule direction cannot be deduced from keywords", s->id);
1710  }
1711 
1712  if ((s->flags & SIG_FLAG_REQUIRE_PACKET) &&
1713  (s->flags & SIG_FLAG_REQUIRE_STREAM)) {
1714  SCLogError(SC_ERR_INVALID_SIGNATURE, "can't mix packet keywords with "
1715  "tcp-stream or flow:only_stream. Invalidating signature.");
1716  SCReturnInt(0);
1717  }
1718 
1719 #if 0 // TODO figure out why this is even necessary
1720  if ((s->init_data->smlists[DETECT_SM_LIST_FILEDATA] != NULL && s->alproto == ALPROTO_SMTP) ||
1721  s->init_data->smlists[DETECT_SM_LIST_UMATCH] != NULL ||
1722  s->init_data->smlists[DETECT_SM_LIST_HRUDMATCH] != NULL ||
1723  s->init_data->smlists[DETECT_SM_LIST_HCBDMATCH] != NULL ||
1724  s->init_data->smlists[DETECT_SM_LIST_HUADMATCH] != NULL) {
1725  sig_flags |= SIG_FLAG_TOSERVER;
1726  s->flags |= SIG_FLAG_TOSERVER;
1727  s->flags &= ~SIG_FLAG_TOCLIENT;
1728  }
1729  if ((s->init_data->smlists[DETECT_SM_LIST_FILEDATA] != NULL && s->alproto == ALPROTO_HTTP) ||
1730  s->init_data->smlists[DETECT_SM_LIST_HSMDMATCH] != NULL ||
1731  s->init_data->smlists[DETECT_SM_LIST_HSCDMATCH] != NULL) {
1732  sig_flags |= SIG_FLAG_TOCLIENT;
1733  s->flags |= SIG_FLAG_TOCLIENT;
1734  s->flags &= ~SIG_FLAG_TOSERVER;
1735  }
1736 #endif
1738  SCLogError(SC_ERR_INVALID_SIGNATURE,"You seem to have mixed keywords "
1739  "that require inspection in both directions. Atm we only "
1740  "support keywords in one direction within a rule.");
1741  SCReturnInt(0);
1742  }
1743 
1744  if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
1745  for (int i = 0; i < nlists; i++) {
1746  if (s->init_data->smlists[i] == NULL)
1747  continue;
1749  continue;
1750 
1752  SCLogError(SC_ERR_INVALID_SIGNATURE, "Signature combines packet "
1753  "specific matches (like dsize, flags, ttl) with stream / "
1754  "state matching by matching on app layer proto (like using "
1755  "http_* keywords).");
1756  SCReturnInt(0);
1757  }
1758  }
1759  }
1760 
1761  /* TCP: corner cases:
1762  * - pkt vs stream vs depth/offset
1763  * - pkt vs stream vs stream_size
1764  */
1765  if (s->proto.proto[IPPROTO_TCP / 8] & (1 << (IPPROTO_TCP % 8))) {
1770  while (sm != NULL) {
1771  if (sm->type == DETECT_CONTENT &&
1772  (((DetectContentData *)(sm->ctx))->flags &
1775  break;
1776  }
1777  sm = sm->next;
1778  }
1779  /* if stream_size is in use, also inspect packets */
1781  while (sm != NULL) {
1782  if (sm->type == DETECT_STREAM_SIZE) {
1784  break;
1785  }
1786  sm = sm->next;
1787  }
1788  }
1789  }
1790  }
1791 
1792  if (s->init_data->smlists[DETECT_SM_LIST_BASE64_DATA] != NULL) {
1793  int list;
1794  uint16_t idx = s->init_data->smlists[DETECT_SM_LIST_BASE64_DATA]->idx;
1795  for (list = 0; list < nlists; list++) {
1796  if (list == DETECT_SM_LIST_POSTMATCH ||
1797  list == DETECT_SM_LIST_TMATCH ||
1798  list == DETECT_SM_LIST_SUPPRESS ||
1799  list == DETECT_SM_LIST_THRESHOLD)
1800  {
1801  continue;
1802  }
1803 
1804  if (list != DETECT_SM_LIST_BASE64_DATA &&
1805  s->init_data->smlists[list] != NULL) {
1806  if (s->init_data->smlists[list]->idx > idx) {
1807  SCLogError(SC_ERR_INVALID_SIGNATURE, "Rule buffer "
1808  "cannot be reset after base64_data.");
1809  SCReturnInt(0);
1810  }
1811  }
1812  }
1813  }
1814 
1815 #ifdef HAVE_LUA
1816  DetectLuaPostSetup(s);
1817 #endif
1818 
1819 #ifdef DEBUG
1820  int i;
1821  for (i = 0; i < nlists; i++) {
1822  if (s->init_data->smlists[i] != NULL) {
1823  for (sm = s->init_data->smlists[i]; sm != NULL; sm = sm->next) {
1824  BUG_ON(sm == sm->prev);
1825  BUG_ON(sm == sm->next);
1826  }
1827  }
1828  }
1829 #endif
1830 
1831  if ((s->flags & SIG_FLAG_FILESTORE) || s->file_flags != 0) {
1832  if (s->alproto != ALPROTO_UNKNOWN &&
1833  !AppLayerParserSupportsFiles(IPPROTO_TCP, s->alproto))
1834  {
1835  SCLogError(SC_ERR_NO_FILES_FOR_PROTOCOL, "protocol %s doesn't "
1836  "support file matching", AppProtoToString(s->alproto));
1837  SCReturnInt(0);
1838  }
1839 
1840  if (s->alproto == ALPROTO_HTTP) {
1842  }
1843  }
1844 
1845  SCReturnInt(1);
1846 }
1847 
1848 /**
1849  * \internal
1850  * \brief Helper function for SigInit().
1851  */
1852 static Signature *SigInitHelper(DetectEngineCtx *de_ctx, const char *sigstr,
1853  uint8_t dir)
1854 {
1855  SignatureParser parser;
1856  memset(&parser, 0x00, sizeof(parser));
1857 
1858  Signature *sig = SigAlloc();
1859  if (sig == NULL)
1860  goto error;
1861 
1862  /* default gid to 1 */
1863  sig->gid = 1;
1864 
1865  int ret = SigParse(de_ctx, sig, sigstr, dir, &parser);
1866  if (ret == -3) {
1867  de_ctx->sigerror_silent = true;
1868  de_ctx->sigerror_ok = true;
1869  goto error;
1870  }
1871  else if (ret == -2) {
1872  de_ctx->sigerror_silent = true;
1873  goto error;
1874  } else if (ret < 0) {
1875  goto error;
1876  }
1877 
1878  /* signature priority hasn't been overwritten. Using default priority */
1879  if (sig->prio == -1)
1880  sig->prio = DETECT_DEFAULT_PRIO;
1881 
1882  sig->num = de_ctx->signum;
1883  de_ctx->signum++;
1884 
1885  if (sig->alproto != ALPROTO_UNKNOWN) {
1886  int override_needed = 0;
1887  if (sig->proto.flags & DETECT_PROTO_ANY) {
1888  sig->proto.flags &= ~DETECT_PROTO_ANY;
1889  memset(sig->proto.proto, 0x00, sizeof(sig->proto.proto));
1890  override_needed = 1;
1891  } else {
1892  override_needed = 1;
1893  size_t s = 0;
1894  for (s = 0; s < sizeof(sig->proto.proto); s++) {
1895  if (sig->proto.proto[s] != 0x00) {
1896  override_needed = 0;
1897  break;
1898  }
1899  }
1900  }
1901 
1902  /* at this point if we had alert ip and the ip proto was not
1903  * overridden, we use the ip proto that has been configured
1904  * against the app proto in use. */
1905  if (override_needed)
1907  }
1908 
1909  ret = DetectAppLayerEventPrepare(sig);
1910  if (ret == -3) {
1911  de_ctx->sigerror_silent = true;
1912  de_ctx->sigerror_ok = true;
1913  goto error;
1914  }
1915  else if (ret == -2) {
1916  de_ctx->sigerror_silent = true;
1917  goto error;
1918  } else if (ret < 0) {
1919  goto error;
1920  }
1921 
1922  /* set the packet and app layer flags, but only if the
1923  * app layer flag wasn't already set in which case we
1924  * only consider the app layer */
1925  if (!(sig->flags & SIG_FLAG_APPLAYER)) {
1926  if (sig->init_data->smlists[DETECT_SM_LIST_MATCH] != NULL) {
1928  for ( ; sm != NULL; sm = sm->next) {
1929  if (sigmatch_table[sm->type].Match != NULL)
1931  }
1932  } else {
1934  }
1935  }
1936 
1937  if (!(sig->init_data->init_flags & SIG_FLAG_INIT_FLOW)) {
1938  if ((sig->flags & (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)) == 0) {
1939  sig->flags |= SIG_FLAG_TOSERVER;
1940  sig->flags |= SIG_FLAG_TOCLIENT;
1941  }
1942  }
1943 
1944  SCLogDebug("sig %"PRIu32" SIG_FLAG_APPLAYER: %s, SIG_FLAG_PACKET: %s",
1945  sig->id, sig->flags & SIG_FLAG_APPLAYER ? "set" : "not set",
1946  sig->init_data->init_flags & SIG_FLAG_INIT_PACKET ? "set" : "not set");
1947 
1948  SigBuildAddressMatchArray(sig);
1949 
1950  /* run buffer type callbacks if any */
1951  for (uint32_t x = 0; x < sig->init_data->smlists_array_size; x++) {
1952  if (sig->init_data->smlists[x])
1954  }
1955 
1956  /* validate signature, SigValidate will report the error reason */
1957  if (SigValidate(de_ctx, sig) == 0) {
1958  goto error;
1959  }
1960 
1961  /* check what the type of this sig is */
1962  SignatureSetType(de_ctx, sig);
1963 
1964  if (sig->flags & SIG_FLAG_IPONLY) {
1965  /* For IPOnly */
1966  if (IPOnlySigParseAddress(de_ctx, sig, parser.src, SIG_DIREC_SRC ^ dir) < 0)
1967  goto error;
1968 
1969  if (IPOnlySigParseAddress(de_ctx, sig, parser.dst, SIG_DIREC_DST ^ dir) < 0)
1970  goto error;
1971  }
1972  return sig;
1973 
1974 error:
1975  if (sig != NULL) {
1976  SigFree(sig);
1977  }
1978  return NULL;
1979 }
1980 
1981 /**
1982  * \brief Checks if a signature has the same source and destination
1983  * \param s parsed signature
1984  *
1985  * \retval true if source and destination are the same, false otherwise
1986  */
1987 static bool SigHasSameSourceAndDestination(const Signature *s)
1988 {
1989  if (!(s->flags & SIG_FLAG_SP_ANY) || !(s->flags & SIG_FLAG_DP_ANY)) {
1990  if (!DetectPortListsAreEqual(s->sp, s->dp)) {
1991  return false;
1992  }
1993  }
1994 
1995  if (!(s->flags & SIG_FLAG_SRC_ANY) || !(s->flags & SIG_FLAG_DST_ANY)) {
1998 
2000  return false;
2001  }
2002 
2003  src = s->init_data->src->ipv6_head;
2004  dst = s->init_data->dst->ipv6_head;
2005 
2007  return false;
2008  }
2009  }
2010 
2011  return true;
2012 }
2013 
2014 /**
2015  * \brief Parses a signature and adds it to the Detection Engine Context.
2016  *
2017  * \param de_ctx Pointer to the Detection Engine Context.
2018  * \param sigstr Pointer to a character string containing the signature to be
2019  * parsed.
2020  *
2021  * \retval Pointer to the Signature instance on success; NULL on failure.
2022  */
2023 Signature *SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
2024 {
2025  SCEnter();
2026 
2027  uint32_t oldsignum = de_ctx->signum;
2028  de_ctx->sigerror_silent = false;
2029 
2030  Signature *sig;
2031 
2032  if ((sig = SigInitHelper(de_ctx, sigstr, SIG_DIREC_NORMAL)) == NULL) {
2033  goto error;
2034  }
2035 
2037  if (SigHasSameSourceAndDestination(sig)) {
2038  SCLogInfo("Rule with ID %u is bidirectional, but source and destination are the same, "
2039  "treating the rule as unidirectional", sig->id);
2040 
2042  } else {
2043  sig->next = SigInitHelper(de_ctx, sigstr, SIG_DIREC_SWITCHED);
2044  if (sig->next == NULL) {
2045  goto error;
2046  }
2047  }
2048  }
2049 
2050  SCReturnPtr(sig, "Signature");
2051 
2052 error:
2053  if (sig != NULL) {
2054  SigFree(sig);
2055  }
2056  /* if something failed, restore the old signum count
2057  * since we didn't install it */
2058  de_ctx->signum = oldsignum;
2059 
2060  SCReturnPtr(NULL, "Signature");
2061 }
2062 
2063 /**
2064  * \brief The hash free function to be the used by the hash table -
2065  * DetectEngineCtx->dup_sig_hash_table.
2066  *
2067  * \param data Pointer to the data, in our case SigDuplWrapper to be freed.
2068  */
2069 static void DetectParseDupSigFreeFunc(void *data)
2070 {
2071  if (data != NULL)
2072  SCFree(data);
2073 
2074  return;
2075 }
2076 
2077 /**
2078  * \brief The hash function to be the used by the hash table -
2079  * DetectEngineCtx->dup_sig_hash_table.
2080  *
2081  * \param ht Pointer to the hash table.
2082  * \param data Pointer to the data, in our case SigDuplWrapper.
2083  * \param datalen Not used in our case.
2084  *
2085  * \retval sw->s->id The generated hash value.
2086  */
2087 static uint32_t DetectParseDupSigHashFunc(HashListTable *ht, void *data, uint16_t datalen)
2088 {
2089  SigDuplWrapper *sw = (SigDuplWrapper *)data;
2090 
2091  return (sw->s->id % ht->array_size);
2092 }
2093 
2094 /**
2095  * \brief The Compare function to be used by the hash table -
2096  * DetectEngineCtx->dup_sig_hash_table.
2097  *
2098  * \param data1 Pointer to the first SigDuplWrapper.
2099  * \param len1 Not used.
2100  * \param data2 Pointer to the second SigDuplWrapper.
2101  * \param len2 Not used.
2102  *
2103  * \retval 1 If the 2 SigDuplWrappers sent as args match.
2104  * \retval 0 If the 2 SigDuplWrappers sent as args do not match.
2105  */
2106 static char DetectParseDupSigCompareFunc(void *data1, uint16_t len1, void *data2,
2107  uint16_t len2)
2108 {
2109  SigDuplWrapper *sw1 = (SigDuplWrapper *)data1;
2110  SigDuplWrapper *sw2 = (SigDuplWrapper *)data2;
2111 
2112  if (sw1 == NULL || sw2 == NULL ||
2113  sw1->s == NULL || sw2->s == NULL)
2114  return 0;
2115 
2116  /* sid and gid match required */
2117  if (sw1->s->id == sw2->s->id && sw1->s->gid == sw2->s->gid) return 1;
2118 
2119  return 0;
2120 }
2121 
2122 /**
2123  * \brief Initializes the hash table that is used to cull duplicate sigs.
2124  *
2125  * \param de_ctx Pointer to the detection engine context.
2126  *
2127  * \retval 0 On success.
2128  * \retval -1 On failure.
2129  */
2131 {
2133  DetectParseDupSigHashFunc,
2134  DetectParseDupSigCompareFunc,
2135  DetectParseDupSigFreeFunc);
2136  if (de_ctx->dup_sig_hash_table == NULL)
2137  return -1;
2138 
2139  return 0;
2140 }
2141 
2142 /**
2143  * \brief Frees the hash table that is used to cull duplicate sigs.
2144  *
2145  * \param de_ctx Pointer to the detection engine context that holds this table.
2146  */
2148 {
2149  if (de_ctx->dup_sig_hash_table != NULL)
2151 
2152  de_ctx->dup_sig_hash_table = NULL;
2153 
2154  return;
2155 }
2156 
2157 /**
2158  * \brief Check if a signature is a duplicate.
2159  *
2160  * There are 3 types of return values for this function.
2161  *
2162  * - 0, which indicates that the Signature is not a duplicate
2163  * and has to be added to the detection engine list.
2164  * - 1, Signature is duplicate, and the existing signature in
2165  * the list shouldn't be replaced with this duplicate.
2166  * - 2, Signature is duplicate, and the existing signature in
2167  * the list should be replaced with this duplicate.
2168  *
2169  * \param de_ctx Pointer to the detection engine context.
2170  * \param sig Pointer to the Signature that has to be checked.
2171  *
2172  * \retval 2 If Signature is duplicate and the existing signature in
2173  * the list should be chucked out and replaced with this.
2174  * \retval 1 If Signature is duplicate, and should be chucked out.
2175  * \retval 0 If Signature is not a duplicate.
2176  */
2177 static inline int DetectEngineSignatureIsDuplicate(DetectEngineCtx *de_ctx,
2178  Signature *sig)
2179 {
2180  /* we won't do any NULL checks on the args */
2181 
2182  /* return value */
2183  int ret = 0;
2184 
2185  SigDuplWrapper *sw_dup = NULL;
2186  SigDuplWrapper *sw = NULL;
2187 
2188  /* used for making a duplicate_sig_hash_table entry */
2189  sw = SCMalloc(sizeof(SigDuplWrapper));
2190  if (unlikely(sw == NULL)) {
2191  exit(EXIT_FAILURE);
2192  }
2193  memset(sw, 0, sizeof(SigDuplWrapper));
2194  sw->s = sig;
2195 
2196  /* check if we have a duplicate entry for this signature */
2197  sw_dup = HashListTableLookup(de_ctx->dup_sig_hash_table, (void *)sw, 0);
2198  /* we don't have a duplicate entry for this sig */
2199  if (sw_dup == NULL) {
2200  /* add it to the hash table */
2201  HashListTableAdd(de_ctx->dup_sig_hash_table, (void *)sw, 0);
2202 
2203  /* add the s_prev entry for the previously loaded sw in the hash_table */
2204  if (de_ctx->sig_list != NULL) {
2205  SigDuplWrapper *sw_old = NULL;
2206  SigDuplWrapper sw_tmp;
2207  memset(&sw_tmp, 0, sizeof(SigDuplWrapper));
2208 
2209  /* the topmost sig would be the last loaded sig */
2210  sw_tmp.s = de_ctx->sig_list;
2212  (void *)&sw_tmp, 0);
2213  /* sw_old == NULL case is impossible */
2214  sw_old->s_prev = sig;
2215  }
2216 
2217  ret = 0;
2218  goto end;
2219  }
2220 
2221  /* if we have reached here we have a duplicate entry for this signature.
2222  * Check the signature revision. Store the signature with the latest rev
2223  * and discard the other one */
2224  if (sw->s->rev <= sw_dup->s->rev) {
2225  ret = 1;
2226  SCFree(sw);
2227  sw = NULL;
2228  goto end;
2229  }
2230 
2231  /* the new sig is of a newer revision than the one that is already in the
2232  * list. Remove the old sig from the list */
2233  if (sw_dup->s_prev == NULL) {
2234  SigDuplWrapper sw_temp;
2235  memset(&sw_temp, 0, sizeof(SigDuplWrapper));
2236  if (sw_dup->s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2237  sw_temp.s = sw_dup->s->next->next;
2238  de_ctx->sig_list = sw_dup->s->next->next;
2239  SigFree(sw_dup->s->next);
2240  } else {
2241  sw_temp.s = sw_dup->s->next;
2242  de_ctx->sig_list = sw_dup->s->next;
2243  }
2244  SigDuplWrapper *sw_next = NULL;
2245  if (sw_temp.s != NULL) {
2247  (void *)&sw_temp, 0);
2248  sw_next->s_prev = sw_dup->s_prev;
2249  }
2250  SigFree(sw_dup->s);
2251  } else {
2252  SigDuplWrapper sw_temp;
2253  memset(&sw_temp, 0, sizeof(SigDuplWrapper));
2254  if (sw_dup->s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2255  sw_temp.s = sw_dup->s->next->next;
2256  sw_dup->s_prev->next = sw_dup->s->next->next;
2257  SigFree(sw_dup->s->next);
2258  } else {
2259  sw_temp.s = sw_dup->s->next;
2260  sw_dup->s_prev->next = sw_dup->s->next;
2261  }
2262  SigDuplWrapper *sw_next = NULL;
2263  if (sw_temp.s != NULL) {
2265  (void *)&sw_temp, 0);
2266  sw_next->s_prev = sw_dup->s_prev;;
2267  }
2268  SigFree(sw_dup->s);
2269  }
2270 
2271  /* make changes to the entry to reflect the presence of the new sig */
2272  sw_dup->s = sig;
2273  sw_dup->s_prev = NULL;
2274 
2275  if (de_ctx->sig_list != NULL) {
2276  SigDuplWrapper sw_tmp;
2277  memset(&sw_tmp, 0, sizeof(SigDuplWrapper));
2278  sw_tmp.s = de_ctx->sig_list;
2280  (void *)&sw_tmp, 0);
2281  if (sw_old->s != sw_dup->s) {
2282  // Link on top of the list if there was another element
2283  sw_old->s_prev = sig;
2284  }
2285  }
2286 
2287  /* this is duplicate, but a duplicate that replaced the existing sig entry */
2288  ret = 2;
2289 
2290  SCFree(sw);
2291 
2292 end:
2293  return ret;
2294 }
2295 
2296 /**
2297  * \brief Parse and append a Signature into the Detection Engine Context
2298  * signature list.
2299  *
2300  * If the signature is bidirectional it should append two signatures
2301  * (with the addresses switched) into the list. Also handle duplicate
2302  * signatures. In case of duplicate sigs, use the ones that have the
2303  * latest revision. We use the sid and the msg to identifiy duplicate
2304  * sigs. If 2 sigs have the same sid and gid, they are duplicates.
2305  *
2306  * \param de_ctx Pointer to the Detection Engine Context.
2307  * \param sigstr Pointer to a character string containing the signature to be
2308  * parsed.
2309  * \param sig_file Pointer to a character string containing the filename from
2310  * which signature is read
2311  * \param lineno Line number from where signature is read
2312  *
2313  * \retval Pointer to the head Signature in the detection engine ctx sig_list
2314  * on success; NULL on failure.
2315  */
2317 {
2318  Signature *sig = SigInit(de_ctx, sigstr);
2319  if (sig == NULL) {
2320  return NULL;
2321  }
2322 
2323  /* checking for the status of duplicate signature */
2324  int dup_sig = DetectEngineSignatureIsDuplicate(de_ctx, sig);
2325  /* a duplicate signature that should be chucked out. Check the previously
2326  * called function details to understand the different return values */
2327  if (dup_sig == 1) {
2328  SCLogError(SC_ERR_DUPLICATE_SIG, "Duplicate signature \"%s\"", sigstr);
2329  goto error;
2330  } else if (dup_sig == 2) {
2331  SCLogWarning(SC_ERR_DUPLICATE_SIG, "Signature with newer revision,"
2332  " so the older sig replaced by this new signature \"%s\"",
2333  sigstr);
2334  }
2335 
2337  if (sig->next != NULL) {
2338  sig->next->next = de_ctx->sig_list;
2339  } else {
2340  goto error;
2341  }
2342  } else {
2343  /* if this sig is the first one, sig_list should be null */
2344  sig->next = de_ctx->sig_list;
2345  }
2346 
2347  de_ctx->sig_list = sig;
2348 
2349  /**
2350  * In DetectEngineAppendSig(), the signatures are prepended and we always return the first one
2351  * so if the signature is bidirectional, the returned sig will point through "next" ptr
2352  * to the cloned signatures with the switched addresses
2353  */
2354  return (dup_sig == 0 || dup_sig == 2) ? sig : NULL;
2355 
2356 error:
2357  if (sig != NULL)
2358  SigFree(sig);
2359  return NULL;
2360 }
2361 
2362 static DetectParseRegex *g_detect_parse_regex_list = NULL;
2363 int DetectParsePcreExecLen(DetectParseRegex *parse_regex, const char *str,
2364  int str_len,
2365  int start_offset, int options,
2366  int *ovector, int ovector_size)
2367 {
2368  return pcre_exec(parse_regex->regex, parse_regex->study, str, str_len,
2369  start_offset, options, ovector, ovector_size);
2370 }
2371 
2372 int DetectParsePcreExec(DetectParseRegex *parse_regex, const char *str,
2373  int start_offset, int options,
2374  int *ovector, int ovector_size)
2375 {
2376  return pcre_exec(parse_regex->regex, parse_regex->study, str, strlen(str),
2377  start_offset, options, ovector, ovector_size);
2378 }
2379 
2381 {
2382  if (r->regex) {
2383  pcre_free(r->regex);
2384  }
2385  if (r->study) {
2386  pcre_free_study(r->study);
2387  }
2388 }
2389 
2391 {
2392  DetectParseRegex *r = g_detect_parse_regex_list;
2393  while (r) {
2394  DetectParseRegex *next = r->next;
2395 
2397 
2398  SCFree(r);
2399  r = next;
2400  }
2401  g_detect_parse_regex_list = NULL;
2402 }
2403 
2404 /** \brief add regex and/or study to at exit free list
2405  */
2407 {
2408  DetectParseRegex *r = SCCalloc(1, sizeof(*r));
2409  if (r == NULL) {
2410  FatalError(SC_ERR_MEM_ALLOC, "failed to alloc memory for pcre free list");
2411  }
2412  r->regex = detect_parse->regex;
2413  r->study = detect_parse->study;
2414  r->next = g_detect_parse_regex_list;
2415  g_detect_parse_regex_list = r;
2416 }
2417 
2418 void DetectSetupParseRegexesOpts(const char *parse_str, DetectParseRegex *detect_parse, int opts)
2419 {
2420  const char *eb;
2421  int eo;
2422 
2423  detect_parse->regex = pcre_compile(parse_str, opts, &eb, &eo, NULL);
2424  if (detect_parse->regex == NULL) {
2425  FatalError(SC_ERR_PCRE_COMPILE, "pcre compile of \"%s\" failed at "
2426  "offset %" PRId32 ": %s", parse_str, eo, eb);
2427  }
2428 
2429  detect_parse->study = pcre_study(detect_parse->regex, 0 , &eb);
2430  if (eb != NULL) {
2431  FatalError(SC_ERR_PCRE_STUDY, "pcre study failed: %s", eb);
2432  }
2433 
2434 
2435  DetectParseRegexAddToFreeList(detect_parse);
2436 
2437  return;
2438 }
2439 
2440 void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
2441 {
2442  DetectSetupParseRegexesOpts(parse_str, detect_parse, 0);
2443  return;
2444 }
2445 
2446 
2447 /*
2448  * TESTS
2449  */
2450 
2451 #ifdef UNITTESTS
2452 static int SigParseTest01 (void)
2453 {
2454  int result = 1;
2455  Signature *sig = NULL;
2456 
2458  if (de_ctx == NULL)
2459  goto end;
2460 
2461  sig = SigInit(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1;)");
2462  if (sig == NULL)
2463  result = 0;
2464 
2465 end:
2466  if (sig != NULL) SigFree(sig);
2467  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2468  return result;
2469 }
2470 
2471 static int SigParseTest02 (void)
2472 {
2473  int result = 0;
2474  Signature *sig = NULL;
2475  DetectPort *port = NULL;
2476 
2478 
2479  if (de_ctx == NULL)
2480  goto end;
2481 
2484 
2485  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"ET MALWARE Suspicious 220 Banner on Local Port\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; sid:2003055; rev:4;)");
2486  if (sig == NULL) {
2487  goto end;
2488  }
2489 
2490  int r = DetectPortParse(de_ctx, &port, "0:20");
2491  if (r < 0)
2492  goto end;
2493 
2494  if (DetectPortCmp(sig->sp, port) == PORT_EQ) {
2495  result = 1;
2496  } else {
2497  DetectPortPrint(port); printf(" != "); DetectPortPrint(sig->sp); printf(": ");
2498  }
2499 
2500 end:
2501  if (port != NULL)
2503  if (sig != NULL)
2504  SigFree(sig);
2505  if (de_ctx != NULL)
2507  return result;
2508 }
2509 
2510 /**
2511  * \test SigParseTest03 test for invalid direction operator in rule
2512  */
2513 static int SigParseTest03 (void)
2514 {
2515  int result = 1;
2516  Signature *sig = NULL;
2517 
2519  if (de_ctx == NULL)
2520  goto end;
2521 
2522  sig = SigInit(de_ctx, "alert tcp 1.2.3.4 any <- !1.2.3.4 any (msg:\"SigParseTest03\"; sid:1;)");
2523  if (sig != NULL) {
2524  result = 0;
2525  printf("expected NULL got sig ptr %p: ",sig);
2526  }
2527 
2528 end:
2529  if (sig != NULL) SigFree(sig);
2530  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2531  return result;
2532 }
2533 
2534 static int SigParseTest04 (void)
2535 {
2536  int result = 1;
2537  Signature *sig = NULL;
2538 
2540  if (de_ctx == NULL)
2541  goto end;
2542 
2543  sig = SigInit(de_ctx, "alert tcp 1.2.3.4 1024: -> !1.2.3.4 1024: (msg:\"SigParseTest04\"; sid:1;)");
2544  if (sig == NULL)
2545  result = 0;
2546 
2547 end:
2548  if (sig != NULL) SigFree(sig);
2549  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2550  return result;
2551 }
2552 
2553 /** \test Port validation */
2554 static int SigParseTest05 (void)
2555 {
2556  int result = 0;
2557  Signature *sig = NULL;
2558 
2560  if (de_ctx == NULL)
2561  goto end;
2562 
2563  sig = SigInit(de_ctx, "alert tcp 1.2.3.4 1024:65536 -> !1.2.3.4 any (msg:\"SigParseTest05\"; sid:1;)");
2564  if (sig == NULL) {
2565  result = 1;
2566  } else {
2567  printf("signature didn't fail to parse as we expected: ");
2568  }
2569 
2570 end:
2571  if (sig != NULL) SigFree(sig);
2572  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2573  return result;
2574 }
2575 
2576 /** \test Parsing bug debugging at 2010-03-18 */
2577 static int SigParseTest06 (void)
2578 {
2579  int result = 0;
2580  Signature *sig = NULL;
2581 
2583  if (de_ctx == NULL)
2584  goto end;
2585 
2586  sig = SigInit(de_ctx, "alert tcp any any -> any any (flow:to_server; content:\"GET\"; nocase; http_method; uricontent:\"/uri/\"; nocase; content:\"Host|3A| abc\"; nocase; sid:1; rev:1;)");
2587  if (sig != NULL) {
2588  result = 1;
2589  } else {
2590  printf("signature failed to parse: ");
2591  }
2592 
2593 end:
2594  if (sig != NULL)
2595  SigFree(sig);
2596  if (de_ctx != NULL)
2598  return result;
2599 }
2600 
2601 /**
2602  * \test Parsing duplicate sigs.
2603  */
2604 static int SigParseTest07(void)
2605 {
2606  int result = 0;
2607 
2609  if (de_ctx == NULL)
2610  goto end;
2611 
2612  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2613  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2614 
2615  result = (de_ctx->sig_list != NULL && de_ctx->sig_list->next == NULL);
2616 
2617 end:
2618  if (de_ctx != NULL)
2620  return result;
2621 }
2622 
2623 /**
2624  * \test Parsing duplicate sigs.
2625  */
2626 static int SigParseTest08(void)
2627 {
2628  int result = 0;
2629 
2631  if (de_ctx == NULL)
2632  goto end;
2633 
2634  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2635  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:2;)");
2636 
2637  result = (de_ctx->sig_list != NULL && de_ctx->sig_list->next == NULL &&
2638  de_ctx->sig_list->rev == 2);
2639 
2640 end:
2641  if (de_ctx != NULL)
2643  return result;
2644 }
2645 
2646 /**
2647  * \test Parsing duplicate sigs.
2648  */
2649 static int SigParseTest09(void)
2650 {
2651  int result = 1;
2652 
2654  if (de_ctx == NULL)
2655  goto end;
2656 
2657  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2658  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:2;)");
2659  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:6;)");
2660  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:4;)");
2661  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:2;)");
2662  result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
2663  de_ctx->sig_list->rev == 2);
2664  if (result == 0)
2665  goto end;
2666  result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
2667  de_ctx->sig_list->next->rev == 6);
2668  if (result == 0)
2669  goto end;
2670 
2671  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:1;)");
2672  result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
2673  de_ctx->sig_list->rev == 2);
2674  if (result == 0)
2675  goto end;
2676  result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
2677  de_ctx->sig_list->next->rev == 6);
2678  if (result == 0)
2679  goto end;
2680 
2681  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:4;)");
2682  result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
2683  de_ctx->sig_list->rev == 4);
2684  if (result == 0)
2685  goto end;
2686  result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
2687  de_ctx->sig_list->next->rev == 6);
2688  if (result == 0)
2689  goto end;
2690 
2691 end:
2692  if (de_ctx != NULL)
2694  return result;
2695 }
2696 
2697 /**
2698  * \test Parsing duplicate sigs.
2699  */
2700 static int SigParseTest10(void)
2701 {
2702  int result = 1;
2703 
2705  if (de_ctx == NULL)
2706  goto end;
2707 
2708  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2709  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:1;)");
2710  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:3; rev:1;)");
2711  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:4; rev:1;)");
2712  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:5; rev:1;)");
2713  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:3; rev:2;)");
2714  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:2;)");
2715 
2716  result &= ((de_ctx->sig_list->id == 2) &&
2717  (de_ctx->sig_list->next->id == 3) &&
2718  (de_ctx->sig_list->next->next->id == 5) &&
2719  (de_ctx->sig_list->next->next->next->id == 4) &&
2720  (de_ctx->sig_list->next->next->next->next->id == 1));
2721 
2722 end:
2723  if (de_ctx != NULL)
2725  return result;
2726 }
2727 
2728 /**
2729  * \test Parsing sig with trailing space(s) as reported by
2730  * Morgan Cox on oisf-users.
2731  */
2732 static int SigParseTest11(void)
2733 {
2734  int result = 0;
2735 
2737  if (de_ctx == NULL)
2738  goto end;
2739 
2740  Signature *s = NULL;
2741 
2742  s = DetectEngineAppendSig(de_ctx, "drop tcp any any -> any 80 (msg:\"Snort_Inline is blocking the http link\";) ");
2743  if (s == NULL) {
2744  printf("sig 1 didn't parse: ");
2745  goto end;
2746  }
2747 
2748  s = DetectEngineAppendSig(de_ctx, "drop tcp any any -> any 80 (msg:\"Snort_Inline is blocking the http link\"; sid:1;) ");
2749  if (s == NULL) {
2750  printf("sig 2 didn't parse: ");
2751  goto end;
2752  }
2753 
2754  result = 1;
2755 end:
2756  if (de_ctx != NULL)
2758  return result;
2759 }
2760 
2761 /**
2762  * \test file_data with rawbytes
2763  */
2764 static int SigParseTest12(void)
2765 {
2766  int result = 0;
2767 
2769  if (de_ctx == NULL)
2770  goto end;
2771 
2772  Signature *s = NULL;
2773 
2774  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (file_data; content:\"abc\"; rawbytes; sid:1;)");
2775  if (s != NULL) {
2776  printf("sig 1 should have given an error: ");
2777  goto end;
2778  }
2779 
2780  result = 1;
2781 end:
2782  if (de_ctx != NULL)
2784  return result;
2785 }
2786 
2787 /**
2788  * \test packet/stream sig
2789  */
2790 static int SigParseTest13(void)
2791 {
2792  int result = 0;
2793 
2795  if (de_ctx == NULL)
2796  goto end;
2797 
2798  Signature *s = NULL;
2799 
2800  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; sid:1;)");
2801  if (s == NULL) {
2802  printf("sig 1 invalidated: failure");
2803  goto end;
2804  }
2805 
2806  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
2807  printf("sig doesn't have stream flag set\n");
2808  goto end;
2809  }
2810 
2811  if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
2812  printf("sig has packet flag set\n");
2813  goto end;
2814  }
2815 
2816  result = 1;
2817 
2818 end:
2819  if (de_ctx != NULL)
2821  return result;
2822 }
2823 
2824 /**
2825  * \test packet/stream sig
2826  */
2827 static int SigParseTest14(void)
2828 {
2829  int result = 0;
2830 
2832  if (de_ctx == NULL)
2833  goto end;
2834 
2835  Signature *s = NULL;
2836 
2837  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; dsize:>0; sid:1;)");
2838  if (s == NULL) {
2839  printf("sig 1 invalidated: failure");
2840  goto end;
2841  }
2842 
2843  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
2844  printf("sig doesn't have packet flag set\n");
2845  goto end;
2846  }
2847 
2848  if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
2849  printf("sig has stream flag set\n");
2850  goto end;
2851  }
2852 
2853  result = 1;
2854 
2855 end:
2856  if (de_ctx != NULL)
2858  return result;
2859 }
2860 
2861 /**
2862  * \test packet/stream sig
2863  */
2864 static int SigParseTest15(void)
2865 {
2866  int result = 0;
2867 
2869  if (de_ctx == NULL)
2870  goto end;
2871 
2872  Signature *s = NULL;
2873 
2874  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:5; sid:1;)");
2875  if (s == NULL) {
2876  printf("sig 1 invalidated: failure");
2877  goto end;
2878  }
2879 
2880  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
2881  printf("sig doesn't have packet flag set\n");
2882  goto end;
2883  }
2884 
2885  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
2886  printf("sig doesn't have stream flag set\n");
2887  goto end;
2888  }
2889 
2890  result = 1;
2891 
2892 end:
2893  if (de_ctx != NULL)
2895  return result;
2896 }
2897 
2898 /**
2899  * \test packet/stream sig
2900  */
2901 static int SigParseTest16(void)
2902 {
2903  int result = 0;
2904 
2906  if (de_ctx == NULL)
2907  goto end;
2908 
2909  Signature *s = NULL;
2910 
2911  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; depth:5; sid:1;)");
2912  if (s == NULL) {
2913  printf("sig 1 invalidated: failure");
2914  goto end;
2915  }
2916 
2917  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
2918  printf("sig doesn't have packet flag set\n");
2919  goto end;
2920  }
2921 
2922  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
2923  printf("sig doesn't have stream flag set\n");
2924  goto end;
2925  }
2926 
2927  result = 1;
2928 
2929 end:
2930  if (de_ctx != NULL)
2932  return result;
2933 }
2934 
2935 /**
2936  * \test packet/stream sig
2937  */
2938 static int SigParseTest17(void)
2939 {
2940  int result = 0;
2941 
2943  if (de_ctx == NULL)
2944  goto end;
2945 
2946  Signature *s = NULL;
2947 
2948  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:1; depth:5; sid:1;)");
2949  if (s == NULL) {
2950  printf("sig 1 invalidated: failure");
2951  goto end;
2952  }
2953 
2954  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
2955  printf("sig doesn't have packet flag set\n");
2956  goto end;
2957  }
2958 
2959  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
2960  printf("sig doesn't have stream flag set\n");
2961  goto end;
2962  }
2963 
2964  result = 1;
2965 
2966 end:
2967  if (de_ctx != NULL)
2969  return result;
2970 }
2971 
2972 /** \test sid value too large. Bug #779 */
2973 static int SigParseTest18 (void)
2974 {
2975  int result = 0;
2976 
2978  if (de_ctx == NULL)
2979  goto end;
2980 
2981  if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:99999999999999999999;)") != NULL)
2982  goto end;
2983 
2984  result = 1;
2985 end:
2986  if (de_ctx != NULL)
2988  return result;
2989 }
2990 
2991 /** \test gid value too large. Related to bug #779 */
2992 static int SigParseTest19 (void)
2993 {
2994  int result = 0;
2995 
2997  if (de_ctx == NULL)
2998  goto end;
2999 
3000  if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1; gid:99999999999999999999;)") != NULL)
3001  goto end;
3002 
3003  result = 1;
3004 end:
3005  if (de_ctx != NULL)
3007  return result;
3008 }
3009 
3010 /** \test rev value too large. Related to bug #779 */
3011 static int SigParseTest20 (void)
3012 {
3013  int result = 0;
3014 
3016  if (de_ctx == NULL)
3017  goto end;
3018 
3019  if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1; rev:99999999999999999999;)") != NULL)
3020  goto end;
3021 
3022  result = 1;
3023 end:
3024  if (de_ctx != NULL)
3026  return result;
3027 }
3028 
3029 /** \test address parsing */
3030 static int SigParseTest21 (void)
3031 {
3032  int result = 0;
3033 
3035  if (de_ctx == NULL)
3036  goto end;
3037 
3038  if (DetectEngineAppendSig(de_ctx, "alert tcp [1.2.3.4, 1.2.3.5] any -> !1.2.3.4 any (sid:1;)") == NULL)
3039  goto end;
3040 
3041  result = 1;
3042 end:
3043  if (de_ctx != NULL)
3045  return result;
3046 }
3047 
3048 /** \test address parsing */
3049 static int SigParseTest22 (void)
3050 {
3051  int result = 0;
3052 
3054  if (de_ctx == NULL)
3055  goto end;
3056 
3057  if (DetectEngineAppendSig(de_ctx, "alert tcp [10.10.10.0/24, !10.10.10.247] any -> [10.10.10.0/24, !10.10.10.247] any (sid:1;)") == NULL)
3058  goto end;
3059 
3060  result = 1;
3061 end:
3062  if (de_ctx != NULL)
3064  return result;
3065 }
3066 
3067 /**
3068  * \test rule ending in carriage return
3069  */
3070 static int SigParseTest23(void)
3071 {
3074 
3075  Signature *s = NULL;
3076 
3077  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:1; depth:5; sid:1;)\r");
3078  FAIL_IF_NULL(s);
3079 
3081  PASS;
3082 }
3083 
3084 /** \test Direction operator validation (invalid) */
3085 static int SigParseBidirecTest06 (void)
3086 {
3087  int result = 1;
3088  Signature *sig = NULL;
3089 
3091  if (de_ctx == NULL)
3092  goto end;
3093 
3094  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any - 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3095  if (sig == NULL)
3096  result = 1;
3097 
3098 end:
3099  if (sig != NULL) SigFree(sig);
3100  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3101  return result;
3102 }
3103 
3104 /** \test Direction operator validation (invalid) */
3105 static int SigParseBidirecTest07 (void)
3106 {
3107  int result = 1;
3108  Signature *sig = NULL;
3109 
3111  if (de_ctx == NULL)
3112  goto end;
3113 
3114  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <- 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3115  if (sig == NULL)
3116  result = 1;
3117 
3118 end:
3119  if (sig != NULL) SigFree(sig);
3120  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3121  return result;
3122 }
3123 
3124 /** \test Direction operator validation (invalid) */
3125 static int SigParseBidirecTest08 (void)
3126 {
3127  int result = 1;
3128  Signature *sig = NULL;
3129 
3131  if (de_ctx == NULL)
3132  goto end;
3133 
3134  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any < 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3135  if (sig == NULL)
3136  result = 1;
3137 
3138 end:
3139  if (sig != NULL) SigFree(sig);
3140  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3141  return result;
3142 }
3143 
3144 /** \test Direction operator validation (invalid) */
3145 static int SigParseBidirecTest09 (void)
3146 {
3147  int result = 1;
3148  Signature *sig = NULL;
3149 
3151  if (de_ctx == NULL)
3152  goto end;
3153 
3154  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any > 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3155  if (sig == NULL)
3156  result = 1;
3157 
3158 end:
3159  if (sig != NULL) SigFree(sig);
3160  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3161  return result;
3162 }
3163 
3164 /** \test Direction operator validation (invalid) */
3165 static int SigParseBidirecTest10 (void)
3166 {
3167  int result = 1;
3168  Signature *sig = NULL;
3169 
3171  if (de_ctx == NULL)
3172  goto end;
3173 
3174  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -< 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3175  if (sig == NULL)
3176  result = 1;
3177 
3178 end:
3179  if (sig != NULL) SigFree(sig);
3180  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3181  return result;
3182 }
3183 
3184 /** \test Direction operator validation (invalid) */
3185 static int SigParseBidirecTest11 (void)
3186 {
3187  int result = 1;
3188  Signature *sig = NULL;
3189 
3191  if (de_ctx == NULL)
3192  goto end;
3193 
3194  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any >- 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3195  if (sig == NULL)
3196  result = 1;
3197 
3198 end:
3199  if (sig != NULL) SigFree(sig);
3200  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3201  return result;
3202 }
3203 
3204 /** \test Direction operator validation (invalid) */
3205 static int SigParseBidirecTest12 (void)
3206 {
3207  int result = 1;
3208  Signature *sig = NULL;
3209 
3211  if (de_ctx == NULL)
3212  goto end;
3213 
3214  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any >< 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3215  if (sig == NULL)
3216  result = 1;
3217 
3218 end:
3219  if (sig != NULL) SigFree(sig);
3220  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3221  return result;
3222 }
3223 
3224 /** \test Direction operator validation (valid) */
3225 static int SigParseBidirecTest13 (void)
3226 {
3227  int result = 1;
3228  Signature *sig = NULL;
3229 
3231  if (de_ctx == NULL)
3232  goto end;
3233 
3234  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <> 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3235  if (sig != NULL)
3236  result = 1;
3237 
3238 end:
3239  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3240  return result;
3241 }
3242 
3243 /** \test Direction operator validation (valid) */
3244 static int SigParseBidirecTest14 (void)
3245 {
3246  int result = 1;
3247  Signature *sig = NULL;
3248 
3250  if (de_ctx == NULL)
3251  goto end;
3252 
3253  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3254  if (sig != NULL)
3255  result = 1;
3256 
3257 end:
3258  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3259  return result;
3260 }
3261 
3262 /** \test Ensure that we don't set bidirectional in a
3263  * normal (one direction) Signature
3264  */
3265 static int SigTestBidirec01 (void)
3266 {
3267  Signature *sig = NULL;
3268  int result = 0;
3269 
3271  if (de_ctx == NULL)
3272  goto end;
3273 
3274  sig = DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 1024:65535 -> !1.2.3.4 any (msg:\"SigTestBidirec01\"; sid:1;)");
3275  if (sig == NULL)
3276  goto end;
3277  if (sig->next != NULL)
3278  goto end;
3280  goto end;
3281  if (de_ctx->signum != 1)
3282  goto end;
3283 
3284  result = 1;
3285 
3286 end:
3287  if (de_ctx != NULL) {
3291  }
3292  return result;
3293 }
3294 
3295 /** \test Ensure that we set a bidirectional Signature correctly */
3296 static int SigTestBidirec02 (void)
3297 {
3298  int result = 0;
3299  Signature *sig = NULL;
3300  Signature *copy = NULL;
3301 
3303  if (de_ctx == NULL)
3304  goto end;
3305 
3306  de_ctx->flags |= DE_QUIET;
3307 
3308  sig = DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 1024:65535 <> !1.2.3.4 any (msg:\"SigTestBidirec02\"; sid:1;)");
3309  if (sig == NULL)
3310  goto end;
3311  if (de_ctx->sig_list != sig)
3312  goto end;
3314  goto end;
3315  if (sig->next == NULL)
3316  goto end;
3317  if (de_ctx->signum != 2)
3318  goto end;
3319  copy = sig->next;
3320  if (copy->next != NULL)
3321  goto end;
3322  if (!(copy->init_data->init_flags & SIG_FLAG_INIT_BIDIREC))
3323  goto end;
3324 
3325  result = 1;
3326 
3327 end:
3328  if (de_ctx != NULL) {
3332  }
3333 
3334  return result;
3335 }
3336 
3337 /** \test Ensure that we set a bidirectional Signature correctly
3338 * and we install it with the rest of the signatures, checking
3339 * also that it match with the correct addr directions
3340 */
3341 static int SigTestBidirec03 (void)
3342 {
3343  int result = 0;
3344  Signature *sig = NULL;
3345  Packet *p = NULL;
3346 
3348  if (de_ctx == NULL)
3349  goto end;
3350 
3351  de_ctx->flags |= DE_QUIET;
3352 
3353  const char *sigs[3];
3354  sigs[0] = "alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 1\"; sid:1;)";
3355  sigs[1] = "alert tcp any any <> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)";
3356  sigs[2] = "alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 3\"; sid:3;)";
3357  UTHAppendSigs(de_ctx, sigs, 3);
3358 
3359  /* Checking that bidirectional rules are set correctly */
3360  sig = de_ctx->sig_list;
3361  if (sig == NULL)
3362  goto end;
3363  if (sig->next == NULL)
3364  goto end;
3365  if (sig->next->next == NULL)
3366  goto end;
3367  if (sig->next->next->next == NULL)
3368  goto end;
3369  if (sig->next->next->next->next != NULL)
3370  goto end;
3371  if (de_ctx->signum != 4)
3372  goto end;
3373 
3374  uint8_t rawpkt1_ether[] = {
3375  0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
3376  0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
3377  0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
3378  0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
3379  0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
3380  0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
3381  0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
3382  0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
3383  0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
3384  0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
3385  0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
3386  0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
3387  0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
3388  0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
3389  0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
3390  0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
3391  0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
3392  0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
3393  0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
3394  0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
3395  0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
3396  0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
3397  0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
3398  0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
3399  0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
3400  0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
3401  0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
3402  0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
3403  0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
3404  0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
3405  0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
3406  0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
3407  0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
3408  0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
3409  0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3410  0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3411  0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
3412  0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
3413  0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
3414  0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
3415  0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
3416  0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
3417  0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
3418  0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3419  0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
3420  0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
3421  0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
3422  0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
3423  0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3424  0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
3425  0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
3426  0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
3427  0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
3428  0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
3429  0x76,0x65,0x0d,0x0a,0x0d,0x0a }; /* end rawpkt1_ether */
3430 
3432  p = UTHBuildPacketFromEth(rawpkt1_ether, sizeof(rawpkt1_ether));
3433  if (p == NULL) {
3434  SCLogDebug("Error building packet");
3435  goto end;
3436  }
3437  UTHMatchPackets(de_ctx, &p, 1);
3438 
3439  uint32_t sids[3] = {1, 2, 3};
3440  uint32_t results[3] = {1, 1, 1};
3441  result = UTHCheckPacketMatchResults(p, sids, results, 1);
3442 
3443 end:
3444  if (p != NULL) {
3445  PACKET_RECYCLE(p);
3446  SCFree(p);
3447  }
3448  if (de_ctx != NULL) {
3452  }
3453  FlowShutdown();
3454 
3455  return result;
3456 }
3457 
3458 /** \test Ensure that we set a bidirectional Signature correctly
3459 * and we install it with the rest of the signatures, checking
3460 * also that it match with the correct addr directions
3461 */
3462 static int SigTestBidirec04 (void)
3463 {
3464  int result = 0;
3465  Signature *sig = NULL;
3466  Packet *p = NULL;
3467 
3469  if (de_ctx == NULL)
3470  goto end;
3471 
3472  de_ctx->flags |= DE_QUIET;
3473 
3474  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> any any (msg:\"SigTestBidirec03 sid 1\"; sid:1;)");
3475  if (sig == NULL)
3476  goto end;
3477  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <> any any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)");
3478  if (sig == NULL)
3479  goto end;
3480  if ( !(sig->init_data->init_flags & SIG_FLAG_INIT_BIDIREC))
3481  goto end;
3482  if (sig->next == NULL)
3483  goto end;
3484  if (sig->next->next == NULL)
3485  goto end;
3486  if (sig->next->next->next != NULL)
3487  goto end;
3488  if (de_ctx->signum != 3)
3489  goto end;
3490 
3491  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> any any (msg:\"SigTestBidirec03 sid 3\"; sid:3;)");
3492  if (sig == NULL)
3493  goto end;
3494  if (sig->next == NULL)
3495  goto end;
3496  if (sig->next->next == NULL)
3497  goto end;
3498  if (sig->next->next->next == NULL)
3499  goto end;
3500  if (sig->next->next->next->next != NULL)
3501  goto end;
3502  if (de_ctx->signum != 4)
3503  goto end;
3504 
3505  uint8_t rawpkt1_ether[] = {
3506  0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
3507  0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
3508  0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
3509  0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
3510  0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
3511  0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
3512  0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
3513  0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
3514  0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
3515  0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
3516  0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
3517  0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
3518  0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
3519  0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
3520  0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
3521  0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
3522  0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
3523  0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
3524  0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
3525  0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
3526  0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
3527  0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
3528  0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
3529  0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
3530  0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
3531  0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
3532  0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
3533  0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
3534  0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
3535  0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
3536  0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
3537  0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
3538  0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
3539  0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
3540  0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3541  0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3542  0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
3543  0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
3544  0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
3545  0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
3546  0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
3547  0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
3548  0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
3549  0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3550  0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
3551  0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
3552  0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
3553  0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
3554  0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3555  0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
3556  0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
3557  0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
3558  0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
3559  0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
3560  0x76,0x65,0x0d,0x0a,0x0d,0x0a }; /* end rawpkt1_ether */
3561 
3562  p = SCMalloc(SIZE_OF_PACKET);
3563  if (unlikely(p == NULL))
3564  return 0;
3566  ThreadVars th_v;
3567  DetectEngineThreadCtx *det_ctx;
3568 
3569  memset(&th_v, 0, sizeof(th_v));
3570  memset(p, 0, SIZE_OF_PACKET);
3571 
3573  DecodeEthernet(&th_v, &dtv, p, rawpkt1_ether, sizeof(rawpkt1_ether));
3574  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
3575 
3576  /* At this point we have a list of 4 signatures. The last one
3577  is a copy of the second one. If we receive a packet
3578  with source 192.168.1.1 80, all the sids should match */
3579 
3581  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3582 
3583  /* only sid 2 should match with a packet going to 192.168.1.1 port 80 */
3584  if (PacketAlertCheck(p, 1) <= 0 && PacketAlertCheck(p, 3) <= 0 &&
3585  PacketAlertCheck(p, 2) == 1) {
3586  result = 1;
3587  }
3588 
3589  if (p != NULL) {
3590  PACKET_RECYCLE(p);
3591  }
3592  FlowShutdown();
3593  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
3594 
3595 end:
3596  if (de_ctx != NULL) {
3600  }
3601 
3602  if (p != NULL)
3603  SCFree(p);
3604  return result;
3605 }
3606 
3607 /**
3608  * \test check that we don't allow invalid negation options
3609  */
3610 static int SigParseTestNegation01 (void)
3611 {
3612  int result = 0;
3614  Signature *s=NULL;
3615 
3617  if (de_ctx == NULL)
3618  goto end;
3619  de_ctx->flags |= DE_QUIET;
3620 
3621  s = SigInit(de_ctx,"alert tcp !any any -> any any (msg:\"SigTest41-01 src address is !any \"; classtype:misc-activity; sid:410001; rev:1;)");
3622  if (s != NULL) {
3623  SigFree(s);
3624  goto end;
3625  }
3626 
3627  result = 1;
3628 end:
3629  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3630  return result;
3631 }
3632 
3633 /**
3634  * \test check that we don't allow invalid negation options
3635  */
3636 static int SigParseTestNegation02 (void)
3637 {
3638  int result = 0;
3640  Signature *s=NULL;
3641 
3643  if (de_ctx == NULL)
3644  goto end;
3645  de_ctx->flags |= DE_QUIET;
3646 
3647  s = SigInit(de_ctx,"alert tcp any !any -> any any (msg:\"SigTest41-02 src ip is !any \"; classtype:misc-activity; sid:410002; rev:1;)");
3648  if (s != NULL) {
3649  SigFree(s);
3650  goto end;
3651  }
3652 
3653  result = 1;
3654 end:
3655  if (de_ctx != NULL)
3657  return result;
3658 }
3659 /**
3660  * \test check that we don't allow invalid negation options
3661  */
3662 static int SigParseTestNegation03 (void)
3663 {
3664  int result = 0;
3666  Signature *s=NULL;
3667 
3669  if (de_ctx == NULL)
3670  goto end;
3671  de_ctx->flags |= DE_QUIET;
3672 
3673  s = SigInit(de_ctx,"alert tcp any any -> any [80:!80] (msg:\"SigTest41-03 dst port [80:!80] \"; classtype:misc-activity; sid:410003; rev:1;)");
3674  if (s != NULL) {
3675  SigFree(s);
3676  goto end;
3677  }
3678 
3679  result = 1;
3680 end:
3681  if (de_ctx != NULL)
3683  return result;
3684 }
3685 /**
3686  * \test check that we don't allow invalid negation options
3687  */
3688 static int SigParseTestNegation04 (void)
3689 {
3690  int result = 0;
3692  Signature *s=NULL;
3693 
3695  if (de_ctx == NULL)
3696  goto end;
3697  de_ctx->flags |= DE_QUIET;
3698 
3699  s = SigInit(de_ctx,"alert tcp any any -> any [80,!80] (msg:\"SigTest41-03 dst port [80:!80] \"; classtype:misc-activity; sid:410003; rev:1;)");
3700  if (s != NULL) {
3701  SigFree(s);
3702  goto end;
3703  }
3704 
3705  result = 1;
3706 end:
3707  if (de_ctx != NULL)
3709  return result;
3710 }
3711 /**
3712  * \test check that we don't allow invalid negation options
3713  */
3714 static int SigParseTestNegation05 (void)
3715 {
3716  int result = 0;
3718  Signature *s=NULL;
3719 
3721  if (de_ctx == NULL)
3722  goto end;
3723  de_ctx->flags |= DE_QUIET;
3724 
3725  s = SigInit(de_ctx,"alert tcp any any -> [192.168.0.2,!192.168.0.2] any (msg:\"SigTest41-04 dst ip [192.168.0.2,!192.168.0.2] \"; classtype:misc-activity; sid:410004; rev:1;)");
3726  if (s != NULL) {
3727  SigFree(s);
3728  goto end;
3729  }
3730 
3731  result = 1;
3732 end:
3733  if (de_ctx != NULL)
3735  return result;
3736 }
3737 /**
3738  * \test check that we don't allow invalid negation options
3739  */
3740 static int SigParseTestNegation06 (void)
3741 {
3742  int result = 0;
3744  Signature *s=NULL;
3745 
3747  if (de_ctx == NULL)
3748  goto end;
3749  de_ctx->flags |= DE_QUIET;
3750 
3751  s = SigInit(de_ctx,"alert tcp any any -> any [100:1000,!1:20000] (msg:\"SigTest41-05 dst port [100:1000,!1:20000] \"; classtype:misc-activity; sid:410005; rev:1;)");
3752  if (s != NULL) {
3753  SigFree(s);
3754  goto end;
3755  }
3756 
3757  result = 1;
3758 end:
3759  if (de_ctx != NULL)
3761  return result;
3762 }
3763 
3764 /**
3765  * \test check that we don't allow invalid negation options
3766  */
3767 static int SigParseTestNegation07 (void)
3768 {
3769  int result = 0;
3771  Signature *s=NULL;
3772 
3774  if (de_ctx == NULL)
3775  goto end;
3776  de_ctx->flags |= DE_QUIET;
3777 
3778  s = SigInit(de_ctx,"alert tcp any any -> [192.168.0.2,!192.168.0.0/24] any (msg:\"SigTest41-06 dst ip [192.168.0.2,!192.168.0.0/24] \"; classtype:misc-activity; sid:410006; rev:1;)");
3779  if (s != NULL) {
3780  SigFree(s);
3781  goto end;
3782  }
3783 
3784  result = 1;
3785 end:
3786  if (de_ctx != NULL)
3788  return result;
3789 }
3790 
3791 /**
3792  * \test check valid negation bug 1079
3793  */
3794 static int SigParseTestNegation08 (void)
3795 {
3796  int result = 0;
3798  Signature *s=NULL;
3799 
3801  if (de_ctx == NULL)
3802  goto end;
3803  de_ctx->flags |= DE_QUIET;
3804 
3805  s = SigInit(de_ctx,"alert tcp any any -> [192.168.0.0/16,!192.168.0.0/24] any (sid:410006; rev:1;)");
3806  if (s == NULL) {
3807  goto end;
3808  }
3809 
3810  result = 1;
3811 end:
3812  if (de_ctx != NULL)
3814  return result;
3815 }
3816 
3817 /**
3818  * \test mpm
3819  */
3820 static int SigParseTestMpm01 (void)
3821 {
3822  int result = 0;
3823  Signature *sig = NULL;
3824 
3826  if (de_ctx == NULL)
3827  goto end;
3828 
3829  sig = SigInit(de_ctx, "alert tcp any any -> any any (msg:\"mpm test\"; content:\"abcd\"; sid:1;)");
3830  if (sig == NULL) {
3831  printf("sig failed to init: ");
3832  goto end;
3833  }
3834 
3835  if (sig->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
3836  printf("sig doesn't have content list: ");
3837  goto end;
3838  }
3839 
3840  result = 1;
3841 end:
3842  if (sig != NULL)
3843  SigFree(sig);
3845  return result;
3846 }
3847 
3848 /**
3849  * \test mpm
3850  */
3851 static int SigParseTestMpm02 (void)
3852 {
3853  int result = 0;
3854  Signature *sig = NULL;
3855 
3857  if (de_ctx == NULL)
3858  goto end;
3859 
3860  sig = SigInit(de_ctx, "alert tcp any any -> any any (msg:\"mpm test\"; content:\"abcd\"; content:\"abcdef\"; sid:1;)");
3861  if (sig == NULL) {
3862  printf("sig failed to init: ");
3863  goto end;
3864  }
3865 
3866  if (sig->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
3867  printf("sig doesn't have content list: ");
3868  goto end;
3869  }
3870 
3871  result = 1;
3872 end:
3873  if (sig != NULL)
3874  SigFree(sig);
3876  return result;
3877 }
3878 
3879 /**
3880  * \test test tls (app layer) rule
3881  */
3882 static int SigParseTestAppLayerTLS01(void)
3883 {
3884  int result = 0;
3886  Signature *s=NULL;
3887 
3889  if (de_ctx == NULL)
3890  goto end;
3891  de_ctx->flags |= DE_QUIET;
3892 
3893  s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS01 \"; sid:410006; rev:1;)");
3894  if (s == NULL) {
3895  printf("parsing sig failed: ");
3896  goto end;
3897  }
3898 
3899  if (s->alproto == 0) {
3900  printf("alproto not set: ");
3901  goto end;
3902  }
3903 
3904  result = 1;
3905 end:
3906  if (s != NULL)
3907  SigFree(s);
3908  if (de_ctx != NULL)
3910 
3911  return result;
3912 }
3913 
3914 /**
3915  * \test test tls (app layer) rule
3916  */
3917 static int SigParseTestAppLayerTLS02(void)
3918 {
3919  int result = 0;
3921  Signature *s=NULL;
3922 
3924  if (de_ctx == NULL)
3925  goto end;
3926  de_ctx->flags |= DE_QUIET;
3927 
3928  s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS02 \"; tls.version:1.0; sid:410006; rev:1;)");
3929  if (s == NULL) {
3930  printf("parsing sig failed: ");
3931  goto end;
3932  }
3933 
3934  if (s->alproto == 0) {
3935  printf("alproto not set: ");
3936  goto end;
3937  }
3938 
3939  result = 1;
3940 end:
3941  if (s != NULL)
3942  SigFree(s);
3943  if (de_ctx != NULL)
3945  return result;
3946 }
3947 
3948 /**
3949  * \test test tls (app layer) rule
3950  */
3951 static int SigParseTestAppLayerTLS03(void)
3952 {
3953  int result = 0;
3955  Signature *s=NULL;
3956 
3958  if (de_ctx == NULL)
3959  goto end;
3960  de_ctx->flags |= DE_QUIET;
3961 
3962  s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS03 \"; tls.version:2.5; sid:410006; rev:1;)");
3963  if (s != NULL) {
3964  SigFree(s);
3965  goto end;
3966  }
3967 
3968  result = 1;
3969 end:
3970  if (de_ctx != NULL)
3972  return result;
3973 }
3974 
3975 static int SigParseTestUnblanacedQuotes01(void)
3976 {
3978  Signature *s;
3979 
3982  de_ctx->flags |= DE_QUIET;
3983 
3984  s = SigInit(de_ctx, "alert http any any -> any any (msg:\"SigParseTestUnblanacedQuotes01\"; pcre:\"/\\/[a-z]+\\.php\\?[a-z]+?=\\d{7}&[a-z]+?=\\d{7,8}$/U\" flowbits:set,et.exploitkitlanding; classtype:trojan-activity; sid:2017078; rev:5;)");
3985  FAIL_IF_NOT_NULL(s);
3986 
3987  PASS;
3988 }
3989 
3990 static int SigParseTestContentGtDsize01(void)
3991 {
3994  de_ctx->flags |= DE_QUIET;
3995 
3996  Signature *s = SigInit(de_ctx,
3997  "alert http any any -> any any ("
3998  "dsize:21; content:\"0123456789001234567890|00 00|\"; "
3999  "sid:1; rev:1;)");
4000  FAIL_IF_NOT_NULL(s);
4001 
4002  PASS;
4003 }
4004 
4005 static int SigParseTestContentGtDsize02(void)
4006 {
4009  de_ctx->flags |= DE_QUIET;
4010 
4011  Signature *s = SigInit(de_ctx,
4012  "alert http any any -> any any ("
4013  "dsize:21; content:\"0123456789|00 00|\"; offset:10; "
4014  "sid:1; rev:1;)");
4015  FAIL_IF_NOT_NULL(s);
4016 
4017  PASS;
4018 }
4019 
4020 static int SigParseBidirWithSameSrcAndDest01(void)
4021 {
4024  de_ctx->flags |= DE_QUIET;
4025 
4026  Signature *s = SigInit(de_ctx,
4027  "alert tcp any any <> any any (sid:1; rev:1;)");
4028  FAIL_IF_NULL(s);
4029  FAIL_IF_NOT_NULL(s->next);
4031 
4032  SigFree(s);
4033 
4034  s = SigInit(de_ctx,
4035  "alert tcp any [80, 81] <> any [81, 80] (sid:1; rev:1;)");
4036  FAIL_IF_NULL(s);
4037  FAIL_IF_NOT_NULL(s->next);
4039 
4040  SigFree(s);
4041 
4042  s = SigInit(de_ctx,
4043  "alert tcp [1.2.3.4, 5.6.7.8] [80, 81] <> [5.6.7.8, 1.2.3.4] [81, 80] (sid:1; rev:1;)");
4044  FAIL_IF_NULL(s);
4045  FAIL_IF_NOT_NULL(s->next);
4047 
4048  SigFree(s);
4049 
4050  PASS;
4051 }
4052 
4053 static int SigParseBidirWithSameSrcAndDest02(void)
4054 {
4057  de_ctx->flags |= DE_QUIET;
4058 
4059  // Source is a subset of destination
4060  Signature *s = SigInit(de_ctx,
4061  "alert tcp 1.2.3.4 any <> [1.2.3.4, 5.6.7.8, ::1] any (sid:1; rev:1;)");
4062  FAIL_IF_NULL(s);
4063  FAIL_IF_NULL(s->next);
4065 
4066  SigFree(s);
4067 
4068  // Source is a subset of destinationn
4069  s = SigInit(de_ctx,
4070  "alert tcp [1.2.3.4, ::1] [80, 81, 82] <> [1.2.3.4, ::1] [80, 81] (sid:1; rev:1;)");
4071  FAIL_IF_NULL(s);
4072  FAIL_IF_NULL(s->next);
4074 
4075  SigFree(s);
4076 
4077  // Source intersects with destination
4078  s = SigInit(de_ctx,
4079  "alert tcp [1.2.3.4, ::1, ABCD:AAAA::1] [80] <> [1.2.3.4, ::1] [80, 81] (sid:1; rev:1;)");
4080  FAIL_IF_NULL(s);
4081  FAIL_IF_NULL(s->next);
4083 
4084  SigFree(s);
4085 
4086  PASS;
4087 }
4088 
4089 #endif /* UNITTESTS */
4090 
4091 #ifdef UNITTESTS
4092 void DetectParseRegisterTests (void);
4093 #include "tests/detect-parse.c"
4094 #endif
4095 
4097 {
4098 #ifdef UNITTESTS
4100 
4101  UtRegisterTest("SigParseTest01", SigParseTest01);
4102  UtRegisterTest("SigParseTest02", SigParseTest02);
4103  UtRegisterTest("SigParseTest03", SigParseTest03);
4104  UtRegisterTest("SigParseTest04", SigParseTest04);
4105  UtRegisterTest("SigParseTest05", SigParseTest05);
4106  UtRegisterTest("SigParseTest06", SigParseTest06);
4107  UtRegisterTest("SigParseTest07", SigParseTest07);
4108  UtRegisterTest("SigParseTest08", SigParseTest08);
4109  UtRegisterTest("SigParseTest09", SigParseTest09);
4110  UtRegisterTest("SigParseTest10", SigParseTest10);
4111  UtRegisterTest("SigParseTest11", SigParseTest11);
4112  UtRegisterTest("SigParseTest12", SigParseTest12);
4113  UtRegisterTest("SigParseTest13", SigParseTest13);
4114  UtRegisterTest("SigParseTest14", SigParseTest14);
4115  UtRegisterTest("SigParseTest15", SigParseTest15);
4116  UtRegisterTest("SigParseTest16", SigParseTest16);
4117  UtRegisterTest("SigParseTest17", SigParseTest17);
4118  UtRegisterTest("SigParseTest18", SigParseTest18);
4119  UtRegisterTest("SigParseTest19", SigParseTest19);
4120  UtRegisterTest("SigParseTest20", SigParseTest20);
4121  UtRegisterTest("SigParseTest21 -- address with space", SigParseTest21);
4122  UtRegisterTest("SigParseTest22 -- address with space", SigParseTest22);
4123  UtRegisterTest("SigParseTest23 -- carriage return", SigParseTest23);
4124 
4125  UtRegisterTest("SigParseBidirecTest06", SigParseBidirecTest06);
4126  UtRegisterTest("SigParseBidirecTest07", SigParseBidirecTest07);
4127  UtRegisterTest("SigParseBidirecTest08", SigParseBidirecTest08);
4128  UtRegisterTest("SigParseBidirecTest09", SigParseBidirecTest09);
4129  UtRegisterTest("SigParseBidirecTest10", SigParseBidirecTest10);
4130  UtRegisterTest("SigParseBidirecTest11", SigParseBidirecTest11);
4131  UtRegisterTest("SigParseBidirecTest12", SigParseBidirecTest12);
4132  UtRegisterTest("SigParseBidirecTest13", SigParseBidirecTest13);
4133  UtRegisterTest("SigParseBidirecTest14", SigParseBidirecTest14);
4134  UtRegisterTest("SigTestBidirec01", SigTestBidirec01);
4135  UtRegisterTest("SigTestBidirec02", SigTestBidirec02);
4136  UtRegisterTest("SigTestBidirec03", SigTestBidirec03);
4137  UtRegisterTest("SigTestBidirec04", SigTestBidirec04);
4138  UtRegisterTest("SigParseTestNegation01", SigParseTestNegation01);
4139  UtRegisterTest("SigParseTestNegation02", SigParseTestNegation02);
4140  UtRegisterTest("SigParseTestNegation03", SigParseTestNegation03);
4141  UtRegisterTest("SigParseTestNegation04", SigParseTestNegation04);
4142  UtRegisterTest("SigParseTestNegation05", SigParseTestNegation05);
4143  UtRegisterTest("SigParseTestNegation06", SigParseTestNegation06);
4144  UtRegisterTest("SigParseTestNegation07", SigParseTestNegation07);
4145  UtRegisterTest("SigParseTestNegation08", SigParseTestNegation08);
4146  UtRegisterTest("SigParseTestMpm01", SigParseTestMpm01);
4147  UtRegisterTest("SigParseTestMpm02", SigParseTestMpm02);
4148  UtRegisterTest("SigParseTestAppLayerTLS01", SigParseTestAppLayerTLS01);
4149  UtRegisterTest("SigParseTestAppLayerTLS02", SigParseTestAppLayerTLS02);
4150  UtRegisterTest("SigParseTestAppLayerTLS03", SigParseTestAppLayerTLS03);
4151  UtRegisterTest("SigParseTestUnblanacedQuotes01",
4152  SigParseTestUnblanacedQuotes01);
4153 
4154  UtRegisterTest("SigParseTestContentGtDsize01",
4155  SigParseTestContentGtDsize01);
4156  UtRegisterTest("SigParseTestContentGtDsize02",
4157  SigParseTestContentGtDsize02);
4158 
4159  UtRegisterTest("SigParseBidirWithSameSrcAndDest01",
4160  SigParseBidirWithSameSrcAndDest01);
4161  UtRegisterTest("SigParseBidirWithSameSrcAndDest02",
4162  SigParseBidirWithSameSrcAndDest02);
4163 #endif /* UNITTESTS */
4164 }
DetectAddressListsAreEqual
bool DetectAddressListsAreEqual(DetectAddress *list1, DetectAddress *list2)
Checks if two address group lists are equal.
Definition: detect-engine-address.c:366
DetectParseRegex_::next
struct DetectParseRegex_ * next
Definition: detect-parse.h:48
SignatureParser_
Definition: detect-parse.c:103
DetectAddress_::ip
Address ip
Definition: detect.h:141
host.h
SC_ERR_INVALID_DIRECTION
@ SC_ERR_INVALID_DIRECTION
Definition: util-error.h:221
DetectPortCmp
int DetectPortCmp(DetectPort *a, DetectPort *b)
Function that compare port groups.
Definition: detect-engine-port.c:550
DetectEngineAppInspectionEngine_
Definition: detect.h:395
DETECT_CONTENT_RELATIVE_NEXT
#define DETECT_CONTENT_RELATIVE_NEXT
Definition: detect-content.h:64
DetectSignatureSetAppProto
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
Definition: detect-parse.c:1459
pcre_free_study
#define pcre_free_study
Definition: suricata-common.h:356
SigMatch_::prev
struct SigMatch_ * prev
Definition: detect.h:323
detect-content.h
len
uint8_t len
Definition: app-layer-dnp3.h:4
ts
uint64_t ts
Definition: source-erf-file.c:2
DetectAppLayerEventPrepare
int DetectAppLayerEventPrepare(Signature *s)
Definition: detect-app-layer-event.c:348
SC_ERR_PCRE_COMPILE
@ SC_ERR_PCRE_COMPILE
Definition: util-error.h:35
DetectMetadataFree
void DetectMetadataFree(DetectMetadata *mdata)
Free a Metadata object.
Definition: detect-metadata.c:54
AppLayerHtpNeedFileInspection
void AppLayerHtpNeedFileInspection(void)
Sets a flag that informs the HTP app layer that some module in the engine needs the http request file...
Definition: app-layer-htp.c:505
detect-engine.h
SigMatchRemoveSMFromList
void SigMatchRemoveSMFromList(Signature *s, SigMatch *sm, int sm_list)
Definition: detect-parse.c:387
detect-app-layer-protocol.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:90
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
DetectParseRegisterTests
void DetectParseRegisterTests(void)
this function registers unit tests for DetectParse
Definition: detect-parse.c:45
SCStrdup
#define SCStrdup(a)
Definition: util-mem.h:268
DetectParseDupSigHashInit
int DetectParseDupSigHashInit(DetectEngineCtx *de_ctx)
Initializes the hash table that is used to cull duplicate sigs.
Definition: detect-parse.c:2130
SignatureInitData_::list_set
bool list_set
Definition: detect.h:499
Signature_::addr_src_match6
DetectMatchAddressIPv6 * addr_src_match6
Definition: detect.h:553
Signature_::sig_str
char * sig_str
Definition: detect.h:589
offset
uint64_t offset
Definition: util-streaming-buffer.h:2
SIG_DIREC_DST
@ SIG_DIREC_DST
Definition: detect-parse.h:39
SigFree
void SigFree(Signature *s)
Definition: detect-parse.c:1377
SC_ERR_DUPLICATE_SIG
@ SC_ERR_DUPLICATE_SIG
Definition: util-error.h:208
SigDuplWrapper_
We use this as data to the hash table DetectEngineCtx->dup_sig_hash_table.
Definition: detect-parse.c:84
DetectEngineAppInspectionEngine_::next
struct DetectEngineAppInspectionEngine_ * next
Definition: detect.h:421
DetectIPProtoRemoveAllSMs
void DetectIPProtoRemoveAllSMs(Signature *s)
Definition: detect-ipproto.c:426
SignatureParser_::sp
char sp[DETECT_MAX_RULE_SIZE]
Definition: detect-parse.c:109
DetectPortListsAreEqual
bool DetectPortListsAreEqual(DetectPort *list1, DetectPort *list2)
Checks if two port group lists are equal.
Definition: detect-engine-port.c:694
SIGMATCH_STRICT_PARSING
#define SIGMATCH_STRICT_PARSING
Definition: detect.h:1398
SignatureParser_::action
char action[DETECT_MAX_RULE_SIZE]
Definition: detect-parse.c:104
SigTableElmt_::name
const char * name
Definition: detect.h:1201
Signature_::num
SigIntId num
Definition: detect.h:532
DetectListToHumanString
const char * DetectListToHumanString(int list)
Definition: detect-parse.c:114
SIG_FLAG_INIT_FLOW
#define SIG_FLAG_INIT_FLOW
Definition: detect.h:258
SC_ERR_LIBNET_REQUIRED_FOR_ACTION
@ SC_ERR_LIBNET_REQUIRED_FOR_ACTION
Definition: util-error.h:173
SCFree
#define SCFree(a)
Definition: util-mem.h:322
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
ACTION_PASS
#define ACTION_PASS
Definition: action-globals.h:34
SigTableApplyStrictCommandlineOption
void SigTableApplyStrictCommandlineOption(const char *str)
Definition: detect-parse.c:306
ACTION_REJECT
#define ACTION_REJECT
Definition: action-globals.h:31
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
SigDuplWrapper
struct SigDuplWrapper_ SigDuplWrapper
We use this as data to the hash table DetectEngineCtx->dup_sig_hash_table.
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:59
DetectAddress_
address structure for use in the detection engine.
Definition: detect.h:139
SignatureInitData_::src_contains_negation
bool src_contains_negation
Definition: detect.h:482
DetectEngineCtx_::sigerror_silent
bool sigerror_silent
Definition: detect.h:867
Signature_::alproto
AppProto alproto
Definition: detect.h:526
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:335
SIGMATCH_QUOTES_OPTIONAL
#define SIGMATCH_QUOTES_OPTIONAL
Definition: detect.h:1382
IPOnlySigParseAddress
int IPOnlySigParseAddress(const DetectEngineCtx *de_ctx, Signature *s, const char *addrstr, char flag)
Parses an address group sent as a character string and updates the IPOnlyCIDRItem lists src and dst o...
Definition: detect-engine-iponly.c:793
SC_ERR_INVALID_RULE_ARGUMENT
@ SC_ERR_INVALID_RULE_ARGUMENT
Definition: util-error.h:302
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:2
SCClassConfLoadClassficationConfigFile
void SCClassConfLoadClassficationConfigFile(DetectEngineCtx *de_ctx, FILE *fd)
Loads the Classtype info from the classification.config file.
Definition: util-classification-config.c:528
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:71
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:138
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:330
URL
#define URL
Signature_::metadata
DetectMetadata * metadata
Definition: detect.h:587
DetectReferenceFree
void DetectReferenceFree(DetectReference *ref)
Free a Reference object.
Definition: detect-reference.c:73
DETECT_TBLSIZE
@ DETECT_TBLSIZE
Definition: detect-engine-register.h:268
SignatureParser_::src
char src[DETECT_MAX_RULE_SIZE]
Definition: detect-parse.c:107
DETECT_SM_LIST_THRESHOLD
@ DETECT_SM_LIST_THRESHOLD
Definition: detect.h:104
results
struct DetectRfbSecresult_ results[]
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:30
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1195
SigDuplWrapper_::s_prev
Signature * s_prev
Definition: detect-parse.c:88
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:761
DETECT_PROTO_ANY
#define DETECT_PROTO_ANY
Definition: detect-engine-proto.h:27
FlowInitConfig
void FlowInitConfig(char quiet)
initialize the configuration
Definition: flow.c:529
DETECT_CONTENT_RAWBYTES
#define DETECT_CONTENT_RAWBYTES
Definition: detect-content.h:38
CASE_CODE_STRING
#define CASE_CODE_STRING(E, S)
Signature_::CidrSrc
IPOnlyCIDRItem * CidrSrc
Definition: detect.h:568
SC_ERR_INVALID_SIGNATURE
@ SC_ERR_INVALID_SIGNATURE
Definition: util-error.h:69
DETECT_STREAM_SIZE
@ DETECT_STREAM_SIZE
Definition: detect-engine-register.h:95
AppLayerParserSupportsFiles
int AppLayerParserSupportsFiles(uint8_t ipproto, AppProto alproto)
Definition: app-layer-parser.c:1113
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2030
AppLayerProtoDetectSupportedIpprotos
void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
Definition: app-layer-detect-proto.c:2037
detect-lua.h
DetectParsePcreExecLen
int DetectParsePcreExecLen(DetectParseRegex *parse_regex, const char *str, int str_len, int start_offset, int options, int *ovector, int ovector_size)
Definition: detect-parse.c:2363
SIG_FLAG_DST_ANY
#define SIG_FLAG_DST_ANY
Definition: detect.h:212
SIG_FLAG_REQUIRE_STREAM
#define SIG_FLAG_REQUIRE_STREAM
Definition: detect.h:224
DetectBufferRunValidateCallback
bool DetectBufferRunValidateCallback(const DetectEngineCtx *de_ctx, const int id, const Signature *s, const char **sigerror)
Definition: detect-engine.c:962
DetectKeywordId
DetectKeywordId
Definition: detect-engine-register.h:27
DE_QUIET
#define DE_QUIET
Definition: detect.h:292
DetectLuaPostSetup
void DetectLuaPostSetup(Signature *s)
DetectGetLastSMByListPtr
SigMatch * DetectGetLastSMByListPtr(const Signature *s, SigMatch *sm_list,...)
Returns the sm with the largest index (added last) from the list passed to us as a pointer.
Definition: detect-parse.c:508
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:575
SignatureInitData_::init_flags
uint32_t init_flags
Definition: detect.h:486
DetectParseDupSigHashFree
void DetectParseDupSigHashFree(DetectEngineCtx *de_ctx)
Frees the hash table that is used to cull duplicate sigs.
Definition: detect-parse.c:2147
DetectContentData_
Definition: detect-content.h:86
SigTableElmt_::Free
void(* Free)(void *)
Definition: detect.h:1192
DetectEngineCtx_::sigerror_ok
bool sigerror_ok
Definition: detect.h:868
DetectPcreData_::flags
uint16_t flags
Definition: detect-pcre.h:43
SignatureParser_::dp
char dp[DETECT_MAX_RULE_SIZE]
Definition: detect-parse.c:110
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:39
HashListTableLookup
void * HashListTableLookup(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:248
SC_ERR_DETECT_PREPARE
@ SC_ERR_DETECT_PREPARE
Definition: util-error.h:205
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:237
SIG_FLAG_SRC_ANY
#define SIG_FLAG_SRC_ANY
Definition: detect.h:211
SigTableElmt_
element in sigmatch type table.
Definition: detect.h:1169
SigMatchData_
Data needed for Match()
Definition: detect.h:327
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1187
DetectFlowSetupImplicit
int DetectFlowSetupImplicit(Signature *s, uint32_t flags)
Definition: detect-flow.c:317
detect-pcre.h
DetectMatchAddressIPv4_::ip
uint32_t ip
Definition: detect.h:161
DETECT_TRANSFORMS_MAX
#define DETECT_TRANSFORMS_MAX
Definition: detect.h:58
DetectContentPMATCHValidateCallback
bool DetectContentPMATCHValidateCallback(const Signature *s)
Definition: detect-content.c:377
DetectParseRegexAddToFreeList
void DetectParseRegexAddToFreeList(DetectParseRegex *detect_parse)
add regex and/or study to at exit free list
Definition: detect-parse.c:2406
util-unittest.h
AppLayerGetProtoByName
AppProto AppLayerGetProtoByName(char *alproto_name)
Given a protocol string, returns the corresponding internal protocol id.
Definition: app-layer.c:764
PORT_EQ
@ PORT_EQ
Definition: detect.h:179
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
DetectPortPrint
void DetectPortPrint(DetectPort *dp)
Helper function that print the DetectPort info.
Definition: detect-engine-port.c:646
SIG_FLAG_APPLAYER
#define SIG_FLAG_APPLAYER
Definition: detect.h:218
DetectGetLastSMByListId
SigMatch * DetectGetLastSMByListId(const Signature *s, int list_id,...)
Returns the sm with the largest index (added last) from the list passed to us as an id.
Definition: detect-parse.c:540
DetectSignatureAddTransform
int DetectSignatureAddTransform(Signature *s, int transform)
Definition: detect-parse.c:1442
HashListTableAdd
int HashListTableAdd(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:116
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
HashListTable_::array_size
uint32_t array_size
Definition: util-hashlist.h:41
detect-reference.h
Signature_::gid
uint32_t gid
Definition: detect.h:556
DetectMatchAddressIPv6_::ip2
uint32_t ip2[4]
Definition: detect.h:167
Signature_::next
struct Signature_ * next
Definition: detect.h:594
ACTION_REJECT_DST
#define ACTION_REJECT_DST
Definition: action-globals.h:32
DetectParseFreeRegexes
void DetectParseFreeRegexes(void)
Definition: detect-parse.c:2390
DetectEngineAppInspectionEngine_::sm_list
uint16_t sm_list
Definition: detect.h:401
SignatureInitData_::smlists_tail
struct SigMatch_ ** smlists_tail
Definition: detect.h:518
SIGMATCH_QUOTES_MANDATORY
#define SIGMATCH_QUOTES_MANDATORY
Definition: detect.h:1386
UTHMatchPackets
int UTHMatchPackets(DetectEngineCtx *de_ctx, Packet **p, int num_packets)
Definition: util-unittest-helper.c:741
app-layer-detect-proto.h
DETECT_SM_LIST_POSTMATCH
@ DETECT_SM_LIST_POSTMATCH
Definition: detect.h:98
DetectEngineCtx_::sm_types_silent_error
bool sm_types_silent_error[DETECT_TBLSIZE]
Definition: detect.h:948
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:236
app-layer-htp.h
DetectPortParse
int DetectPortParse(const DetectEngineCtx *de_ctx, DetectPort **head, const char *str)
Function for parsing port strings.
Definition: detect-engine-port.c:1231
detect-app-layer-event.h
HashListTableInit
HashListTable * HashListTableInit(uint32_t size, uint32_t(*Hash)(struct HashListTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
Definition: util-hashlist.c:35
Signature_::addr_src_match4
DetectMatchAddressIPv4 * addr_src_match4
Definition: detect.h:550
SigParseRegisterTests
void SigParseRegisterTests(void)
Definition: detect-parse.c:4096
decode.h
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
util-debug.h
type
uint8_t type
Definition: decode-icmpv4.h:2
SC_ERR_CMD_LINE
@ SC_ERR_CMD_LINE
Definition: util-error.h:227
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
DETECT_CONTENT_DISTANCE
#define DETECT_CONTENT_DISTANCE
Definition: detect-content.h:30
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:16
DetectParseRegex_::study
pcre_extra * study
Definition: detect-parse.h:44
SIG_FLAG_INIT_BIDIREC
#define SIG_FLAG_INIT_BIDIREC
Definition: detect.h:259
DetectProtoParse
int DetectProtoParse(DetectProto *dp, const char *str)
Parses a protocol sent as a string.
Definition: detect-engine-proto.c:56
DetectEngineThreadCtx_
Definition: detect.h:1004
DetectGetLastSMFromMpmLists
SigMatch * DetectGetLastSMFromMpmLists(const DetectEngineCtx *de_ctx, const Signature *s)
get the last SigMatch from lists that support MPM.
Definition: detect-parse.c:429
SignatureInitData_::src
const DetectAddressHead * src
Definition: detect.h:510
DETECT_SM_LIST_BASE64_DATA
@ DETECT_SM_LIST_BASE64_DATA
Definition: detect.h:95
DetectEngineAppInspectionEngineSignatureFree
void DetectEngineAppInspectionEngineSignatureFree(Signature *s)
free app inspect engines for a signature
Definition: detect-engine.c:667
ALPROTO_SMTP
@ ALPROTO_SMTP
Definition: app-layer-protos.h:32
DetectSetupParseRegexes
void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
Definition: detect-parse.c:2440
DETECT_CONTENT_DEPTH
#define DETECT_CONTENT_DEPTH
Definition: detect-content.h:33
SignatureInitData_::list
int list
Definition: detect.h:498
SCEnter
#define SCEnter(...)
Definition: util-debug.h:337
detect-engine-mpm.h
Signature_::references
DetectReference * references
Definition: detect.h:585
DetectBufferTypeMaxId
int DetectBufferTypeMaxId(void)
Definition: detect-engine.c:735
CASE_CODE
#define CASE_CODE(E)
Definition: detect-parse.c:130
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
SCRealloc
#define SCRealloc(x, a)
Definition: util-mem.h:238
SigMatchList2DataArray
SigMatchData * SigMatchList2DataArray(SigMatch *head)
convert SigMatch list to SigMatchData array
Definition: detect-parse.c:1596
pkt-var.h
UTHCheckPacketMatchResults
int UTHCheckPacketMatchResults(Packet *p, uint32_t sids[], uint32_t results[], int numsids)
UTHCheckPacketMatches: function to check if a packet match some sids.
Definition: util-unittest-helper.c:618
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:322
SigMatchData_::type
uint8_t type
Definition: detect.h:328
detect-engine-port.h
SigDuplWrapper_::s
Signature * s
Definition: detect-parse.c:86
SigMatchStrictEnabled
bool SigMatchStrictEnabled(const enum DetectKeywordId id)
Definition: detect-parse.c:298
DetectAddress_::ip2
Address ip2
Definition: detect.h:142
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:89
SIZE_OF_PACKET
#define SIZE_OF_PACKET
Definition: decode.h:619
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2023
DetectPort_
Port structure for detection engine.
Definition: detect.h:191
SC_ERR_INVALID_ARGUMENT
@ SC_ERR_INVALID_ARGUMENT
Definition: util-error.h:43
SigTableElmt_::alternative
uint16_t alternative
Definition: detect.h:1199
app-layer-parser.h
TRUE
#define TRUE
Definition: suricata-common.h:33
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:321
DetectReference_
Signature reference list.
Definition: detect-reference.h:34
SCMalloc
#define SCMalloc(a)
Definition: util-mem.h:222
DetectProto_::proto
uint8_t proto[256/8]
Definition: detect-engine-proto.h:37
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:265
SC_WARN_DEPRECATED
@ SC_WARN_DEPRECATED
Definition: util-error.h:235
SignatureInitData_::transform_cnt
int transform_cnt
Definition: detect.h:502
SigMatchSignatures
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1665
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:1947
Signature_::action
uint8_t action
Definition: detect.h:535
util-profiling.h
util-rule-vars.h
FALSE
#define FALSE
Definition: suricata-common.h:34
SCReturn
#define SCReturn
Definition: util-debug.h:339
Signature_::flags
uint32_t flags
Definition: detect.h:523
DetectEngineContentModifierBufferSetup
int DetectEngineContentModifierBufferSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg, int sm_type, int sm_list, AppProto alproto)
Definition: detect-parse.c:146
DetectParsePcreExec
int DetectParsePcreExec(DetectParseRegex *parse_regex, const char *str, int start_offset, int options, int *ovector, int ovector_size)
Definition: detect-parse.c:2372
ACTION_ALERT
#define ACTION_ALERT
Definition: action-globals.h:29
Packet_
Definition: decode.h:408
SCCalloc
#define SCCalloc(nm, a)
Definition: util-mem.h:253
conf-yaml-loader.h
SIG_FLAG_IPONLY
#define SIG_FLAG_IPONLY
Definition: detect.h:219
conf.h
Signature_::CidrDst
IPOnlyCIDRItem * CidrDst
Definition: detect.h:568
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:97
DETECT_MAX_RULE_SIZE
#define DETECT_MAX_RULE_SIZE
Definition: detect.h:56
SignatureParser_::direction
char direction[DETECT_MAX_RULE_SIZE]
Definition: detect-parse.c:106
detect-ipproto.h
SIGMATCH_HANDLE_NEGATION
#define SIGMATCH_HANDLE_NEGATION
Definition: detect.h:1390
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:591
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:353
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
SignatureInitData_::negated
bool negated
Definition: detect.h:478
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1171
SignatureInitData_
Definition: detect.h:472
SignatureInitData_::smlists
struct SigMatch_ ** smlists
Definition: detect.h:516
SC_ERR_PCRE_STUDY
@ SC_ERR_PCRE_STUDY
Definition: util-error.h:36
HashListTable_
Definition: util-hashlist.h:37
SC_ERR_LIBNET11_INCOMPATIBLE_WITH_LIBCAP_NG
@ SC_ERR_LIBNET11_INCOMPATIBLE_WITH_LIBCAP_NG
Definition: util-error.h:191
DetectGetLastSM
SigMatch * DetectGetLastSM(const Signature *s)
Returns the sm with the largest index (added latest) from this sig.
Definition: detect-parse.c:572
SignatureInitData_::dst_contains_negation
bool dst_contains_negation
Definition: detect.h:483
Signature_::addr_dst_match6_cnt
uint16_t addr_dst_match6_cnt
Definition: detect.h:547
DetectReference_::next
struct DetectReference_ * next
Definition: detect-reference.h:40
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:235
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
DETECT_PCRE
@ DETECT_PCRE
Definition: detect-engine-register.h:61
Signature_::sp
DetectPort * sp
Definition: detect.h:561
DetectMetadata_
Signature metadata list.
Definition: detect-metadata.h:30
IPOnlyCIDRListFree
void IPOnlyCIDRListFree(IPOnlyCIDRItem *tmphead)
This function free a IPOnlyCIDRItem list.
Definition: detect-engine-iponly.c:409
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1876
DetectEngineCtx_::dup_sig_hash_table
HashListTable * dup_sig_hash_table
Definition: detect.h:805
SigMatch_::type
uint8_t type
Definition: detect.h:319
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:33
DetectEngineAppInspectionEngine_::alproto
AppProto alproto
Definition: detect.h:396
SC_ERR_UNKNOWN_PROTOCOL
@ SC_ERR_UNKNOWN_PROTOCOL
Definition: util-error.h:154
DETECT_SM_LIST_NOTSET
#define DETECT_SM_LIST_NOTSET
Definition: detect.h:115
ACTION_REJECT_BOTH
#define ACTION_REJECT_BOTH
Definition: action-globals.h:33
DetectAddressHead_::ipv6_head
DetectAddress * ipv6_head
Definition: detect.h:156
DetectProto_::flags
uint8_t flags
Definition: detect-engine-proto.h:38
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:2316
SigMatchSilentErrorEnabled
bool SigMatchSilentErrorEnabled(const DetectEngineCtx *de_ctx, const enum DetectKeywordId id)
Definition: detect-parse.c:292
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:2726
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
SignatureParser_::opts
char opts[DETECT_MAX_RULE_SIZE]
Definition: detect-parse.c:111
flags
uint8_t flags
Definition: decode-gre.h:2
Signature_::proto
DetectProto proto
Definition: detect.h:539
SIG_DIREC_SRC
@ SIG_DIREC_SRC
Definition: detect-parse.h:38
SigTableElmt_::alias
const char * alias
Definition: detect.h:1202
SigMatchData_::is_last
uint8_t is_last
Definition: detect.h:329
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:2934
SigMatch_::idx
uint16_t idx
Definition: detect.h:320
SIG_FLAG_SP_ANY
#define SIG_FLAG_SP_ANY
Definition: detect.h:213
SignatureParser_::protocol
char protocol[DETECT_MAX_RULE_SIZE]
Definition: detect-parse.c:105
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:82
Signature_::file_flags
uint8_t file_flags
Definition: detect.h:536
FlowShutdown
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:684
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:73
DetectParseRegex_
Definition: detect-parse.h:42
DetectBufferTypeSupportsMpmGetById
bool DetectBufferTypeSupportsMpmGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:924
DETECT_PROTO_ONLY_STREAM
#define DETECT_PROTO_ONLY_STREAM
Definition: detect-engine-proto.h:31
ACTION_DROP
#define ACTION_DROP
Definition: action-globals.h:30
SIG_FLAG_INIT_PACKET
#define SIG_FLAG_INIT_PACKET
Definition: detect.h:257
SignatureParser_::dst
char dst[DETECT_MAX_RULE_SIZE]
Definition: detect-parse.c:108
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
DetectListToString
const char * DetectListToString(int list)
Definition: detect-parse.c:131
DetectMatchAddressIPv4_::ip2
uint32_t ip2
Definition: detect.h:162
Signature_::rev
uint32_t rev
Definition: detect.h:557
SignatureInitData_::sm_cnt
uint16_t sm_cnt
Definition: detect.h:474
util-classification-config.h
FatalError
#define FatalError(x,...)
Definition: util-debug.h:569
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:767
SC_ERR_INVALID_ACTION
@ SC_ERR_INVALID_ACTION
Definition: util-error.h:172
DETECT_SM_LIST_TMATCH
@ DETECT_SM_LIST_TMATCH
Definition: detect.h:100
SignatureParser
struct SignatureParser_ SignatureParser
SigMatchFree
void SigMatchFree(SigMatch *sm)
free a SigMatch
Definition: detect-parse.c:250
Signature_::prio
int prio
Definition: detect.h:558
DetectMatchAddressIPv6_::ip
uint32_t ip[4]
Definition: detect.h:166
SIGMATCH_OPTIONAL_OPT
#define SIGMATCH_OPTIONAL_OPT
Definition: detect.h:1379
detect-flow.h
Signature_::addr_src_match6_cnt
uint16_t addr_src_match6_cnt
Definition: detect.h:548
DetectEngineCtx_::app_inspect_engines
DetectEngineAppInspectionEngine * app_inspect_engines
Definition: detect.h:928
SignatureInitData_::dst
const DetectAddressHead * dst
Definition: detect.h:510
SIG_DIREC_NORMAL
@ SIG_DIREC_NORMAL
Definition: detect-parse.h:31
Signature_::dp
DetectPort * dp
Definition: detect.h:561
str
#define str(s)
Definition: suricata-common.h:256
detect-http-method.h
head
Flow * head
Definition: flow-hash.h:2
DetectParseRegex_::regex
pcre * regex
Definition: detect-parse.h:43
SigMatchListSMBelongsTo
int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
Definition: detect-parse.c:622
SCLogWarning
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
SCNtohl
#define SCNtohl(x)
Definition: suricata-common.h:374
SIGMATCH_INFO_DEPRECATED
#define SIGMATCH_INFO_DEPRECATED
Definition: detect.h:1396
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:622
Signature_::addr_dst_match6
DetectMatchAddressIPv6 * addr_dst_match6
Definition: detect.h:552
Signature_::id
uint32_t id
Definition: detect.h:555
DETECT_CONTENT_OFFSET
#define DETECT_CONTENT_OFFSET
Definition: detect-content.h:32
DetectMetadata_::next
struct DetectMetadata_ * next
Definition: detect-metadata.h:36
detect-engine-iponly.h
detect-parse.h
src
uint16_t src
Definition: app-layer-dnp3.h:7
Signature_
Signature container.
Definition: detect.h:522
SigMatch_
a single match condition for a signature
Definition: detect.h:318
SignatureInitData_::transforms
int transforms[DETECT_TRANSFORMS_MAX]
Definition: detect.h:501
DETECT_SM_LIST_MAX
@ DETECT_SM_LIST_MAX
Definition: detect.h:106
ALPROTO_HTTP
@ ALPROTO_HTTP
Definition: app-layer-protos.h:30
DETECT_PROTO_ONLY_PKT
#define DETECT_PROTO_ONLY_PKT
Definition: detect-engine-proto.h:29
DetectAddress_::next
struct DetectAddress_ * next
Definition: detect.h:150
UTHBuildPacketFromEth
Packet * UTHBuildPacketFromEth(uint8_t *raw_eth, uint16_t pktsize)
UTHBuildPacketFromEth is a wrapper that build a packet for the rawbytes.
Definition: util-unittest-helper.c:319
DetectMatchAddressIPv6_
Definition: detect.h:165
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
ALPROTO_FAILED
@ ALPROTO_FAILED
Definition: app-layer-protos.h:61
DetectMatchAddressIPv4_
Definition: detect.h:160
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:1985
DETECT_PCRE_RELATIVE_NEXT
#define DETECT_PCRE_RELATIVE_NEXT
Definition: detect-pcre.h:34
DetectSetupParseRegexesOpts
void DetectSetupParseRegexesOpts(const char *parse_str, DetectParseRegex *detect_parse, int opts)
Definition: detect-parse.c:2418
SignatureSetType
void SignatureSetType(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine-build.c:1263
app-layer-protos.h
SC_ERR_NO_FILES_FOR_PROTOCOL
@ SC_ERR_NO_FILES_FOR_PROTOCOL
Definition: util-error.h:318
SC_ERR_MEM_ALLOC
@ SC_ERR_MEM_ALLOC
Definition: util-error.h:31
SCClassConfGenerateValidDummyClassConfigFD01
FILE * SCClassConfGenerateValidDummyClassConfigFD01(void)
Creates a dummy classification file, with all valid Classtypes, for testing purposes.
Definition: util-classification-config.c:585
DetectPcreData_
Definition: detect-pcre.h:39
FLOW_QUIET
#define FLOW_QUIET
Definition: flow.h:38
DetectEngineAppInspectionEngine_::dir
uint8_t dir
Definition: detect.h:397
DetectParseAddress
const DetectAddressHead * DetectParseAddress(DetectEngineCtx *de_ctx, const char *string, bool *contains_negation)
Definition: detect-engine-address.c:1441
detect-uricontent.h
DETECT_DEFAULT_PRIO
#define DETECT_DEFAULT_PRIO
Definition: detect.h:62
sc_set_caps
int sc_set_caps
Definition: suricata.c:218
DetectBufferTypeGetNameById
const char * DetectBufferTypeGetNameById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:869
DetectBufferRunSetupCallback
void DetectBufferRunSetupCallback(const DetectEngineCtx *de_ctx, const int id, Signature *s)
Definition: detect-engine.c:943
SC_ERR_RULE_KEYWORD_UNKNOWN
@ SC_ERR_RULE_KEYWORD_UNKNOWN
Definition: util-error.h:132
SIGMATCH_NOOPT
#define SIGMATCH_NOOPT
Definition: detect.h:1370
DetectEngineCtx_::sigerror
const char * sigerror
Definition: detect.h:869
DetectParseFreeRegex
void DetectParseFreeRegex(DetectParseRegex *r)
Definition: detect-parse.c:2380
DetectGetLastSMFromLists
SigMatch * DetectGetLastSMFromLists(const Signature *s,...)
Returns the sm with the largest index (added latest) from the lists passed to us.
Definition: detect-parse.c:468
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:762
SigAlloc
Signature * SigAlloc(void)
Definition: detect-parse.c:1254
UTHAppendSigs
int UTHAppendSigs(DetectEngineCtx *de_ctx, const char *sigs[], int numsigs)
UTHAppendSigs: Add sigs to the detection_engine checking for errors.
Definition: util-unittest-helper.c:652
dst
uint16_t dst
Definition: app-layer-dnp3.h:6
Signature_::addr_dst_match4
DetectMatchAddressIPv4 * addr_dst_match4
Definition: detect.h:549
DETECT_CONTENT_REPLACE
#define DETECT_CONTENT_REPLACE
Definition: detect-content.h:51
Signature_::msg
char * msg
Definition: detect.h:580
flow.h
Signature_::addr_src_match4_cnt
uint16_t addr_src_match4_cnt
Definition: detect.h:546
Signature_::addr_dst_match4_cnt
uint16_t addr_dst_match4_cnt
Definition: detect.h:545
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:341
DetectEngineCtx_::signum
uint32_t signum
Definition: detect.h:780
DetectPortCleanupList
void DetectPortCleanupList(const DetectEngineCtx *de_ctx, DetectPort *head)
Free a DetectPort list and each of its members.
Definition: detect-engine-port.c:120
DETECT_SM_LIST_SUPPRESS
@ DETECT_SM_LIST_SUPPRESS
Definition: detect.h:103
SIG_DIREC_SWITCHED
@ SIG_DIREC_SWITCHED
Definition: detect-parse.h:32
DecodeEthernet
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-ethernet.c:41
DetectAddressHead_::ipv4_head
DetectAddress * ipv4_head
Definition: detect.h:155
SigMatchAppendSMToList
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:349
detect-engine-address.h
DetectBufferTypeSupportsPacketGetById
bool DetectBufferTypeSupportsPacketGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:915
SIG_FLAG_FILESTORE
#define SIG_FLAG_FILESTORE
Definition: detect.h:234
DETECT_CONTENT_WITHIN
#define DETECT_CONTENT_WITHIN
Definition: detect-content.h:31
detect-parse.c
debug.h
SIG_FLAG_DP_ANY
#define SIG_FLAG_DP_ANY
Definition: detect.h:214
PACKET_RECYCLE
#define PACKET_RECYCLE(p)
Definition: decode.h:804
app-layer.h
SignatureInitData_::smlists_array_size
uint32_t smlists_array_size
Definition: detect.h:514
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:223
SC_ERR_CONFLICTING_RULE_KEYWORDS
@ SC_ERR_CONFLICTING_RULE_KEYWORDS
Definition: util-error.h:171