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