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