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