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