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