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