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