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 
848  s->init_data->src = DetectParseAddress(de_ctx, addrstr,
850  if (s->init_data->src == NULL)
851  goto error;
852  } else {
853  if (strcasecmp(addrstr, "any") == 0)
854  s->flags |= SIG_FLAG_DST_ANY;
855 
856  s->init_data->dst = DetectParseAddress(de_ctx, addrstr,
858  if (s->init_data->dst == NULL)
859  goto error;
860  }
861 
862  return 0;
863 
864 error:
865  return -1;
866 }
867 
868 /**
869  * \brief Parses the protocol supplied by the Signature.
870  *
871  * http://www.iana.org/assignments/protocol-numbers
872  *
873  * \param s Pointer to the Signature instance to which the parsed
874  * protocol has to be added.
875  * \param protostr Pointer to the character string containing the protocol name.
876  *
877  * \retval 0 On successfully parsing the protocl sent as the argument.
878  * \retval -1 On failure
879  */
880 static int SigParseProto(Signature *s, const char *protostr)
881 {
882  SCEnter();
883 
884  int r = DetectProtoParse(&s->proto, (char *)protostr);
885  if (r < 0) {
886  s->alproto = AppLayerGetProtoByName((char *)protostr);
887  /* indicate that the signature is app-layer */
888  if (s->alproto != ALPROTO_UNKNOWN) {
889  s->flags |= SIG_FLAG_APPLAYER;
890 
892  }
893  else {
894  SCLogError(SC_ERR_UNKNOWN_PROTOCOL, "protocol \"%s\" cannot be used "
895  "in a signature. Either detection for this protocol "
896  "is not yet supported OR detection has been disabled for "
897  "protocol through the yaml option "
898  "app-layer.protocols.%s.detection-enabled", protostr,
899  protostr);
900  SCReturnInt(-1);
901  }
902  }
903 
904  /* if any of these flags are set they are set in a mutually exclusive
905  * manner */
906  if (s->proto.flags & DETECT_PROTO_ONLY_PKT) {
908  } else if (s->proto.flags & DETECT_PROTO_ONLY_STREAM) {
910  }
911 
912  SCReturnInt(0);
913 }
914 
915 /**
916  * \brief Parses the port(source or destination) field, from a Signature.
917  *
918  * \param s Pointer to the signature which has to be updated with the
919  * port information.
920  * \param portstr Pointer to the character string containing the port info.
921  * \param Flag which indicates if the portstr received is src or dst
922  * port. For src port: flag = 0, dst port: flag = 1.
923  *
924  * \retval 0 On success.
925  * \retval -1 On failure.
926  */
927 static int SigParsePort(const DetectEngineCtx *de_ctx,
928  Signature *s, const char *portstr, char flag)
929 {
930  int r = 0;
931 
932  /* XXX VJ exclude handling this for none UDP/TCP proto's */
933 
934  SCLogDebug("Port group \"%s\" to be parsed", portstr);
935 
936  if (flag == 0) {
937  if (strcasecmp(portstr, "any") == 0)
938  s->flags |= SIG_FLAG_SP_ANY;
939 
940  r = DetectPortParse(de_ctx, &s->sp, (char *)portstr);
941  } else if (flag == 1) {
942  if (strcasecmp(portstr, "any") == 0)
943  s->flags |= SIG_FLAG_DP_ANY;
944 
945  r = DetectPortParse(de_ctx, &s->dp, (char *)portstr);
946  }
947 
948  if (r < 0)
949  return -1;
950 
951  return 0;
952 }
953 
954 /** \retval 1 valid
955  * \retval 0 invalid
956  */
957 static int SigParseActionRejectValidate(const char *action)
958 {
959 #ifdef HAVE_LIBNET11
960 #if defined HAVE_LIBCAP_NG && !defined HAVE_LIBNET_CAPABILITIES
961  if (sc_set_caps == TRUE) {
963  "incompatible with POSIX based capabilities with privs dropping. "
964  "For rejects to work, run as root/super user.");
965  return 0;
966  }
967 #endif
968 #else /* no libnet 1.1 */
970  "required for action \"%s\" but is not compiled into Suricata",
971  action);
972  return 0;
973 #endif
974  return 1;
975 }
976 
977 /**
978  * \brief Parses the action that has been used by the Signature and allots it
979  * to its Signature instance.
980  *
981  * \param s Pointer to the Signature instance to which the action belongs.
982  * \param action Pointer to the action string used by the Signature.
983  *
984  * \retval 0 On successfully parsing the action string and adding it to the
985  * Signature.
986  * \retval -1 On failure.
987  */
988 static int SigParseAction(Signature *s, const char *action)
989 {
990  if (strcasecmp(action, "alert") == 0) {
991  s->action = ACTION_ALERT;
992  return 0;
993  } else if (strcasecmp(action, "drop") == 0) {
994  s->action = ACTION_DROP;
995  return 0;
996  } else if (strcasecmp(action, "pass") == 0) {
997  s->action = ACTION_PASS;
998  return 0;
999  } else if (strcasecmp(action, "reject") == 0) {
1000  if (!(SigParseActionRejectValidate(action)))
1001  return -1;
1003  return 0;
1004  } else if (strcasecmp(action, "rejectsrc") == 0) {
1005  if (!(SigParseActionRejectValidate(action)))
1006  return -1;
1008  return 0;
1009  } else if (strcasecmp(action, "rejectdst") == 0) {
1010  if (!(SigParseActionRejectValidate(action)))
1011  return -1;
1013  return 0;
1014  } else if (strcasecmp(action, "rejectboth") == 0) {
1015  if (!(SigParseActionRejectValidate(action)))
1016  return -1;
1018  return 0;
1019  } else {
1020  SCLogError(SC_ERR_INVALID_ACTION,"An invalid action \"%s\" was given",action);
1021  return -1;
1022  }
1023 }
1024 
1025 /**
1026  * \brief Parse the next token in rule.
1027  *
1028  * For rule parsing a token is considered to be a string of characters
1029  * separated by white space.
1030  *
1031  * \param input double pointer to input buffer, will be advanced as input is
1032  * parsed.
1033  * \param output buffer to copy token into.
1034  * \param output_size length of output buffer.
1035  */
1036 static inline int SigParseToken(char **input, char *output,
1037  const size_t output_size)
1038 {
1039  size_t len = *input == NULL ? 0 : strlen(*input);
1040 
1041  if (!len) {
1042  return 0;
1043  }
1044 
1045  while (len && isblank(**input)) {
1046  (*input)++;
1047  len--;
1048  }
1049 
1050  char *endptr = strpbrk(*input, " \t\n\r");
1051  if (endptr != NULL) {
1052  *(endptr++) = '\0';
1053  }
1054  strlcpy(output, *input, output_size);
1055  *input = endptr;
1056 
1057  return 1;
1058 }
1059 
1060 /**
1061  * \brief Parse the next rule "list" token.
1062  *
1063  * Parses rule tokens that may be lists such as addresses and ports
1064  * handling the case when they may not be lists.
1065  *
1066  * \param input ouble pointer to input buffer, will be advanced as input is
1067  * parsed.
1068  * \param output buffer to copy token into.
1069  * \param output_size length of output buffer.
1070  */
1071 static inline int SigParseList(char **input, char *output,
1072  const size_t output_size)
1073 {
1074  int in_list = 0;
1075  size_t len = *input != NULL ? strlen(*input) : 0;
1076 
1077  if (len == 0) {
1078  return 0;
1079  }
1080 
1081  while (len && isblank(**input)) {
1082  (*input)++;
1083  len--;
1084  }
1085 
1086  size_t i = 0;
1087  for (i = 0; i < len; i++) {
1088  char c = (*input)[i];
1089  if (c == '[') {
1090  in_list++;
1091  } else if (c == ']') {
1092  in_list--;
1093  } else if (c == ' ') {
1094  if (!in_list) {
1095  break;
1096  }
1097  }
1098  }
1099  if (i == len) {
1100  *input = NULL;
1101  return 0;
1102  }
1103  (*input)[i] = '\0';
1104  strlcpy(output, *input, output_size);
1105  *input = *input + i + 1;
1106 
1107  return 1;
1108 }
1109 
1110 /**
1111  * \internal
1112  * \brief split a signature string into a few blocks for further parsing
1113  */
1114 static int SigParseBasics(DetectEngineCtx *de_ctx,
1115  Signature *s, const char *sigstr, SignatureParser *parser, uint8_t addrs_direction)
1116 {
1117  char *index, dup[DETECT_MAX_RULE_SIZE];
1118 
1119  strlcpy(dup, sigstr, DETECT_MAX_RULE_SIZE);
1120  index = dup;
1121 
1122  /* Action. */
1123  SigParseToken(&index, parser->action, sizeof(parser->action));
1124 
1125  /* Protocol. */
1126  SigParseList(&index, parser->protocol, sizeof(parser->protocol));
1127 
1128  /* Source. */
1129  SigParseList(&index, parser->src, sizeof(parser->src));
1130 
1131  /* Source port(s). */
1132  SigParseList(&index, parser->sp, sizeof(parser->sp));
1133 
1134  /* Direction. */
1135  SigParseToken(&index, parser->direction, sizeof(parser->direction));
1136 
1137  /* Destination. */
1138  SigParseList(&index, parser->dst, sizeof(parser->dst));
1139 
1140  /* Destination port(s). */
1141  SigParseList(&index, parser->dp, sizeof(parser->dp));
1142 
1143  /* Options. */
1144  if (index == NULL) {
1145  SCLogError(SC_ERR_INVALID_RULE_ARGUMENT, "no rule options.");
1146  goto error;
1147  }
1148  while (isspace(*index) || *index == '(') {
1149  index++;
1150  }
1151  for (size_t i = strlen(index); i > 0; i--) {
1152  if (isspace(index[i - 1]) || index[i - 1] == ')') {
1153  index[i - 1] = '\0';
1154  } else {
1155  break;
1156  }
1157  }
1158  strlcpy(parser->opts, index, sizeof(parser->opts));
1159 
1160  /* Parse Action */
1161  if (SigParseAction(s, parser->action) < 0)
1162  goto error;
1163 
1164  if (SigParseProto(s, parser->protocol) < 0)
1165  goto error;
1166 
1167  if (strcmp(parser->direction, "<>") == 0) {
1169  } else if (strcmp(parser->direction, "->") != 0) {
1171  "\"%s\" is not a valid direction modifier, "
1172  "\"->\" and \"<>\" are supported.", parser->direction);
1173  goto error;
1174  }
1175 
1176  /* Parse Address & Ports */
1177  if (SigParseAddress(de_ctx, s, parser->src, SIG_DIREC_SRC ^ addrs_direction) < 0)
1178  goto error;
1179 
1180  if (SigParseAddress(de_ctx, s, parser->dst, SIG_DIREC_DST ^ addrs_direction) < 0)
1181  goto error;
1182 
1183  /* By AWS - Traditionally we should be doing this only for tcp/udp/sctp,
1184  * but we do it for regardless of ip proto, since the dns/dnstcp/dnsudp
1185  * changes that we made sees to it that at this point of time we don't
1186  * set the ip proto for the sig. We do it a bit later. */
1187  if (SigParsePort(de_ctx, s, parser->sp, SIG_DIREC_SRC ^ addrs_direction) < 0)
1188  goto error;
1189  if (SigParsePort(de_ctx, s, parser->dp, SIG_DIREC_DST ^ addrs_direction) < 0)
1190  goto error;
1191 
1192  return 0;
1193 
1194 error:
1195  return -1;
1196 }
1197 
1198 /**
1199  * \brief parse a signature
1200  *
1201  * \param de_ctx detection engine ctx to add it to
1202  * \param s memory structure to store the signature in
1203  * \param sigstr the raw signature as a null terminated string
1204  * \param addrs_direction direction (for bi-directional sigs)
1205  *
1206  * \param -1 parse error
1207  * \param 0 ok
1208  */
1209 static int SigParse(DetectEngineCtx *de_ctx, Signature *s,
1210  const char *sigstr, uint8_t addrs_direction, SignatureParser *parser)
1211 {
1212  SCEnter();
1213 
1214  s->sig_str = SCStrdup(sigstr);
1215  if (unlikely(s->sig_str == NULL)) {
1216  SCReturnInt(-1);
1217  }
1218 
1219  int ret = SigParseBasics(de_ctx, s, sigstr, parser, addrs_direction);
1220  if (ret < 0) {
1221  SCLogDebug("SigParseBasics failed");
1222  SCReturnInt(-1);
1223  }
1224 
1225  /* we can have no options, so make sure we have them */
1226  if (strlen(parser->opts) > 0) {
1227  size_t buffer_size = strlen(parser->opts) + 1;
1228  char input[buffer_size];
1229  char output[buffer_size];
1230  memset(input, 0x00, buffer_size);
1231  memcpy(input, parser->opts, strlen(parser->opts)+1);
1232 
1233  /* loop the option parsing. Each run processes one option
1234  * and returns the rest of the option string through the
1235  * output variable. */
1236  do {
1237  memset(output, 0x00, buffer_size);
1238  ret = SigParseOptions(de_ctx, s, input, output, buffer_size);
1239  if (ret == 1) {
1240  memcpy(input, output, buffer_size);
1241  }
1242 
1243  } while (ret == 1);
1244  }
1245 
1247 
1248  SCReturnInt(ret);
1249 }
1250 
1252 {
1253  Signature *sig = SCMalloc(sizeof(Signature));
1254  if (unlikely(sig == NULL))
1255  return NULL;
1256  memset(sig, 0, sizeof(Signature));
1257 
1258  sig->init_data = SCCalloc(1, sizeof(SignatureInitData));
1259  if (sig->init_data == NULL) {
1260  SCFree(sig);
1261  return NULL;
1262  }
1263 
1265  SCLogDebug("smlists size %u", sig->init_data->smlists_array_size);
1266  sig->init_data->smlists = SCCalloc(sig->init_data->smlists_array_size, sizeof(SigMatch *));
1267  if (sig->init_data->smlists == NULL) {
1268  SCFree(sig->init_data);
1269  SCFree(sig);
1270  return NULL;
1271  }
1272 
1274  if (sig->init_data->smlists_tail == NULL) {
1275  SCFree(sig->init_data->smlists_tail);
1276  SCFree(sig->init_data);
1277  SCFree(sig);
1278  return NULL;
1279  }
1280 
1281  /* assign it to -1, so that we can later check if the value has been
1282  * overwritten after the Signature has been parsed, and if it hasn't been
1283  * overwritten, we can then assign the default value of 3 */
1284  sig->prio = -1;
1285 
1287  return sig;
1288 }
1289 
1290 /**
1291  * \internal
1292  * \brief Free Medadata list
1293  *
1294  * \param s Pointer to the signature
1295  */
1296 static void SigMetadataFree(Signature *s)
1297 {
1298  SCEnter();
1299 
1300  DetectMetadata *mdata = NULL;
1301  DetectMetadata *next_mdata = NULL;
1302 
1303  if (s == NULL) {
1304  SCReturn;
1305  }
1306 
1307  SCLogDebug("s %p, s->metadata %p", s, s->metadata);
1308 
1309  for (mdata = s->metadata; mdata != NULL;) {
1310  next_mdata = mdata->next;
1311  DetectMetadataFree(mdata);
1312  mdata = next_mdata;
1313  }
1314 
1315  s->metadata = NULL;
1316 
1317  SCReturn;
1318 }
1319 
1320 /**
1321  * \internal
1322  * \brief Free Reference list
1323  *
1324  * \param s Pointer to the signature
1325  */
1326 static void SigRefFree (Signature *s)
1327 {
1328  SCEnter();
1329 
1330  DetectReference *ref = NULL;
1331  DetectReference *next_ref = NULL;
1332 
1333  if (s == NULL) {
1334  SCReturn;
1335  }
1336 
1337  SCLogDebug("s %p, s->references %p", s, s->references);
1338 
1339  for (ref = s->references; ref != NULL;) {
1340  next_ref = ref->next;
1341  DetectReferenceFree(ref);
1342  ref = next_ref;
1343  }
1344 
1345  s->references = NULL;
1346 
1347  SCReturn;
1348 }
1349 
1350 static void SigMatchFreeArrays(Signature *s, int ctxs)
1351 {
1352  if (s != NULL) {
1353  int type;
1354  for (type = 0; type < DETECT_SM_LIST_MAX; type++) {
1355  if (s->sm_arrays[type] != NULL) {
1356  if (ctxs) {
1357  SigMatchData *smd = s->sm_arrays[type];
1358  while(1) {
1359  if (sigmatch_table[smd->type].Free != NULL) {
1360  sigmatch_table[smd->type].Free(smd->ctx);
1361  }
1362  if (smd->is_last)
1363  break;
1364  smd++;
1365  }
1366  }
1367 
1368  SCFree(s->sm_arrays[type]);
1369  }
1370  }
1371  }
1372 }
1373 
1375 {
1376  if (s == NULL)
1377  return;
1378 
1379  if (s->CidrDst != NULL)
1381 
1382  if (s->CidrSrc != NULL)
1384 
1385  int i;
1386  if (s->init_data) {
1387  const int nlists = s->init_data->smlists_array_size;
1388  for (i = 0; i < nlists; i++) {
1389  SigMatch *sm = s->init_data->smlists[i];
1390  while (sm != NULL) {
1391  SigMatch *nsm = sm->next;
1392  SigMatchFree(sm);
1393  sm = nsm;
1394  }
1395  }
1396  }
1397  SigMatchFreeArrays(s, (s->init_data == NULL));
1398  if (s->init_data) {
1399  SCFree(s->init_data->smlists);
1401  SCFree(s->init_data);
1402  s->init_data = NULL;
1403  }
1404 
1405  if (s->sp != NULL) {
1406  DetectPortCleanupList(NULL, s->sp);
1407  }
1408  if (s->dp != NULL) {
1409  DetectPortCleanupList(NULL, s->dp);
1410  }
1411 
1412  if (s->msg != NULL)
1413  SCFree(s->msg);
1414 
1415  if (s->addr_src_match4 != NULL) {
1416  SCFree(s->addr_src_match4);
1417  }
1418  if (s->addr_dst_match4 != NULL) {
1419  SCFree(s->addr_dst_match4);
1420  }
1421  if (s->addr_src_match6 != NULL) {
1422  SCFree(s->addr_src_match6);
1423  }
1424  if (s->addr_dst_match6 != NULL) {
1425  SCFree(s->addr_dst_match6);
1426  }
1427  if (s->sig_str != NULL) {
1428  SCFree(s->sig_str);
1429  }
1430 
1431  SigRefFree(s);
1432  SigMetadataFree(s);
1433 
1435 
1436  SCFree(s);
1437 }
1438 
1440 {
1441  /* we only support buffers */
1442  if (s->init_data->list == 0) {
1443  SCReturnInt(-1);
1444  }
1445  if (!s->init_data->list_set) {
1446  SCLogError(SC_ERR_INVALID_SIGNATURE, "transforms must directly follow stickybuffers");
1447  SCReturnInt(-1);
1448  }
1450  SCReturnInt(-1);
1451  }
1452  s->init_data->transforms[s->init_data->transform_cnt++] = transform;
1453  SCReturnInt(0);
1454 }
1455 
1457 {
1458  if (alproto == ALPROTO_UNKNOWN ||
1459  alproto >= ALPROTO_FAILED) {
1460  SCLogError(SC_ERR_INVALID_ARGUMENT, "invalid alproto %u", alproto);
1461  return -1;
1462  }
1463 
1464  if (s->alproto != ALPROTO_UNKNOWN && s->alproto != alproto) {
1466  "can't set rule app proto to %s: already set to %s",
1467  AppProtoToString(alproto), AppProtoToString(s->alproto));
1468  return -1;
1469  }
1470 
1471  s->alproto = alproto;
1472  s->flags |= SIG_FLAG_APPLAYER;
1473  return 0;
1474 }
1475 
1476 /**
1477  * \internal
1478  * \brief build address match array for cache efficient matching
1479  *
1480  * \param s the signature
1481  */
1482 static void SigBuildAddressMatchArray(Signature *s)
1483 {
1484  /* source addresses */
1485  uint16_t cnt = 0;
1486  uint16_t idx = 0;
1487  DetectAddress *da = s->init_data->src->ipv4_head;
1488  for ( ; da != NULL; da = da->next) {
1489  cnt++;
1490  }
1491  if (cnt > 0) {
1492  s->addr_src_match4 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv4));
1493  if (s->addr_src_match4 == NULL) {
1494  exit(EXIT_FAILURE);
1495  }
1496 
1497  for (da = s->init_data->src->ipv4_head; da != NULL; da = da->next) {
1498  s->addr_src_match4[idx].ip = SCNtohl(da->ip.addr_data32[0]);
1499  s->addr_src_match4[idx].ip2 = SCNtohl(da->ip2.addr_data32[0]);
1500  idx++;
1501  }
1502  s->addr_src_match4_cnt = cnt;
1503  }
1504 
1505  /* destination addresses */
1506  cnt = 0;
1507  idx = 0;
1508  da = s->init_data->dst->ipv4_head;
1509  for ( ; da != NULL; da = da->next) {
1510  cnt++;
1511  }
1512  if (cnt > 0) {
1513  s->addr_dst_match4 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv4));
1514  if (s->addr_dst_match4 == NULL) {
1515  exit(EXIT_FAILURE);
1516  }
1517 
1518  for (da = s->init_data->dst->ipv4_head; da != NULL; da = da->next) {
1519  s->addr_dst_match4[idx].ip = SCNtohl(da->ip.addr_data32[0]);
1520  s->addr_dst_match4[idx].ip2 = SCNtohl(da->ip2.addr_data32[0]);
1521  idx++;
1522  }
1523  s->addr_dst_match4_cnt = cnt;
1524  }
1525 
1526  /* source addresses IPv6 */
1527  cnt = 0;
1528  idx = 0;
1529  da = s->init_data->src->ipv6_head;
1530  for ( ; da != NULL; da = da->next) {
1531  cnt++;
1532  }
1533  if (cnt > 0) {
1534  s->addr_src_match6 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv6));
1535  if (s->addr_src_match6 == NULL) {
1536  exit(EXIT_FAILURE);
1537  }
1538 
1539  for (da = s->init_data->src->ipv6_head; da != NULL; da = da->next) {
1540  s->addr_src_match6[idx].ip[0] = SCNtohl(da->ip.addr_data32[0]);
1541  s->addr_src_match6[idx].ip[1] = SCNtohl(da->ip.addr_data32[1]);
1542  s->addr_src_match6[idx].ip[2] = SCNtohl(da->ip.addr_data32[2]);
1543  s->addr_src_match6[idx].ip[3] = SCNtohl(da->ip.addr_data32[3]);
1544  s->addr_src_match6[idx].ip2[0] = SCNtohl(da->ip2.addr_data32[0]);
1545  s->addr_src_match6[idx].ip2[1] = SCNtohl(da->ip2.addr_data32[1]);
1546  s->addr_src_match6[idx].ip2[2] = SCNtohl(da->ip2.addr_data32[2]);
1547  s->addr_src_match6[idx].ip2[3] = SCNtohl(da->ip2.addr_data32[3]);
1548  idx++;
1549  }
1550  s->addr_src_match6_cnt = cnt;
1551  }
1552 
1553  /* destination addresses IPv6 */
1554  cnt = 0;
1555  idx = 0;
1556  da = s->init_data->dst->ipv6_head;
1557  for ( ; da != NULL; da = da->next) {
1558  cnt++;
1559  }
1560  if (cnt > 0) {
1561  s->addr_dst_match6 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv6));
1562  if (s->addr_dst_match6 == NULL) {
1563  exit(EXIT_FAILURE);
1564  }
1565 
1566  for (da = s->init_data->dst->ipv6_head; da != NULL; da = da->next) {
1567  s->addr_dst_match6[idx].ip[0] = SCNtohl(da->ip.addr_data32[0]);
1568  s->addr_dst_match6[idx].ip[1] = SCNtohl(da->ip.addr_data32[1]);
1569  s->addr_dst_match6[idx].ip[2] = SCNtohl(da->ip.addr_data32[2]);
1570  s->addr_dst_match6[idx].ip[3] = SCNtohl(da->ip.addr_data32[3]);
1571  s->addr_dst_match6[idx].ip2[0] = SCNtohl(da->ip2.addr_data32[0]);
1572  s->addr_dst_match6[idx].ip2[1] = SCNtohl(da->ip2.addr_data32[1]);
1573  s->addr_dst_match6[idx].ip2[2] = SCNtohl(da->ip2.addr_data32[2]);
1574  s->addr_dst_match6[idx].ip2[3] = SCNtohl(da->ip2.addr_data32[3]);
1575  idx++;
1576  }
1577  s->addr_dst_match6_cnt = cnt;
1578  }
1579 }
1580 
1581 static int SigMatchListLen(SigMatch *sm)
1582 {
1583  int len = 0;
1584  for (; sm != NULL; sm = sm->next)
1585  len++;
1586 
1587  return len;
1588 }
1589 
1590 /** \brief convert SigMatch list to SigMatchData array
1591  * \note ownership of sm->ctx is transfered to smd->ctx
1592  */
1594 {
1595  int len = SigMatchListLen(head);
1596  if (len == 0)
1597  return NULL;
1598 
1599  SigMatchData *smd = (SigMatchData *)SCCalloc(len, sizeof(SigMatchData));
1600  if (smd == NULL) {
1601  SCLogError(SC_ERR_DETECT_PREPARE, "initializing the detection engine failed");
1602  exit(EXIT_FAILURE);
1603  }
1604  SigMatchData *out = smd;
1605 
1606  /* Copy sm type and Context into array */
1607  SigMatch *sm = head;
1608  for (; sm != NULL; sm = sm->next, smd++) {
1609  smd->type = sm->type;
1610  smd->ctx = sm->ctx;
1611  sm->ctx = NULL; // SigMatch no longer owns the ctx
1612  smd->is_last = (sm->next == NULL);
1613  }
1614  return out;
1615 }
1616 
1617 /**
1618  * \internal
1619  * \brief validate a just parsed signature for internal inconsistencies
1620  *
1621  * \param s just parsed signature
1622  *
1623  * \retval 0 invalid
1624  * \retval 1 valid
1625  */
1626 static int SigValidate(DetectEngineCtx *de_ctx, Signature *s)
1627 {
1628  uint32_t sig_flags = 0;
1629  SigMatch *sm;
1630  const int nlists = s->init_data->smlists_array_size;
1631 
1632  SCEnter();
1633 
1634  /* check for sticky buffers that were set w/o matches
1635  * e.g. alert ... (file_data; sid:1;) */
1636  if (s->init_data->list != DETECT_SM_LIST_NOTSET) {
1637  if (s->init_data->smlists[s->init_data->list] == NULL) {
1638  SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u setup buffer %s but didn't add matches to it",
1639  s->id, DetectBufferTypeGetNameById(de_ctx, s->init_data->list));
1640  SCReturnInt(0);
1641  }
1642  }
1643 
1644  /* run buffer type validation callbacks if any */
1647  SCReturnInt(0);
1648  }
1649 
1650  struct BufferVsDir {
1651  int ts;
1652  int tc;
1653  } bufdir[nlists];
1654  memset(&bufdir, 0, nlists * sizeof(struct BufferVsDir));
1655 
1656  int x;
1657  for (x = 0; x < nlists; x++) {
1658  if (s->init_data->smlists[x]) {
1660  for ( ; app != NULL; app = app->next) {
1661  if (app->sm_list == x && ((s->alproto == app->alproto) || s->alproto == 0)) {
1662  SCLogDebug("engine %s dir %d alproto %d",
1663  DetectBufferTypeGetNameById(de_ctx, app->sm_list),
1664  app->dir, app->alproto);
1665 
1666  bufdir[x].ts += (app->dir == 0);
1667  bufdir[x].tc += (app->dir == 1);
1668  }
1669  }
1670 
1671  if (DetectBufferRunValidateCallback(de_ctx, x, s, &de_ctx->sigerror) == FALSE) {
1672  SCReturnInt(0);
1673  }
1674  }
1675  }
1676 
1677  int ts_excl = 0;
1678  int tc_excl = 0;
1679  int dir_amb = 0;
1680  for (x = 0; x < nlists; x++) {
1681  if (bufdir[x].ts == 0 && bufdir[x].tc == 0)
1682  continue;
1683  ts_excl += (bufdir[x].ts > 0 && bufdir[x].tc == 0);
1684  tc_excl += (bufdir[x].ts == 0 && bufdir[x].tc > 0);
1685  dir_amb += (bufdir[x].ts > 0 && bufdir[x].tc > 0);
1686 
1687  SCLogDebug("%s/%d: %d/%d", DetectBufferTypeGetNameById(de_ctx, x),
1688  x, bufdir[x].ts, bufdir[x].tc);
1689  }
1690  if (ts_excl && tc_excl) {
1691  SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id);
1692  SCReturnInt(0);
1693  } else if (ts_excl) {
1694  SCLogDebug("%u: implied rule direction is toserver", s->id);
1696  SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id);
1697  SCReturnInt(0);
1698  }
1699  } else if (tc_excl) {
1700  SCLogDebug("%u: implied rule direction is toclient", s->id);
1702  SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id);
1703  SCReturnInt(0);
1704  }
1705  } else if (dir_amb) {
1706  SCLogDebug("%u: rule direction cannot be deduced from keywords", s->id);
1707  }
1708 
1709  if ((s->flags & SIG_FLAG_REQUIRE_PACKET) &&
1710  (s->flags & SIG_FLAG_REQUIRE_STREAM)) {
1711  SCLogError(SC_ERR_INVALID_SIGNATURE, "can't mix packet keywords with "
1712  "tcp-stream or flow:only_stream. Invalidating signature.");
1713  SCReturnInt(0);
1714  }
1715 
1716 #if 0 // TODO figure out why this is even necessary
1717  if ((s->init_data->smlists[DETECT_SM_LIST_FILEDATA] != NULL && s->alproto == ALPROTO_SMTP) ||
1718  s->init_data->smlists[DETECT_SM_LIST_UMATCH] != NULL ||
1719  s->init_data->smlists[DETECT_SM_LIST_HRUDMATCH] != NULL ||
1720  s->init_data->smlists[DETECT_SM_LIST_HCBDMATCH] != NULL ||
1721  s->init_data->smlists[DETECT_SM_LIST_HUADMATCH] != NULL) {
1722  sig_flags |= SIG_FLAG_TOSERVER;
1723  s->flags |= SIG_FLAG_TOSERVER;
1724  s->flags &= ~SIG_FLAG_TOCLIENT;
1725  }
1726  if ((s->init_data->smlists[DETECT_SM_LIST_FILEDATA] != NULL && s->alproto == ALPROTO_HTTP) ||
1727  s->init_data->smlists[DETECT_SM_LIST_HSMDMATCH] != NULL ||
1728  s->init_data->smlists[DETECT_SM_LIST_HSCDMATCH] != NULL) {
1729  sig_flags |= SIG_FLAG_TOCLIENT;
1730  s->flags |= SIG_FLAG_TOCLIENT;
1731  s->flags &= ~SIG_FLAG_TOSERVER;
1732  }
1733 #endif
1735  SCLogError(SC_ERR_INVALID_SIGNATURE,"You seem to have mixed keywords "
1736  "that require inspection in both directions. Atm we only "
1737  "support keywords in one direction within a rule.");
1738  SCReturnInt(0);
1739  }
1740 
1741  if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
1742  for (int i = 0; i < nlists; i++) {
1743  if (s->init_data->smlists[i] == NULL)
1744  continue;
1745  if (!(DetectBufferTypeGetNameById(de_ctx, i)))
1746  continue;
1747 
1748  if (!(DetectBufferTypeSupportsPacketGetById(de_ctx, i))) {
1749  SCLogError(SC_ERR_INVALID_SIGNATURE, "Signature combines packet "
1750  "specific matches (like dsize, flags, ttl) with stream / "
1751  "state matching by matching on app layer proto (like using "
1752  "http_* keywords).");
1753  SCReturnInt(0);
1754  }
1755  }
1756  }
1757 
1758  /* TCP: corner cases:
1759  * - pkt vs stream vs depth/offset
1760  * - pkt vs stream vs stream_size
1761  */
1762  if (s->proto.proto[IPPROTO_TCP / 8] & (1 << (IPPROTO_TCP % 8))) {
1767  while (sm != NULL) {
1768  if (sm->type == DETECT_CONTENT &&
1769  (((DetectContentData *)(sm->ctx))->flags &
1772  break;
1773  }
1774  sm = sm->next;
1775  }
1776  /* if stream_size is in use, also inspect packets */
1778  while (sm != NULL) {
1779  if (sm->type == DETECT_STREAM_SIZE) {
1781  break;
1782  }
1783  sm = sm->next;
1784  }
1785  }
1786  }
1787  }
1788 
1789  if (s->init_data->smlists[DETECT_SM_LIST_BASE64_DATA] != NULL) {
1790  int list;
1791  uint16_t idx = s->init_data->smlists[DETECT_SM_LIST_BASE64_DATA]->idx;
1792  for (list = 0; list < nlists; list++) {
1793  if (list == DETECT_SM_LIST_POSTMATCH ||
1794  list == DETECT_SM_LIST_TMATCH ||
1795  list == DETECT_SM_LIST_SUPPRESS ||
1796  list == DETECT_SM_LIST_THRESHOLD)
1797  {
1798  continue;
1799  }
1800 
1801  if (list != DETECT_SM_LIST_BASE64_DATA &&
1802  s->init_data->smlists[list] != NULL) {
1803  if (s->init_data->smlists[list]->idx > idx) {
1804  SCLogError(SC_ERR_INVALID_SIGNATURE, "Rule buffer "
1805  "cannot be reset after base64_data.");
1806  SCReturnInt(0);
1807  }
1808  }
1809  }
1810  }
1811 
1812 #ifdef HAVE_LUA
1813  DetectLuaPostSetup(s);
1814 #endif
1815 
1816 #ifdef DEBUG
1817  int i;
1818  for (i = 0; i < nlists; i++) {
1819  if (s->init_data->smlists[i] != NULL) {
1820  for (sm = s->init_data->smlists[i]; sm != NULL; sm = sm->next) {
1821  BUG_ON(sm == sm->prev);
1822  BUG_ON(sm == sm->next);
1823  }
1824  }
1825  }
1826 #endif
1827 
1828  if ((s->flags & SIG_FLAG_FILESTORE) || s->file_flags != 0) {
1829  if (s->alproto != ALPROTO_UNKNOWN &&
1830  !AppLayerParserSupportsFiles(IPPROTO_TCP, s->alproto))
1831  {
1832  SCLogError(SC_ERR_NO_FILES_FOR_PROTOCOL, "protocol %s doesn't "
1833  "support file matching", AppProtoToString(s->alproto));
1834  SCReturnInt(0);
1835  }
1836 
1837  if (s->alproto == ALPROTO_HTTP) {
1839  }
1840  }
1841 
1842  SCReturnInt(1);
1843 }
1844 
1845 /**
1846  * \internal
1847  * \brief Helper function for SigInit().
1848  */
1849 static Signature *SigInitHelper(DetectEngineCtx *de_ctx, const char *sigstr,
1850  uint8_t dir)
1851 {
1852  SignatureParser parser;
1853  memset(&parser, 0x00, sizeof(parser));
1854 
1855  Signature *sig = SigAlloc();
1856  if (sig == NULL)
1857  goto error;
1858 
1859  /* default gid to 1 */
1860  sig->gid = 1;
1861 
1862  int ret = SigParse(de_ctx, sig, sigstr, dir, &parser);
1863  if (ret == -2) {
1864  de_ctx->sigerror_silent = true;
1865  goto error;
1866  } else if (ret < 0) {
1867  goto error;
1868  }
1869 
1870  /* signature priority hasn't been overwritten. Using default priority */
1871  if (sig->prio == -1)
1872  sig->prio = DETECT_DEFAULT_PRIO;
1873 
1874  sig->num = de_ctx->signum;
1875  de_ctx->signum++;
1876 
1877  if (sig->alproto != ALPROTO_UNKNOWN) {
1878  int override_needed = 0;
1879  if (sig->proto.flags & DETECT_PROTO_ANY) {
1880  sig->proto.flags &= ~DETECT_PROTO_ANY;
1881  memset(sig->proto.proto, 0x00, sizeof(sig->proto.proto));
1882  override_needed = 1;
1883  } else {
1884  override_needed = 1;
1885  size_t s = 0;
1886  for (s = 0; s < sizeof(sig->proto.proto); s++) {
1887  if (sig->proto.proto[s] != 0x00) {
1888  override_needed = 0;
1889  break;
1890  }
1891  }
1892  }
1893 
1894  /* at this point if we had alert ip and the ip proto was not
1895  * overridden, we use the ip proto that has been configured
1896  * against the app proto in use. */
1897  if (override_needed)
1899  }
1900 
1901  if (DetectAppLayerEventPrepare(sig) < 0)
1902  goto error;
1903 
1904  /* set the packet and app layer flags, but only if the
1905  * app layer flag wasn't already set in which case we
1906  * only consider the app layer */
1907  if (!(sig->flags & SIG_FLAG_APPLAYER)) {
1908  if (sig->init_data->smlists[DETECT_SM_LIST_MATCH] != NULL) {
1910  for ( ; sm != NULL; sm = sm->next) {
1911  if (sigmatch_table[sm->type].Match != NULL)
1913  }
1914  } else {
1916  }
1917  }
1918 
1919  if (!(sig->init_data->init_flags & SIG_FLAG_INIT_FLOW)) {
1920  if ((sig->flags & (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)) == 0) {
1921  sig->flags |= SIG_FLAG_TOSERVER;
1922  sig->flags |= SIG_FLAG_TOCLIENT;
1923  }
1924  }
1925 
1926  SCLogDebug("sig %"PRIu32" SIG_FLAG_APPLAYER: %s, SIG_FLAG_PACKET: %s",
1927  sig->id, sig->flags & SIG_FLAG_APPLAYER ? "set" : "not set",
1928  sig->init_data->init_flags & SIG_FLAG_INIT_PACKET ? "set" : "not set");
1929 
1930  SigBuildAddressMatchArray(sig);
1931 
1932  /* run buffer type callbacks if any */
1933  for (uint32_t x = 0; x < sig->init_data->smlists_array_size; x++) {
1934  if (sig->init_data->smlists[x])
1935  DetectBufferRunSetupCallback(de_ctx, x, sig);
1936  }
1937 
1938  /* validate signature, SigValidate will report the error reason */
1939  if (SigValidate(de_ctx, sig) == 0) {
1940  goto error;
1941  }
1942 
1943  /* check what the type of this sig is */
1944  SignatureSetType(de_ctx, sig);
1945 
1946  if (sig->flags & SIG_FLAG_IPONLY) {
1947  /* For IPOnly */
1948  if (IPOnlySigParseAddress(de_ctx, sig, parser.src, SIG_DIREC_SRC ^ dir) < 0)
1949  goto error;
1950 
1951  if (IPOnlySigParseAddress(de_ctx, sig, parser.dst, SIG_DIREC_DST ^ dir) < 0)
1952  goto error;
1953  }
1954  return sig;
1955 
1956 error:
1957  if (sig != NULL) {
1958  SigFree(sig);
1959  }
1960  return NULL;
1961 }
1962 
1963 /**
1964  * \brief Checks if a signature has the same source and destination
1965  * \param s parsed signature
1966  *
1967  * \retval true if source and destination are the same, false otherwise
1968  */
1969 static bool SigHasSameSourceAndDestination(const Signature *s)
1970 {
1971  if (!(s->flags & SIG_FLAG_SP_ANY) || !(s->flags & SIG_FLAG_DP_ANY)) {
1972  if (!DetectPortListsAreEqual(s->sp, s->dp)) {
1973  return false;
1974  }
1975  }
1976 
1977  if (!(s->flags & SIG_FLAG_SRC_ANY) || !(s->flags & SIG_FLAG_DST_ANY)) {
1980 
1981  if (!DetectAddressListsAreEqual(src, dst)) {
1982  return false;
1983  }
1984 
1985  src = s->init_data->src->ipv6_head;
1986  dst = s->init_data->dst->ipv6_head;
1987 
1988  if (!DetectAddressListsAreEqual(src, dst)) {
1989  return false;
1990  }
1991  }
1992 
1993  return true;
1994 }
1995 
1996 /**
1997  * \brief Parses a signature and adds it to the Detection Engine Context.
1998  *
1999  * \param de_ctx Pointer to the Detection Engine Context.
2000  * \param sigstr Pointer to a character string containing the signature to be
2001  * parsed.
2002  *
2003  * \retval Pointer to the Signature instance on success; NULL on failure.
2004  */
2005 Signature *SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
2006 {
2007  SCEnter();
2008 
2009  uint32_t oldsignum = de_ctx->signum;
2010  de_ctx->sigerror_silent = false;
2011 
2012  Signature *sig;
2013 
2014  if ((sig = SigInitHelper(de_ctx, sigstr, SIG_DIREC_NORMAL)) == NULL) {
2015  goto error;
2016  }
2017 
2019  if (SigHasSameSourceAndDestination(sig)) {
2020  SCLogInfo("Rule with ID %u is bidirectional, but source and destination are the same, "
2021  "treating the rule as unidirectional", sig->id);
2022 
2024  } else {
2025  sig->next = SigInitHelper(de_ctx, sigstr, SIG_DIREC_SWITCHED);
2026  if (sig->next == NULL) {
2027  goto error;
2028  }
2029  }
2030  }
2031 
2032  SCReturnPtr(sig, "Signature");
2033 
2034 error:
2035  if (sig != NULL) {
2036  SigFree(sig);
2037  }
2038  /* if something failed, restore the old signum count
2039  * since we didn't install it */
2040  de_ctx->signum = oldsignum;
2041 
2042  SCReturnPtr(NULL, "Signature");
2043 }
2044 
2045 /**
2046  * \brief The hash free function to be the used by the hash table -
2047  * DetectEngineCtx->dup_sig_hash_table.
2048  *
2049  * \param data Pointer to the data, in our case SigDuplWrapper to be freed.
2050  */
2051 static void DetectParseDupSigFreeFunc(void *data)
2052 {
2053  if (data != NULL)
2054  SCFree(data);
2055 
2056  return;
2057 }
2058 
2059 /**
2060  * \brief The hash function to be the used by the hash table -
2061  * DetectEngineCtx->dup_sig_hash_table.
2062  *
2063  * \param ht Pointer to the hash table.
2064  * \param data Pointer to the data, in our case SigDuplWrapper.
2065  * \param datalen Not used in our case.
2066  *
2067  * \retval sw->s->id The generated hash value.
2068  */
2069 static uint32_t DetectParseDupSigHashFunc(HashListTable *ht, void *data, uint16_t datalen)
2070 {
2071  SigDuplWrapper *sw = (SigDuplWrapper *)data;
2072 
2073  return (sw->s->id % ht->array_size);
2074 }
2075 
2076 /**
2077  * \brief The Compare function to be used by the hash table -
2078  * DetectEngineCtx->dup_sig_hash_table.
2079  *
2080  * \param data1 Pointer to the first SigDuplWrapper.
2081  * \param len1 Not used.
2082  * \param data2 Pointer to the second SigDuplWrapper.
2083  * \param len2 Not used.
2084  *
2085  * \retval 1 If the 2 SigDuplWrappers sent as args match.
2086  * \retval 0 If the 2 SigDuplWrappers sent as args do not match.
2087  */
2088 static char DetectParseDupSigCompareFunc(void *data1, uint16_t len1, void *data2,
2089  uint16_t len2)
2090 {
2091  SigDuplWrapper *sw1 = (SigDuplWrapper *)data1;
2092  SigDuplWrapper *sw2 = (SigDuplWrapper *)data2;
2093 
2094  if (sw1 == NULL || sw2 == NULL ||
2095  sw1->s == NULL || sw2->s == NULL)
2096  return 0;
2097 
2098  /* sid and gid match required */
2099  if (sw1->s->id == sw2->s->id && sw1->s->gid == sw2->s->gid) return 1;
2100 
2101  return 0;
2102 }
2103 
2104 /**
2105  * \brief Initializes the hash table that is used to cull duplicate sigs.
2106  *
2107  * \param de_ctx Pointer to the detection engine context.
2108  *
2109  * \retval 0 On success.
2110  * \retval -1 On failure.
2111  */
2113 {
2114  de_ctx->dup_sig_hash_table = HashListTableInit(15000,
2115  DetectParseDupSigHashFunc,
2116  DetectParseDupSigCompareFunc,
2117  DetectParseDupSigFreeFunc);
2118  if (de_ctx->dup_sig_hash_table == NULL)
2119  return -1;
2120 
2121  return 0;
2122 }
2123 
2124 /**
2125  * \brief Frees the hash table that is used to cull duplicate sigs.
2126  *
2127  * \param de_ctx Pointer to the detection engine context that holds this table.
2128  */
2130 {
2131  if (de_ctx->dup_sig_hash_table != NULL)
2133 
2134  de_ctx->dup_sig_hash_table = NULL;
2135 
2136  return;
2137 }
2138 
2139 /**
2140  * \brief Check if a signature is a duplicate.
2141  *
2142  * There are 3 types of return values for this function.
2143  *
2144  * - 0, which indicates that the Signature is not a duplicate
2145  * and has to be added to the detection engine list.
2146  * - 1, Signature is duplicate, and the existing signature in
2147  * the list shouldn't be replaced with this duplicate.
2148  * - 2, Signature is duplicate, and the existing signature in
2149  * the list should be replaced with this duplicate.
2150  *
2151  * \param de_ctx Pointer to the detection engine context.
2152  * \param sig Pointer to the Signature that has to be checked.
2153  *
2154  * \retval 2 If Signature is duplicate and the existing signature in
2155  * the list should be chucked out and replaced with this.
2156  * \retval 1 If Signature is duplicate, and should be chucked out.
2157  * \retval 0 If Signature is not a duplicate.
2158  */
2159 static inline int DetectEngineSignatureIsDuplicate(DetectEngineCtx *de_ctx,
2160  Signature *sig)
2161 {
2162  /* we won't do any NULL checks on the args */
2163 
2164  /* return value */
2165  int ret = 0;
2166 
2167  SigDuplWrapper *sw_dup = NULL;
2168  SigDuplWrapper *sw = NULL;
2169 
2170  /* used for making a duplicate_sig_hash_table entry */
2171  sw = SCMalloc(sizeof(SigDuplWrapper));
2172  if (unlikely(sw == NULL)) {
2173  exit(EXIT_FAILURE);
2174  }
2175  memset(sw, 0, sizeof(SigDuplWrapper));
2176  sw->s = sig;
2177 
2178  /* check if we have a duplicate entry for this signature */
2179  sw_dup = HashListTableLookup(de_ctx->dup_sig_hash_table, (void *)sw, 0);
2180  /* we don't have a duplicate entry for this sig */
2181  if (sw_dup == NULL) {
2182  /* add it to the hash table */
2183  HashListTableAdd(de_ctx->dup_sig_hash_table, (void *)sw, 0);
2184 
2185  /* add the s_prev entry for the previously loaded sw in the hash_table */
2186  if (de_ctx->sig_list != NULL) {
2187  SigDuplWrapper *sw_old = NULL;
2188  SigDuplWrapper sw_tmp;
2189  memset(&sw_tmp, 0, sizeof(SigDuplWrapper));
2190 
2191  /* the topmost sig would be the last loaded sig */
2192  sw_tmp.s = de_ctx->sig_list;
2193  sw_old = HashListTableLookup(de_ctx->dup_sig_hash_table,
2194  (void *)&sw_tmp, 0);
2195  /* sw_old == NULL case is impossible */
2196  sw_old->s_prev = sig;
2197  }
2198 
2199  ret = 0;
2200  goto end;
2201  }
2202 
2203  /* if we have reached here we have a duplicate entry for this signature.
2204  * Check the signature revision. Store the signature with the latest rev
2205  * and discard the other one */
2206  if (sw->s->rev <= sw_dup->s->rev) {
2207  ret = 1;
2208  SCFree(sw);
2209  sw = NULL;
2210  goto end;
2211  }
2212 
2213  /* the new sig is of a newer revision than the one that is already in the
2214  * list. Remove the old sig from the list */
2215  if (sw_dup->s_prev == NULL) {
2216  SigDuplWrapper sw_temp;
2217  memset(&sw_temp, 0, sizeof(SigDuplWrapper));
2218  if (sw_dup->s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2219  sw_temp.s = sw_dup->s->next->next;
2220  de_ctx->sig_list = sw_dup->s->next->next;
2221  SigFree(sw_dup->s->next);
2222  } else {
2223  sw_temp.s = sw_dup->s->next;
2224  de_ctx->sig_list = sw_dup->s->next;
2225  }
2226  SigDuplWrapper *sw_next = NULL;
2227  if (sw_temp.s != NULL) {
2228  sw_next = HashListTableLookup(de_ctx->dup_sig_hash_table,
2229  (void *)&sw_temp, 0);
2230  sw_next->s_prev = sw_dup->s_prev;
2231  }
2232  SigFree(sw_dup->s);
2233  } else {
2234  SigDuplWrapper sw_temp;
2235  memset(&sw_temp, 0, sizeof(SigDuplWrapper));
2236  if (sw_dup->s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2237  sw_temp.s = sw_dup->s->next->next;
2238  sw_dup->s_prev->next = sw_dup->s->next->next;
2239  SigFree(sw_dup->s->next);
2240  } else {
2241  sw_temp.s = sw_dup->s->next;
2242  sw_dup->s_prev->next = sw_dup->s->next;
2243  }
2244  SigDuplWrapper *sw_next = NULL;
2245  if (sw_temp.s != NULL) {
2246  sw_next = HashListTableLookup(de_ctx->dup_sig_hash_table,
2247  (void *)&sw_temp, 0);
2248  sw_next->s_prev = sw_dup->s_prev;;
2249  }
2250  SigFree(sw_dup->s);
2251  }
2252 
2253  /* make changes to the entry to reflect the presence of the new sig */
2254  sw_dup->s = sig;
2255  sw_dup->s_prev = NULL;
2256 
2257  if (de_ctx->sig_list != NULL) {
2258  SigDuplWrapper sw_tmp;
2259  memset(&sw_tmp, 0, sizeof(SigDuplWrapper));
2260  sw_tmp.s = de_ctx->sig_list;
2262  (void *)&sw_tmp, 0);
2263  if (sw_old->s != sw_dup->s) {
2264  // Link on top of the list if there was another element
2265  sw_old->s_prev = sig;
2266  }
2267  }
2268 
2269  /* this is duplicate, but a duplicate that replaced the existing sig entry */
2270  ret = 2;
2271 
2272  SCFree(sw);
2273 
2274 end:
2275  return ret;
2276 }
2277 
2278 /**
2279  * \brief Parse and append a Signature into the Detection Engine Context
2280  * signature list.
2281  *
2282  * If the signature is bidirectional it should append two signatures
2283  * (with the addresses switched) into the list. Also handle duplicate
2284  * signatures. In case of duplicate sigs, use the ones that have the
2285  * latest revision. We use the sid and the msg to identifiy duplicate
2286  * sigs. If 2 sigs have the same sid and gid, they are duplicates.
2287  *
2288  * \param de_ctx Pointer to the Detection Engine Context.
2289  * \param sigstr Pointer to a character string containing the signature to be
2290  * parsed.
2291  * \param sig_file Pointer to a character string containing the filename from
2292  * which signature is read
2293  * \param lineno Line number from where signature is read
2294  *
2295  * \retval Pointer to the head Signature in the detection engine ctx sig_list
2296  * on success; NULL on failure.
2297  */
2298 Signature *DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
2299 {
2300  Signature *sig = SigInit(de_ctx, sigstr);
2301  if (sig == NULL) {
2302  return NULL;
2303  }
2304 
2305  /* checking for the status of duplicate signature */
2306  int dup_sig = DetectEngineSignatureIsDuplicate(de_ctx, sig);
2307  /* a duplicate signature that should be chucked out. Check the previously
2308  * called function details to understand the different return values */
2309  if (dup_sig == 1) {
2310  SCLogError(SC_ERR_DUPLICATE_SIG, "Duplicate signature \"%s\"", sigstr);
2311  goto error;
2312  } else if (dup_sig == 2) {
2313  SCLogWarning(SC_ERR_DUPLICATE_SIG, "Signature with newer revision,"
2314  " so the older sig replaced by this new signature \"%s\"",
2315  sigstr);
2316  }
2317 
2319  if (sig->next != NULL) {
2320  sig->next->next = de_ctx->sig_list;
2321  } else {
2322  goto error;
2323  }
2324  } else {
2325  /* if this sig is the first one, sig_list should be null */
2326  sig->next = de_ctx->sig_list;
2327  }
2328 
2329  de_ctx->sig_list = sig;
2330 
2331  /**
2332  * In DetectEngineAppendSig(), the signatures are prepended and we always return the first one
2333  * so if the signature is bidirectional, the returned sig will point through "next" ptr
2334  * to the cloned signatures with the switched addresses
2335  */
2336  return (dup_sig == 0 || dup_sig == 2) ? sig : NULL;
2337 
2338 error:
2339  if (sig != NULL)
2340  SigFree(sig);
2341  return NULL;
2342 }
2343 
2344 typedef struct DetectParseRegex_ {
2345  pcre *regex;
2346  pcre_extra *study;
2349 
2350 static DetectParseRegex *g_detect_parse_regex_list = NULL;
2351 
2353 {
2354  DetectParseRegex *r = g_detect_parse_regex_list;
2355  while (r) {
2356  DetectParseRegex *next = r->next;
2357 
2358  if (r->regex) {
2359  pcre_free(r->regex);
2360  }
2361  if (r->study) {
2362  pcre_free_study(r->study);
2363  }
2364  SCFree(r);
2365  r = next;
2366  }
2367  g_detect_parse_regex_list = NULL;
2368 }
2369 
2370 /** \brief add regex and/or study to at exit free list
2371  */
2373 {
2374  DetectParseRegex *r = SCCalloc(1, sizeof(*r));
2375  if (r == NULL) {
2376  FatalError(SC_ERR_MEM_ALLOC, "failed to alloc memory for pcre free list");
2377  }
2378  r->regex = regex;
2379  r->study = study;
2380  r->next = g_detect_parse_regex_list;
2381  g_detect_parse_regex_list = r;
2382 }
2383 
2384 void DetectSetupParseRegexes(const char *parse_str,
2385  pcre **parse_regex,
2386  pcre_extra **parse_regex_study)
2387 {
2388  const char *eb;
2389  int eo;
2390  int opts = 0;
2391 
2392  *parse_regex = pcre_compile(parse_str, opts, &eb, &eo, NULL);
2393  if (*parse_regex == NULL) {
2394  FatalError(SC_ERR_PCRE_COMPILE, "pcre compile of \"%s\" failed at "
2395  "offset %" PRId32 ": %s", parse_str, eo, eb);
2396  }
2397 
2398  *parse_regex_study = pcre_study(*parse_regex, 0, &eb);
2399  if (eb != NULL) {
2400  FatalError(SC_ERR_PCRE_STUDY, "pcre study failed: %s", eb);
2401  }
2402 
2403  DetectParseRegexAddToFreeList(*parse_regex, *parse_regex_study);
2404  return;
2405 }
2406 
2407 #ifdef AFLFUZZ_RULES
2408 #include "util-reference-config.h"
2409 int RuleParseDataFromFile(char *filename)
2410 {
2411  char buffer[65536];
2412 
2413  SigTableSetup();
2415  SCClassConfInit();
2416 
2418  if (de_ctx == NULL)
2419  return 0;
2420 
2421 #ifdef AFLFUZZ_PERSISTANT_MODE
2422  while (__AFL_LOOP(10000)) {
2423  /* reset state */
2424  memset(buffer, 0, sizeof(buffer));
2425 #endif /* AFLFUZZ_PERSISTANT_MODE */
2426 
2427  FILE *fp = fopen(filename, "r");
2428  BUG_ON(fp == NULL);
2429 
2430  size_t result = fread(&buffer, 1, sizeof(buffer), fp);
2431  if (result < sizeof(buffer)) {
2432  buffer[result] = '\0';
2433  Signature *s = SigInit(de_ctx, buffer);
2434  if (s != NULL) {
2435  SigFree(s);
2436  }
2437  }
2438  fclose(fp);
2439 
2440 #ifdef AFLFUZZ_PERSISTANT_MODE
2441  }
2442 #endif /* AFLFUZZ_PERSISTANT_MODE */
2443 
2444  DetectEngineCtxFree(de_ctx);
2447  return 0;
2448 }
2449 #endif /* AFLFUZZ_RULES */
2450 
2451 /*
2452  * TESTS
2453  */
2454 
2455 #ifdef UNITTESTS
2456 static int SigParseTest01 (void)
2457 {
2458  int result = 1;
2459  Signature *sig = NULL;
2460 
2462  if (de_ctx == NULL)
2463  goto end;
2464 
2465  sig = SigInit(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1;)");
2466  if (sig == NULL)
2467  result = 0;
2468 
2469 end:
2470  if (sig != NULL) SigFree(sig);
2471  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2472  return result;
2473 }
2474 
2475 static int SigParseTest02 (void)
2476 {
2477  int result = 0;
2478  Signature *sig = NULL;
2479  DetectPort *port = NULL;
2480 
2482 
2483  if (de_ctx == NULL)
2484  goto end;
2485 
2488 
2489  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;)");
2490  if (sig == NULL) {
2491  goto end;
2492  }
2493 
2494  int r = DetectPortParse(de_ctx, &port, "0:20");
2495  if (r < 0)
2496  goto end;
2497 
2498  if (DetectPortCmp(sig->sp, port) == PORT_EQ) {
2499  result = 1;
2500  } else {
2501  DetectPortPrint(port); printf(" != "); DetectPortPrint(sig->sp); printf(": ");
2502  }
2503 
2504 end:
2505  if (port != NULL)
2506  DetectPortCleanupList(de_ctx, port);
2507  if (sig != NULL)
2508  SigFree(sig);
2509  if (de_ctx != NULL)
2510  DetectEngineCtxFree(de_ctx);
2511  return result;
2512 }
2513 
2514 /**
2515  * \test SigParseTest03 test for invalid direction operator in rule
2516  */
2517 static int SigParseTest03 (void)
2518 {
2519  int result = 1;
2520  Signature *sig = NULL;
2521 
2523  if (de_ctx == NULL)
2524  goto end;
2525 
2526  sig = SigInit(de_ctx, "alert tcp 1.2.3.4 any <- !1.2.3.4 any (msg:\"SigParseTest03\"; sid:1;)");
2527  if (sig != NULL) {
2528  result = 0;
2529  printf("expected NULL got sig ptr %p: ",sig);
2530  }
2531 
2532 end:
2533  if (sig != NULL) SigFree(sig);
2534  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2535  return result;
2536 }
2537 
2538 static int SigParseTest04 (void)
2539 {
2540  int result = 1;
2541  Signature *sig = NULL;
2542 
2544  if (de_ctx == NULL)
2545  goto end;
2546 
2547  sig = SigInit(de_ctx, "alert tcp 1.2.3.4 1024: -> !1.2.3.4 1024: (msg:\"SigParseTest04\"; sid:1;)");
2548  if (sig == NULL)
2549  result = 0;
2550 
2551 end:
2552  if (sig != NULL) SigFree(sig);
2553  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2554  return result;
2555 }
2556 
2557 /** \test Port validation */
2558 static int SigParseTest05 (void)
2559 {
2560  int result = 0;
2561  Signature *sig = NULL;
2562 
2564  if (de_ctx == NULL)
2565  goto end;
2566 
2567  sig = SigInit(de_ctx, "alert tcp 1.2.3.4 1024:65536 -> !1.2.3.4 any (msg:\"SigParseTest05\"; sid:1;)");
2568  if (sig == NULL) {
2569  result = 1;
2570  } else {
2571  printf("signature didn't fail to parse as we expected: ");
2572  }
2573 
2574 end:
2575  if (sig != NULL) SigFree(sig);
2576  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2577  return result;
2578 }
2579 
2580 /** \test Parsing bug debugging at 2010-03-18 */
2581 static int SigParseTest06 (void)
2582 {
2583  int result = 0;
2584  Signature *sig = NULL;
2585 
2587  if (de_ctx == NULL)
2588  goto end;
2589 
2590  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;)");
2591  if (sig != NULL) {
2592  result = 1;
2593  } else {
2594  printf("signature failed to parse: ");
2595  }
2596 
2597 end:
2598  if (sig != NULL)
2599  SigFree(sig);
2600  if (de_ctx != NULL)
2601  DetectEngineCtxFree(de_ctx);
2602  return result;
2603 }
2604 
2605 /**
2606  * \test Parsing duplicate sigs.
2607  */
2608 static int SigParseTest07(void)
2609 {
2610  int result = 0;
2611 
2613  if (de_ctx == NULL)
2614  goto end;
2615 
2616  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2617  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2618 
2619  result = (de_ctx->sig_list != NULL && de_ctx->sig_list->next == NULL);
2620 
2621 end:
2622  if (de_ctx != NULL)
2623  DetectEngineCtxFree(de_ctx);
2624  return result;
2625 }
2626 
2627 /**
2628  * \test Parsing duplicate sigs.
2629  */
2630 static int SigParseTest08(void)
2631 {
2632  int result = 0;
2633 
2635  if (de_ctx == NULL)
2636  goto end;
2637 
2638  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2639  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:2;)");
2640 
2641  result = (de_ctx->sig_list != NULL && de_ctx->sig_list->next == NULL &&
2642  de_ctx->sig_list->rev == 2);
2643 
2644 end:
2645  if (de_ctx != NULL)
2646  DetectEngineCtxFree(de_ctx);
2647  return result;
2648 }
2649 
2650 /**
2651  * \test Parsing duplicate sigs.
2652  */
2653 static int SigParseTest09(void)
2654 {
2655  int result = 1;
2656 
2658  if (de_ctx == NULL)
2659  goto end;
2660 
2661  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2662  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:2;)");
2663  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:6;)");
2664  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:4;)");
2665  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:2;)");
2666  result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
2667  de_ctx->sig_list->rev == 2);
2668  if (result == 0)
2669  goto end;
2670  result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
2671  de_ctx->sig_list->next->rev == 6);
2672  if (result == 0)
2673  goto end;
2674 
2675  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:1;)");
2676  result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
2677  de_ctx->sig_list->rev == 2);
2678  if (result == 0)
2679  goto end;
2680  result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
2681  de_ctx->sig_list->next->rev == 6);
2682  if (result == 0)
2683  goto end;
2684 
2685  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:4;)");
2686  result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
2687  de_ctx->sig_list->rev == 4);
2688  if (result == 0)
2689  goto end;
2690  result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
2691  de_ctx->sig_list->next->rev == 6);
2692  if (result == 0)
2693  goto end;
2694 
2695 end:
2696  if (de_ctx != NULL)
2697  DetectEngineCtxFree(de_ctx);
2698  return result;
2699 }
2700 
2701 /**
2702  * \test Parsing duplicate sigs.
2703  */
2704 static int SigParseTest10(void)
2705 {
2706  int result = 1;
2707 
2709  if (de_ctx == NULL)
2710  goto end;
2711 
2712  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2713  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:1;)");
2714  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:3; rev:1;)");
2715  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:4; rev:1;)");
2716  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:5; rev:1;)");
2717  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:3; rev:2;)");
2718  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:2;)");
2719 
2720  result &= ((de_ctx->sig_list->id == 2) &&
2721  (de_ctx->sig_list->next->id == 3) &&
2722  (de_ctx->sig_list->next->next->id == 5) &&
2723  (de_ctx->sig_list->next->next->next->id == 4) &&
2724  (de_ctx->sig_list->next->next->next->next->id == 1));
2725 
2726 end:
2727  if (de_ctx != NULL)
2728  DetectEngineCtxFree(de_ctx);
2729  return result;
2730 }
2731 
2732 /**
2733  * \test Parsing sig with trailing space(s) as reported by
2734  * Morgan Cox on oisf-users.
2735  */
2736 static int SigParseTest11(void)
2737 {
2738  int result = 0;
2739 
2741  if (de_ctx == NULL)
2742  goto end;
2743 
2744  Signature *s = NULL;
2745 
2746  s = DetectEngineAppendSig(de_ctx, "drop tcp any any -> any 80 (msg:\"Snort_Inline is blocking the http link\";) ");
2747  if (s == NULL) {
2748  printf("sig 1 didn't parse: ");
2749  goto end;
2750  }
2751 
2752  s = DetectEngineAppendSig(de_ctx, "drop tcp any any -> any 80 (msg:\"Snort_Inline is blocking the http link\"; sid:1;) ");
2753  if (s == NULL) {
2754  printf("sig 2 didn't parse: ");
2755  goto end;
2756  }
2757 
2758  result = 1;
2759 end:
2760  if (de_ctx != NULL)
2761  DetectEngineCtxFree(de_ctx);
2762  return result;
2763 }
2764 
2765 /**
2766  * \test file_data with rawbytes
2767  */
2768 static int SigParseTest12(void)
2769 {
2770  int result = 0;
2771 
2773  if (de_ctx == NULL)
2774  goto end;
2775 
2776  Signature *s = NULL;
2777 
2778  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (file_data; content:\"abc\"; rawbytes; sid:1;)");
2779  if (s != NULL) {
2780  printf("sig 1 should have given an error: ");
2781  goto end;
2782  }
2783 
2784  result = 1;
2785 end:
2786  if (de_ctx != NULL)
2787  DetectEngineCtxFree(de_ctx);
2788  return result;
2789 }
2790 
2791 /**
2792  * \test packet/stream sig
2793  */
2794 static int SigParseTest13(void)
2795 {
2796  int result = 0;
2797 
2799  if (de_ctx == NULL)
2800  goto end;
2801 
2802  Signature *s = NULL;
2803 
2804  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; sid:1;)");
2805  if (s == NULL) {
2806  printf("sig 1 invalidated: failure");
2807  goto end;
2808  }
2809 
2810  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
2811  printf("sig doesn't have stream flag set\n");
2812  goto end;
2813  }
2814 
2815  if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
2816  printf("sig has packet flag set\n");
2817  goto end;
2818  }
2819 
2820  result = 1;
2821 
2822 end:
2823  if (de_ctx != NULL)
2824  DetectEngineCtxFree(de_ctx);
2825  return result;
2826 }
2827 
2828 /**
2829  * \test packet/stream sig
2830  */
2831 static int SigParseTest14(void)
2832 {
2833  int result = 0;
2834 
2836  if (de_ctx == NULL)
2837  goto end;
2838 
2839  Signature *s = NULL;
2840 
2841  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; dsize:>0; sid:1;)");
2842  if (s == NULL) {
2843  printf("sig 1 invalidated: failure");
2844  goto end;
2845  }
2846 
2847  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
2848  printf("sig doesn't have packet flag set\n");
2849  goto end;
2850  }
2851 
2852  if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
2853  printf("sig has stream flag set\n");
2854  goto end;
2855  }
2856 
2857  result = 1;
2858 
2859 end:
2860  if (de_ctx != NULL)
2861  DetectEngineCtxFree(de_ctx);
2862  return result;
2863 }
2864 
2865 /**
2866  * \test packet/stream sig
2867  */
2868 static int SigParseTest15(void)
2869 {
2870  int result = 0;
2871 
2873  if (de_ctx == NULL)
2874  goto end;
2875 
2876  Signature *s = NULL;
2877 
2878  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:5; sid:1;)");
2879  if (s == NULL) {
2880  printf("sig 1 invalidated: failure");
2881  goto end;
2882  }
2883 
2884  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
2885  printf("sig doesn't have packet flag set\n");
2886  goto end;
2887  }
2888 
2889  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
2890  printf("sig doesn't have stream flag set\n");
2891  goto end;
2892  }
2893 
2894  result = 1;
2895 
2896 end:
2897  if (de_ctx != NULL)
2898  DetectEngineCtxFree(de_ctx);
2899  return result;
2900 }
2901 
2902 /**
2903  * \test packet/stream sig
2904  */
2905 static int SigParseTest16(void)
2906 {
2907  int result = 0;
2908 
2910  if (de_ctx == NULL)
2911  goto end;
2912 
2913  Signature *s = NULL;
2914 
2915  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; depth:5; sid:1;)");
2916  if (s == NULL) {
2917  printf("sig 1 invalidated: failure");
2918  goto end;
2919  }
2920 
2921  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
2922  printf("sig doesn't have packet flag set\n");
2923  goto end;
2924  }
2925 
2926  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
2927  printf("sig doesn't have stream flag set\n");
2928  goto end;
2929  }
2930 
2931  result = 1;
2932 
2933 end:
2934  if (de_ctx != NULL)
2935  DetectEngineCtxFree(de_ctx);
2936  return result;
2937 }
2938 
2939 /**
2940  * \test packet/stream sig
2941  */
2942 static int SigParseTest17(void)
2943 {
2944  int result = 0;
2945 
2947  if (de_ctx == NULL)
2948  goto end;
2949 
2950  Signature *s = NULL;
2951 
2952  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:1; depth:5; sid:1;)");
2953  if (s == NULL) {
2954  printf("sig 1 invalidated: failure");
2955  goto end;
2956  }
2957 
2958  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
2959  printf("sig doesn't have packet flag set\n");
2960  goto end;
2961  }
2962 
2963  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
2964  printf("sig doesn't have stream flag set\n");
2965  goto end;
2966  }
2967 
2968  result = 1;
2969 
2970 end:
2971  if (de_ctx != NULL)
2972  DetectEngineCtxFree(de_ctx);
2973  return result;
2974 }
2975 
2976 /** \test sid value too large. Bug #779 */
2977 static int SigParseTest18 (void)
2978 {
2979  int result = 0;
2980 
2982  if (de_ctx == NULL)
2983  goto end;
2984 
2985  if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:99999999999999999999;)") != NULL)
2986  goto end;
2987 
2988  result = 1;
2989 end:
2990  if (de_ctx != NULL)
2991  DetectEngineCtxFree(de_ctx);
2992  return result;
2993 }
2994 
2995 /** \test gid value too large. Related to bug #779 */
2996 static int SigParseTest19 (void)
2997 {
2998  int result = 0;
2999 
3001  if (de_ctx == NULL)
3002  goto end;
3003 
3004  if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1; gid:99999999999999999999;)") != NULL)
3005  goto end;
3006 
3007  result = 1;
3008 end:
3009  if (de_ctx != NULL)
3010  DetectEngineCtxFree(de_ctx);
3011  return result;
3012 }
3013 
3014 /** \test rev value too large. Related to bug #779 */
3015 static int SigParseTest20 (void)
3016 {
3017  int result = 0;
3018 
3020  if (de_ctx == NULL)
3021  goto end;
3022 
3023  if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1; rev:99999999999999999999;)") != NULL)
3024  goto end;
3025 
3026  result = 1;
3027 end:
3028  if (de_ctx != NULL)
3029  DetectEngineCtxFree(de_ctx);
3030  return result;
3031 }
3032 
3033 /** \test address parsing */
3034 static int SigParseTest21 (void)
3035 {
3036  int result = 0;
3037 
3039  if (de_ctx == NULL)
3040  goto end;
3041 
3042  if (DetectEngineAppendSig(de_ctx, "alert tcp [1.2.3.4, 1.2.3.5] any -> !1.2.3.4 any (sid:1;)") == NULL)
3043  goto end;
3044 
3045  result = 1;
3046 end:
3047  if (de_ctx != NULL)
3048  DetectEngineCtxFree(de_ctx);
3049  return result;
3050 }
3051 
3052 /** \test address parsing */
3053 static int SigParseTest22 (void)
3054 {
3055  int result = 0;
3056 
3058  if (de_ctx == NULL)
3059  goto end;
3060 
3061  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)
3062  goto end;
3063 
3064  result = 1;
3065 end:
3066  if (de_ctx != NULL)
3067  DetectEngineCtxFree(de_ctx);
3068  return result;
3069 }
3070 
3071 /**
3072  * \test rule ending in carriage return
3073  */
3074 static int SigParseTest23(void)
3075 {
3077  FAIL_IF_NULL(de_ctx);
3078 
3079  Signature *s = NULL;
3080 
3081  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:1; depth:5; sid:1;)\r");
3082  FAIL_IF_NULL(s);
3083 
3084  DetectEngineCtxFree(de_ctx);
3085  PASS;
3086 }
3087 
3088 /** \test Direction operator validation (invalid) */
3089 static int SigParseBidirecTest06 (void)
3090 {
3091  int result = 1;
3092  Signature *sig = NULL;
3093 
3095  if (de_ctx == NULL)
3096  goto end;
3097 
3098  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any - 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3099  if (sig == NULL)
3100  result = 1;
3101 
3102 end:
3103  if (sig != NULL) SigFree(sig);
3104  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3105  return result;
3106 }
3107 
3108 /** \test Direction operator validation (invalid) */
3109 static int SigParseBidirecTest07 (void)
3110 {
3111  int result = 1;
3112  Signature *sig = NULL;
3113 
3115  if (de_ctx == NULL)
3116  goto end;
3117 
3118  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <- 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3119  if (sig == NULL)
3120  result = 1;
3121 
3122 end:
3123  if (sig != NULL) SigFree(sig);
3124  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3125  return result;
3126 }
3127 
3128 /** \test Direction operator validation (invalid) */
3129 static int SigParseBidirecTest08 (void)
3130 {
3131  int result = 1;
3132  Signature *sig = NULL;
3133 
3135  if (de_ctx == NULL)
3136  goto end;
3137 
3138  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any < 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3139  if (sig == NULL)
3140  result = 1;
3141 
3142 end:
3143  if (sig != NULL) SigFree(sig);
3144  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3145  return result;
3146 }
3147 
3148 /** \test Direction operator validation (invalid) */
3149 static int SigParseBidirecTest09 (void)
3150 {
3151  int result = 1;
3152  Signature *sig = NULL;
3153 
3155  if (de_ctx == NULL)
3156  goto end;
3157 
3158  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any > 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3159  if (sig == NULL)
3160  result = 1;
3161 
3162 end:
3163  if (sig != NULL) SigFree(sig);
3164  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3165  return result;
3166 }
3167 
3168 /** \test Direction operator validation (invalid) */
3169 static int SigParseBidirecTest10 (void)
3170 {
3171  int result = 1;
3172  Signature *sig = NULL;
3173 
3175  if (de_ctx == NULL)
3176  goto end;
3177 
3178  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -< 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3179  if (sig == NULL)
3180  result = 1;
3181 
3182 end:
3183  if (sig != NULL) SigFree(sig);
3184  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3185  return result;
3186 }
3187 
3188 /** \test Direction operator validation (invalid) */
3189 static int SigParseBidirecTest11 (void)
3190 {
3191  int result = 1;
3192  Signature *sig = NULL;
3193 
3195  if (de_ctx == NULL)
3196  goto end;
3197 
3198  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any >- 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3199  if (sig == NULL)
3200  result = 1;
3201 
3202 end:
3203  if (sig != NULL) SigFree(sig);
3204  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3205  return result;
3206 }
3207 
3208 /** \test Direction operator validation (invalid) */
3209 static int SigParseBidirecTest12 (void)
3210 {
3211  int result = 1;
3212  Signature *sig = NULL;
3213 
3215  if (de_ctx == NULL)
3216  goto end;
3217 
3218  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any >< 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3219  if (sig == NULL)
3220  result = 1;
3221 
3222 end:
3223  if (sig != NULL) SigFree(sig);
3224  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3225  return result;
3226 }
3227 
3228 /** \test Direction operator validation (valid) */
3229 static int SigParseBidirecTest13 (void)
3230 {
3231  int result = 1;
3232  Signature *sig = NULL;
3233 
3235  if (de_ctx == NULL)
3236  goto end;
3237 
3238  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <> 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3239  if (sig != NULL)
3240  result = 1;
3241 
3242 end:
3243  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3244  return result;
3245 }
3246 
3247 /** \test Direction operator validation (valid) */
3248 static int SigParseBidirecTest14 (void)
3249 {
3250  int result = 1;
3251  Signature *sig = NULL;
3252 
3254  if (de_ctx == NULL)
3255  goto end;
3256 
3257  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3258  if (sig != NULL)
3259  result = 1;
3260 
3261 end:
3262  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3263  return result;
3264 }
3265 
3266 /** \test Ensure that we don't set bidirectional in a
3267  * normal (one direction) Signature
3268  */
3269 static int SigTestBidirec01 (void)
3270 {
3271  Signature *sig = NULL;
3272  int result = 0;
3273 
3275  if (de_ctx == NULL)
3276  goto end;
3277 
3278  sig = DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 1024:65535 -> !1.2.3.4 any (msg:\"SigTestBidirec01\"; sid:1;)");
3279  if (sig == NULL)
3280  goto end;
3281  if (sig->next != NULL)
3282  goto end;
3284  goto end;
3285  if (de_ctx->signum != 1)
3286  goto end;
3287 
3288  result = 1;
3289 
3290 end:
3291  if (de_ctx != NULL) {
3292  SigCleanSignatures(de_ctx);
3293  SigGroupCleanup(de_ctx);
3294  DetectEngineCtxFree(de_ctx);
3295  }
3296  return result;
3297 }
3298 
3299 /** \test Ensure that we set a bidirectional Signature correctly */
3300 static int SigTestBidirec02 (void)
3301 {
3302  int result = 0;
3303  Signature *sig = NULL;
3304  Signature *copy = NULL;
3305 
3307  if (de_ctx == NULL)
3308  goto end;
3309 
3310  de_ctx->flags |= DE_QUIET;
3311 
3312  sig = DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 1024:65535 <> !1.2.3.4 any (msg:\"SigTestBidirec02\"; sid:1;)");
3313  if (sig == NULL)
3314  goto end;
3315  if (de_ctx->sig_list != sig)
3316  goto end;
3318  goto end;
3319  if (sig->next == NULL)
3320  goto end;
3321  if (de_ctx->signum != 2)
3322  goto end;
3323  copy = sig->next;
3324  if (copy->next != NULL)
3325  goto end;
3326  if (!(copy->init_data->init_flags & SIG_FLAG_INIT_BIDIREC))
3327  goto end;
3328 
3329  result = 1;
3330 
3331 end:
3332  if (de_ctx != NULL) {
3333  SigCleanSignatures(de_ctx);
3334  SigGroupCleanup(de_ctx);
3335  DetectEngineCtxFree(de_ctx);
3336  }
3337 
3338  return result;
3339 }
3340 
3341 /** \test Ensure that we set a bidirectional Signature correctly
3342 * and we install it with the rest of the signatures, checking
3343 * also that it match with the correct addr directions
3344 */
3345 static int SigTestBidirec03 (void)
3346 {
3347  int result = 0;
3348  Signature *sig = NULL;
3349  Packet *p = NULL;
3350 
3352  if (de_ctx == NULL)
3353  goto end;
3354 
3355  de_ctx->flags |= DE_QUIET;
3356 
3357  const char *sigs[3];
3358  sigs[0] = "alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 1\"; sid:1;)";
3359  sigs[1] = "alert tcp any any <> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)";
3360  sigs[2] = "alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 3\"; sid:3;)";
3361  UTHAppendSigs(de_ctx, sigs, 3);
3362 
3363  /* Checking that bidirectional rules are set correctly */
3364  sig = de_ctx->sig_list;
3365  if (sig == NULL)
3366  goto end;
3367  if (sig->next == NULL)
3368  goto end;
3369  if (sig->next->next == NULL)
3370  goto end;
3371  if (sig->next->next->next == NULL)
3372  goto end;
3373  if (sig->next->next->next->next != NULL)
3374  goto end;
3375  if (de_ctx->signum != 4)
3376  goto end;
3377 
3378  uint8_t rawpkt1_ether[] = {
3379  0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
3380  0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
3381  0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
3382  0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
3383  0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
3384  0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
3385  0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
3386  0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
3387  0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
3388  0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
3389  0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
3390  0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
3391  0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
3392  0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
3393  0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
3394  0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
3395  0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
3396  0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
3397  0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
3398  0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
3399  0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
3400  0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
3401  0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
3402  0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
3403  0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
3404  0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
3405  0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
3406  0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
3407  0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
3408  0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
3409  0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
3410  0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
3411  0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
3412  0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
3413  0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3414  0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3415  0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
3416  0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
3417  0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
3418  0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
3419  0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
3420  0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
3421  0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
3422  0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3423  0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
3424  0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
3425  0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
3426  0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
3427  0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3428  0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
3429  0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
3430  0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
3431  0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
3432  0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
3433  0x76,0x65,0x0d,0x0a,0x0d,0x0a }; /* end rawpkt1_ether */
3434 
3436  p = UTHBuildPacketFromEth(rawpkt1_ether, sizeof(rawpkt1_ether));
3437  if (p == NULL) {
3438  SCLogDebug("Error building packet");
3439  goto end;
3440  }
3441  UTHMatchPackets(de_ctx, &p, 1);
3442 
3443  uint32_t sids[3] = {1, 2, 3};
3444  uint32_t results[3] = {1, 1, 1};
3445  result = UTHCheckPacketMatchResults(p, sids, results, 1);
3446 
3447 end:
3448  if (p != NULL) {
3449  PACKET_RECYCLE(p);
3450  SCFree(p);
3451  }
3452  if (de_ctx != NULL) {
3453  SigCleanSignatures(de_ctx);
3454  SigGroupCleanup(de_ctx);
3455  DetectEngineCtxFree(de_ctx);
3456  }
3457  FlowShutdown();
3458 
3459  return result;
3460 }
3461 
3462 /** \test Ensure that we set a bidirectional Signature correctly
3463 * and we install it with the rest of the signatures, checking
3464 * also that it match with the correct addr directions
3465 */
3466 static int SigTestBidirec04 (void)
3467 {
3468  int result = 0;
3469  Signature *sig = NULL;
3470  Packet *p = NULL;
3471 
3473  if (de_ctx == NULL)
3474  goto end;
3475 
3476  de_ctx->flags |= DE_QUIET;
3477 
3478  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> any any (msg:\"SigTestBidirec03 sid 1\"; sid:1;)");
3479  if (sig == NULL)
3480  goto end;
3481  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <> any any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)");
3482  if (sig == NULL)
3483  goto end;
3484  if ( !(sig->init_data->init_flags & SIG_FLAG_INIT_BIDIREC))
3485  goto end;
3486  if (sig->next == NULL)
3487  goto end;
3488  if (sig->next->next == NULL)
3489  goto end;
3490  if (sig->next->next->next != NULL)
3491  goto end;
3492  if (de_ctx->signum != 3)
3493  goto end;
3494 
3495  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> any any (msg:\"SigTestBidirec03 sid 3\"; sid:3;)");
3496  if (sig == NULL)
3497  goto end;
3498  if (sig->next == NULL)
3499  goto end;
3500  if (sig->next->next == NULL)
3501  goto end;
3502  if (sig->next->next->next == NULL)
3503  goto end;
3504  if (sig->next->next->next->next != NULL)
3505  goto end;
3506  if (de_ctx->signum != 4)
3507  goto end;
3508 
3509  uint8_t rawpkt1_ether[] = {
3510  0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
3511  0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
3512  0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
3513  0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
3514  0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
3515  0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
3516  0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
3517  0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
3518  0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
3519  0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
3520  0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
3521  0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
3522  0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
3523  0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
3524  0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
3525  0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
3526  0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
3527  0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
3528  0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
3529  0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
3530  0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
3531  0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
3532  0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
3533  0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
3534  0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
3535  0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
3536  0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
3537  0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
3538  0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
3539  0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
3540  0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
3541  0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
3542  0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
3543  0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
3544  0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3545  0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3546  0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
3547  0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
3548  0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
3549  0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
3550  0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
3551  0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
3552  0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
3553  0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3554  0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
3555  0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
3556  0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
3557  0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
3558  0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3559  0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
3560  0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
3561  0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
3562  0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
3563  0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
3564  0x76,0x65,0x0d,0x0a,0x0d,0x0a }; /* end rawpkt1_ether */
3565 
3566  p = SCMalloc(SIZE_OF_PACKET);
3567  if (unlikely(p == NULL))
3568  return 0;
3569  DecodeThreadVars dtv;
3570  ThreadVars th_v;
3571  DetectEngineThreadCtx *det_ctx;
3572 
3573  memset(&th_v, 0, sizeof(th_v));
3574  memset(p, 0, SIZE_OF_PACKET);
3575 
3577  DecodeEthernet(&th_v, &dtv, p, rawpkt1_ether, sizeof(rawpkt1_ether), NULL);
3578  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
3579 
3580  /* At this point we have a list of 4 signatures. The last one
3581  is a copy of the second one. If we receive a packet
3582  with source 192.168.1.1 80, all the sids should match */
3583 
3584  SigGroupBuild(de_ctx);
3585  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3586 
3587  /* only sid 2 should match with a packet going to 192.168.1.1 port 80 */
3588  if (PacketAlertCheck(p, 1) <= 0 && PacketAlertCheck(p, 3) <= 0 &&
3589  PacketAlertCheck(p, 2) == 1) {
3590  result = 1;
3591  }
3592 
3593  if (p != NULL) {
3594  PACKET_RECYCLE(p);
3595  }
3596  FlowShutdown();
3597  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
3598 
3599 end:
3600  if (de_ctx != NULL) {
3601  SigCleanSignatures(de_ctx);
3602  SigGroupCleanup(de_ctx);
3603  DetectEngineCtxFree(de_ctx);
3604  }
3605 
3606  if (p != NULL)
3607  SCFree(p);
3608  return result;
3609 }
3610 
3611 /**
3612  * \test check that we don't allow invalid negation options
3613  */
3614 static int SigParseTestNegation01 (void)
3615 {
3616  int result = 0;
3617  DetectEngineCtx *de_ctx;
3618  Signature *s=NULL;
3619 
3620  de_ctx = DetectEngineCtxInit();
3621  if (de_ctx == NULL)
3622  goto end;
3623  de_ctx->flags |= DE_QUIET;
3624 
3625  s = SigInit(de_ctx,"alert tcp !any any -> any any (msg:\"SigTest41-01 src address is !any \"; classtype:misc-activity; sid:410001; rev:1;)");
3626  if (s != NULL) {
3627  SigFree(s);
3628  goto end;
3629  }
3630 
3631  result = 1;
3632 end:
3633  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3634  return result;
3635 }
3636 
3637 /**
3638  * \test check that we don't allow invalid negation options
3639  */
3640 static int SigParseTestNegation02 (void)
3641 {
3642  int result = 0;
3643  DetectEngineCtx *de_ctx;
3644  Signature *s=NULL;
3645 
3646  de_ctx = DetectEngineCtxInit();
3647  if (de_ctx == NULL)
3648  goto end;
3649  de_ctx->flags |= DE_QUIET;
3650 
3651  s = SigInit(de_ctx,"alert tcp any !any -> any any (msg:\"SigTest41-02 src ip is !any \"; classtype:misc-activity; sid:410002; rev:1;)");
3652  if (s != NULL) {
3653  SigFree(s);
3654  goto end;
3655  }
3656 
3657  result = 1;
3658 end:
3659  if (de_ctx != NULL)
3660  DetectEngineCtxFree(de_ctx);
3661  return result;
3662 }
3663 /**
3664  * \test check that we don't allow invalid negation options
3665  */
3666 static int SigParseTestNegation03 (void)
3667 {
3668  int result = 0;
3669  DetectEngineCtx *de_ctx;
3670  Signature *s=NULL;
3671 
3672  de_ctx = DetectEngineCtxInit();
3673  if (de_ctx == NULL)
3674  goto end;
3675  de_ctx->flags |= DE_QUIET;
3676 
3677  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;)");
3678  if (s != NULL) {
3679  SigFree(s);
3680  goto end;
3681  }
3682 
3683  result = 1;
3684 end:
3685  if (de_ctx != NULL)
3686  DetectEngineCtxFree(de_ctx);
3687  return result;
3688 }
3689 /**
3690  * \test check that we don't allow invalid negation options
3691  */
3692 static int SigParseTestNegation04 (void)
3693 {
3694  int result = 0;
3695  DetectEngineCtx *de_ctx;
3696  Signature *s=NULL;
3697 
3698  de_ctx = DetectEngineCtxInit();
3699  if (de_ctx == NULL)
3700  goto end;
3701  de_ctx->flags |= DE_QUIET;
3702 
3703  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;)");
3704  if (s != NULL) {
3705  SigFree(s);
3706  goto end;
3707  }
3708 
3709  result = 1;
3710 end:
3711  if (de_ctx != NULL)
3712  DetectEngineCtxFree(de_ctx);
3713  return result;
3714 }
3715 /**
3716  * \test check that we don't allow invalid negation options
3717  */
3718 static int SigParseTestNegation05 (void)
3719 {
3720  int result = 0;
3721  DetectEngineCtx *de_ctx;
3722  Signature *s=NULL;
3723 
3724  de_ctx = DetectEngineCtxInit();
3725  if (de_ctx == NULL)
3726  goto end;
3727  de_ctx->flags |= DE_QUIET;
3728 
3729  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;)");
3730  if (s != NULL) {
3731  SigFree(s);
3732  goto end;
3733  }
3734 
3735  result = 1;
3736 end:
3737  if (de_ctx != NULL)
3738  DetectEngineCtxFree(de_ctx);
3739  return result;
3740 }
3741 /**
3742  * \test check that we don't allow invalid negation options
3743  */
3744 static int SigParseTestNegation06 (void)
3745 {
3746  int result = 0;
3747  DetectEngineCtx *de_ctx;
3748  Signature *s=NULL;
3749 
3750  de_ctx = DetectEngineCtxInit();
3751  if (de_ctx == NULL)
3752  goto end;
3753  de_ctx->flags |= DE_QUIET;
3754 
3755  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;)");
3756  if (s != NULL) {
3757  SigFree(s);
3758  goto end;
3759  }
3760 
3761  result = 1;
3762 end:
3763  if (de_ctx != NULL)
3764  DetectEngineCtxFree(de_ctx);
3765  return result;
3766 }
3767 
3768 /**
3769  * \test check that we don't allow invalid negation options
3770  */
3771 static int SigParseTestNegation07 (void)
3772 {
3773  int result = 0;
3774  DetectEngineCtx *de_ctx;
3775  Signature *s=NULL;
3776 
3777  de_ctx = DetectEngineCtxInit();
3778  if (de_ctx == NULL)
3779  goto end;
3780  de_ctx->flags |= DE_QUIET;
3781 
3782  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;)");
3783  if (s != NULL) {
3784  SigFree(s);
3785  goto end;
3786  }
3787 
3788  result = 1;
3789 end:
3790  if (de_ctx != NULL)
3791  DetectEngineCtxFree(de_ctx);
3792  return result;
3793 }
3794 
3795 /**
3796  * \test check valid negation bug 1079
3797  */
3798 static int SigParseTestNegation08 (void)
3799 {
3800  int result = 0;
3801  DetectEngineCtx *de_ctx;
3802  Signature *s=NULL;
3803 
3804  de_ctx = DetectEngineCtxInit();
3805  if (de_ctx == NULL)
3806  goto end;
3807  de_ctx->flags |= DE_QUIET;
3808 
3809  s = SigInit(de_ctx,"alert tcp any any -> [192.168.0.0/16,!192.168.0.0/24] any (sid:410006; rev:1;)");
3810  if (s == NULL) {
3811  goto end;
3812  }
3813 
3814  result = 1;
3815 end:
3816  if (de_ctx != NULL)
3817  DetectEngineCtxFree(de_ctx);
3818  return result;
3819 }
3820 
3821 /**
3822  * \test mpm
3823  */
3824 static int SigParseTestMpm01 (void)
3825 {
3826  int result = 0;
3827  Signature *sig = NULL;
3828 
3830  if (de_ctx == NULL)
3831  goto end;
3832 
3833  sig = SigInit(de_ctx, "alert tcp any any -> any any (msg:\"mpm test\"; content:\"abcd\"; sid:1;)");
3834  if (sig == NULL) {
3835  printf("sig failed to init: ");
3836  goto end;
3837  }
3838 
3839  if (sig->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
3840  printf("sig doesn't have content list: ");
3841  goto end;
3842  }
3843 
3844  result = 1;
3845 end:
3846  if (sig != NULL)
3847  SigFree(sig);
3848  DetectEngineCtxFree(de_ctx);
3849  return result;
3850 }
3851 
3852 /**
3853  * \test mpm
3854  */
3855 static int SigParseTestMpm02 (void)
3856 {
3857  int result = 0;
3858  Signature *sig = NULL;
3859 
3861  if (de_ctx == NULL)
3862  goto end;
3863 
3864  sig = SigInit(de_ctx, "alert tcp any any -> any any (msg:\"mpm test\"; content:\"abcd\"; content:\"abcdef\"; sid:1;)");
3865  if (sig == NULL) {
3866  printf("sig failed to init: ");
3867  goto end;
3868  }
3869 
3870  if (sig->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
3871  printf("sig doesn't have content list: ");
3872  goto end;
3873  }
3874 
3875  result = 1;
3876 end:
3877  if (sig != NULL)
3878  SigFree(sig);
3879  DetectEngineCtxFree(de_ctx);
3880  return result;
3881 }
3882 
3883 /**
3884  * \test test tls (app layer) rule
3885  */
3886 static int SigParseTestAppLayerTLS01(void)
3887 {
3888  int result = 0;
3889  DetectEngineCtx *de_ctx;
3890  Signature *s=NULL;
3891 
3892  de_ctx = DetectEngineCtxInit();
3893  if (de_ctx == NULL)
3894  goto end;
3895  de_ctx->flags |= DE_QUIET;
3896 
3897  s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS01 \"; sid:410006; rev:1;)");
3898  if (s == NULL) {
3899  printf("parsing sig failed: ");
3900  goto end;
3901  }
3902 
3903  if (s->alproto == 0) {
3904  printf("alproto not set: ");
3905  goto end;
3906  }
3907 
3908  result = 1;
3909 end:
3910  if (s != NULL)
3911  SigFree(s);
3912  if (de_ctx != NULL)
3913  DetectEngineCtxFree(de_ctx);
3914 
3915  return result;
3916 }
3917 
3918 /**
3919  * \test test tls (app layer) rule
3920  */
3921 static int SigParseTestAppLayerTLS02(void)
3922 {
3923  int result = 0;
3924  DetectEngineCtx *de_ctx;
3925  Signature *s=NULL;
3926 
3927  de_ctx = DetectEngineCtxInit();
3928  if (de_ctx == NULL)
3929  goto end;
3930  de_ctx->flags |= DE_QUIET;
3931 
3932  s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS02 \"; tls.version:1.0; sid:410006; rev:1;)");
3933  if (s == NULL) {
3934  printf("parsing sig failed: ");
3935  goto end;
3936  }
3937 
3938  if (s->alproto == 0) {
3939  printf("alproto not set: ");
3940  goto end;
3941  }
3942 
3943  result = 1;
3944 end:
3945  if (s != NULL)
3946  SigFree(s);
3947  if (de_ctx != NULL)
3948  DetectEngineCtxFree(de_ctx);
3949  return result;
3950 }
3951 
3952 /**
3953  * \test test tls (app layer) rule
3954  */
3955 static int SigParseTestAppLayerTLS03(void)
3956 {
3957  int result = 0;
3958  DetectEngineCtx *de_ctx;
3959  Signature *s=NULL;
3960 
3961  de_ctx = DetectEngineCtxInit();
3962  if (de_ctx == NULL)
3963  goto end;
3964  de_ctx->flags |= DE_QUIET;
3965 
3966  s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS03 \"; tls.version:2.5; sid:410006; rev:1;)");
3967  if (s != NULL) {
3968  SigFree(s);
3969  goto end;
3970  }
3971 
3972  result = 1;
3973 end:
3974  if (de_ctx != NULL)
3975  DetectEngineCtxFree(de_ctx);
3976  return result;
3977 }
3978 
3979 static int SigParseTestUnblanacedQuotes01(void)
3980 {
3981  DetectEngineCtx *de_ctx;
3982  Signature *s;
3983 
3984  de_ctx = DetectEngineCtxInit();
3985  FAIL_IF_NULL(de_ctx);
3986  de_ctx->flags |= DE_QUIET;
3987 
3988  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;)");
3989  FAIL_IF_NOT_NULL(s);
3990 
3991  PASS;
3992 }
3993 
3994 static int SigParseTestContentGtDsize01(void)
3995 {
3997  FAIL_IF_NULL(de_ctx);
3998  de_ctx->flags |= DE_QUIET;
3999 
4000  Signature *s = SigInit(de_ctx,
4001  "alert http any any -> any any ("
4002  "dsize:21; content:\"0123456789001234567890|00 00|\"; "
4003  "sid:1; rev:1;)");
4004  FAIL_IF_NOT_NULL(s);
4005 
4006  PASS;
4007 }
4008 
4009 static int SigParseTestContentGtDsize02(void)
4010 {
4012  FAIL_IF_NULL(de_ctx);
4013  de_ctx->flags |= DE_QUIET;
4014 
4015  Signature *s = SigInit(de_ctx,
4016  "alert http any any -> any any ("
4017  "dsize:21; content:\"0123456789|00 00|\"; offset:10; "
4018  "sid:1; rev:1;)");
4019  FAIL_IF_NOT_NULL(s);
4020 
4021  PASS;
4022 }
4023 
4024 static int SigParseBidirWithSameSrcAndDest01(void)
4025 {
4027  FAIL_IF_NULL(de_ctx);
4028  de_ctx->flags |= DE_QUIET;
4029 
4030  Signature *s = SigInit(de_ctx,
4031  "alert tcp any any <> any any (sid:1; rev:1;)");
4032  FAIL_IF_NULL(s);
4033  FAIL_IF_NOT_NULL(s->next);
4035 
4036  SigFree(s);
4037 
4038  s = SigInit(de_ctx,
4039  "alert tcp any [80, 81] <> any [81, 80] (sid:1; rev:1;)");
4040  FAIL_IF_NULL(s);
4041  FAIL_IF_NOT_NULL(s->next);
4043 
4044  SigFree(s);
4045 
4046  s = SigInit(de_ctx,
4047  "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;)");
4048  FAIL_IF_NULL(s);
4049  FAIL_IF_NOT_NULL(s->next);
4051 
4052  SigFree(s);
4053 
4054  PASS;
4055 }
4056 
4057 static int SigParseBidirWithSameSrcAndDest02(void)
4058 {
4060  FAIL_IF_NULL(de_ctx);
4061  de_ctx->flags |= DE_QUIET;
4062 
4063  // Source is a subset of destination
4064  Signature *s = SigInit(de_ctx,
4065  "alert tcp 1.2.3.4 any <> [1.2.3.4, 5.6.7.8, ::1] any (sid:1; rev:1;)");
4066  FAIL_IF_NULL(s);
4067  FAIL_IF_NULL(s->next);
4069 
4070  SigFree(s);
4071 
4072  // Source is a subset of destinationn
4073  s = SigInit(de_ctx,
4074  "alert tcp [1.2.3.4, ::1] [80, 81, 82] <> [1.2.3.4, ::1] [80, 81] (sid:1; rev:1;)");
4075  FAIL_IF_NULL(s);
4076  FAIL_IF_NULL(s->next);
4078 
4079  SigFree(s);
4080 
4081  // Source intersects with destination
4082  s = SigInit(de_ctx,
4083  "alert tcp [1.2.3.4, ::1, ABCD:AAAA::1] [80] <> [1.2.3.4, ::1] [80, 81] (sid:1; rev:1;)");
4084  FAIL_IF_NULL(s);
4085  FAIL_IF_NULL(s->next);
4087 
4088  SigFree(s);
4089 
4090  PASS;
4091 }
4092 
4093 #endif /* UNITTESTS */
4094 
4095 #ifdef UNITTESTS
4096 void DetectParseRegisterTests (void);
4097 #include "tests/detect-parse.c"
4098 #endif
4099 
4101 {
4102 #ifdef UNITTESTS
4104 
4105  UtRegisterTest("SigParseTest01", SigParseTest01);
4106  UtRegisterTest("SigParseTest02", SigParseTest02);
4107  UtRegisterTest("SigParseTest03", SigParseTest03);
4108  UtRegisterTest("SigParseTest04", SigParseTest04);
4109  UtRegisterTest("SigParseTest05", SigParseTest05);
4110  UtRegisterTest("SigParseTest06", SigParseTest06);
4111  UtRegisterTest("SigParseTest07", SigParseTest07);
4112  UtRegisterTest("SigParseTest08", SigParseTest08);
4113  UtRegisterTest("SigParseTest09", SigParseTest09);
4114  UtRegisterTest("SigParseTest10", SigParseTest10);
4115  UtRegisterTest("SigParseTest11", SigParseTest11);
4116  UtRegisterTest("SigParseTest12", SigParseTest12);
4117  UtRegisterTest("SigParseTest13", SigParseTest13);
4118  UtRegisterTest("SigParseTest14", SigParseTest14);
4119  UtRegisterTest("SigParseTest15", SigParseTest15);
4120  UtRegisterTest("SigParseTest16", SigParseTest16);
4121  UtRegisterTest("SigParseTest17", SigParseTest17);
4122  UtRegisterTest("SigParseTest18", SigParseTest18);
4123  UtRegisterTest("SigParseTest19", SigParseTest19);
4124  UtRegisterTest("SigParseTest20", SigParseTest20);
4125  UtRegisterTest("SigParseTest21 -- address with space", SigParseTest21);
4126  UtRegisterTest("SigParseTest22 -- address with space", SigParseTest22);
4127  UtRegisterTest("SigParseTest23 -- carriage return", SigParseTest23);
4128 
4129  UtRegisterTest("SigParseBidirecTest06", SigParseBidirecTest06);
4130  UtRegisterTest("SigParseBidirecTest07", SigParseBidirecTest07);
4131  UtRegisterTest("SigParseBidirecTest08", SigParseBidirecTest08);
4132  UtRegisterTest("SigParseBidirecTest09", SigParseBidirecTest09);
4133  UtRegisterTest("SigParseBidirecTest10", SigParseBidirecTest10);
4134  UtRegisterTest("SigParseBidirecTest11", SigParseBidirecTest11);
4135  UtRegisterTest("SigParseBidirecTest12", SigParseBidirecTest12);
4136  UtRegisterTest("SigParseBidirecTest13", SigParseBidirecTest13);
4137  UtRegisterTest("SigParseBidirecTest14", SigParseBidirecTest14);
4138  UtRegisterTest("SigTestBidirec01", SigTestBidirec01);
4139  UtRegisterTest("SigTestBidirec02", SigTestBidirec02);
4140  UtRegisterTest("SigTestBidirec03", SigTestBidirec03);
4141  UtRegisterTest("SigTestBidirec04", SigTestBidirec04);
4142  UtRegisterTest("SigParseTestNegation01", SigParseTestNegation01);
4143  UtRegisterTest("SigParseTestNegation02", SigParseTestNegation02);
4144  UtRegisterTest("SigParseTestNegation03", SigParseTestNegation03);
4145  UtRegisterTest("SigParseTestNegation04", SigParseTestNegation04);
4146  UtRegisterTest("SigParseTestNegation05", SigParseTestNegation05);
4147  UtRegisterTest("SigParseTestNegation06", SigParseTestNegation06);
4148  UtRegisterTest("SigParseTestNegation07", SigParseTestNegation07);
4149  UtRegisterTest("SigParseTestNegation08", SigParseTestNegation08);
4150  UtRegisterTest("SigParseTestMpm01", SigParseTestMpm01);
4151  UtRegisterTest("SigParseTestMpm02", SigParseTestMpm02);
4152  UtRegisterTest("SigParseTestAppLayerTLS01", SigParseTestAppLayerTLS01);
4153  UtRegisterTest("SigParseTestAppLayerTLS02", SigParseTestAppLayerTLS02);
4154  UtRegisterTest("SigParseTestAppLayerTLS03", SigParseTestAppLayerTLS03);
4155  UtRegisterTest("SigParseTestUnblanacedQuotes01",
4156  SigParseTestUnblanacedQuotes01);
4157 
4158  UtRegisterTest("SigParseTestContentGtDsize01",
4159  SigParseTestContentGtDsize01);
4160  UtRegisterTest("SigParseTestContentGtDsize02",
4161  SigParseTestContentGtDsize02);
4162 
4163  UtRegisterTest("SigParseBidirWithSameSrcAndDest01",
4164  SigParseBidirWithSameSrcAndDest01);
4165  UtRegisterTest("SigParseBidirWithSameSrcAndDest02",
4166  SigParseBidirWithSameSrcAndDest02);
4167 #endif /* UNITTESTS */
4168 }
#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
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:815
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
const DetectAddressHead * DetectParseAddress(DetectEngineCtx *de_ctx, const char *string, bool *contains_negation)
#define SIG_FLAG_INIT_BIDIREC
Definition: detect.h:259
#define SIZE_OF_PACKET
Definition: decode.h:619
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:633
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1670
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:559
#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