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 /** \retval 0 on error
1218  * \retval flags on success
1219  */
1220 static uint8_t ActionStringToFlags(const char *action)
1221 {
1222  if (strcasecmp(action, "alert") == 0) {
1223  return ACTION_ALERT;
1224  } else if (strcasecmp(action, "drop") == 0) {
1225  return ACTION_DROP | ACTION_ALERT;
1226  } else if (strcasecmp(action, "pass") == 0) {
1227  return ACTION_PASS;
1228  } else if (strcasecmp(action, "reject") == 0 ||
1229  strcasecmp(action, "rejectsrc") == 0)
1230  {
1231  if (!(SigParseActionRejectValidate(action)))
1232  return 0;
1234  } else if (strcasecmp(action, "rejectdst") == 0) {
1235  if (!(SigParseActionRejectValidate(action)))
1236  return 0;
1238  } else if (strcasecmp(action, "rejectboth") == 0) {
1239  if (!(SigParseActionRejectValidate(action)))
1240  return 0;
1242  } else if (strcasecmp(action, "config") == 0) {
1243  return ACTION_CONFIG;
1244  } else {
1245  SCLogError("An invalid action \"%s\" was given", action);
1246  return 0;
1247  }
1248 }
1249 
1250 /**
1251  * \brief Parses the action that has been used by the Signature and allots it
1252  * to its Signature instance.
1253  *
1254  * \param s Pointer to the Signature instance to which the action belongs.
1255  * \param action Pointer to the action string used by the Signature.
1256  *
1257  * \retval 0 On successfully parsing the action string and adding it to the
1258  * Signature.
1259  * \retval -1 On failure.
1260  */
1261 static int SigParseAction(Signature *s, const char *action)
1262 {
1263  uint8_t flags = ActionStringToFlags(action);
1264  if (flags == 0)
1265  return -1;
1266 
1267  s->action = flags;
1268  return 0;
1269 }
1270 
1271 /**
1272  * \brief Parse the next token in rule.
1273  *
1274  * For rule parsing a token is considered to be a string of characters
1275  * separated by white space.
1276  *
1277  * \param input double pointer to input buffer, will be advanced as input is
1278  * parsed.
1279  * \param output buffer to copy token into.
1280  * \param output_size length of output buffer.
1281  */
1282 static inline int SigParseToken(char **input, char *output,
1283  const size_t output_size)
1284 {
1285  size_t len = *input == NULL ? 0 : strlen(*input);
1286 
1287  if (!len) {
1288  return 0;
1289  }
1290 
1291  while (len && isblank(**input)) {
1292  (*input)++;
1293  len--;
1294  }
1295 
1296  char *endptr = strpbrk(*input, " \t\n\r");
1297  if (endptr != NULL) {
1298  *(endptr++) = '\0';
1299  }
1300  strlcpy(output, *input, output_size);
1301  *input = endptr;
1302 
1303  return 1;
1304 }
1305 
1306 /**
1307  * \brief Parse the next rule "list" token.
1308  *
1309  * Parses rule tokens that may be lists such as addresses and ports
1310  * handling the case when they may not be lists.
1311  *
1312  * \param input double pointer to input buffer, will be advanced as input is
1313  * parsed.
1314  * \param output buffer to copy token into.
1315  * \param output_size length of output buffer.
1316  */
1317 static inline int SigParseList(char **input, char *output,
1318  const size_t output_size)
1319 {
1320  int in_list = 0;
1321  size_t len = *input != NULL ? strlen(*input) : 0;
1322 
1323  if (len == 0) {
1324  return 0;
1325  }
1326 
1327  while (len && isblank(**input)) {
1328  (*input)++;
1329  len--;
1330  }
1331 
1332  size_t i = 0;
1333  for (i = 0; i < len; i++) {
1334  char c = (*input)[i];
1335  if (c == '[') {
1336  in_list++;
1337  } else if (c == ']') {
1338  in_list--;
1339  } else if (c == ' ') {
1340  if (!in_list) {
1341  break;
1342  }
1343  }
1344  }
1345  if (i == len) {
1346  *input = NULL;
1347  return 0;
1348  }
1349  (*input)[i] = '\0';
1350  strlcpy(output, *input, output_size);
1351  *input = *input + i + 1;
1352 
1353  return 1;
1354 }
1355 
1356 /**
1357  * \internal
1358  * \brief split a signature string into a few blocks for further parsing
1359  *
1360  * \param scan_only just scan, don't validate
1361  */
1362 static int SigParseBasics(DetectEngineCtx *de_ctx, Signature *s, const char *sigstr,
1363  SignatureParser *parser, uint8_t addrs_direction, bool scan_only)
1364 {
1365  char *index, dup[DETECT_MAX_RULE_SIZE];
1366 
1367  strlcpy(dup, sigstr, DETECT_MAX_RULE_SIZE);
1368  index = dup;
1369 
1370  /* Action. */
1371  SigParseToken(&index, parser->action, sizeof(parser->action));
1372 
1373  /* Protocol. */
1374  SigParseList(&index, parser->protocol, sizeof(parser->protocol));
1375 
1376  /* Source. */
1377  SigParseList(&index, parser->src, sizeof(parser->src));
1378 
1379  /* Source port(s). */
1380  SigParseList(&index, parser->sp, sizeof(parser->sp));
1381 
1382  /* Direction. */
1383  SigParseToken(&index, parser->direction, sizeof(parser->direction));
1384 
1385  /* Destination. */
1386  SigParseList(&index, parser->dst, sizeof(parser->dst));
1387 
1388  /* Destination port(s). */
1389  SigParseList(&index, parser->dp, sizeof(parser->dp));
1390 
1391  /* Options. */
1392  if (index == NULL) {
1393  SCLogError("no rule options.");
1394  goto error;
1395  }
1396  while (isspace(*index) || *index == '(') {
1397  index++;
1398  }
1399  for (size_t i = strlen(index); i > 0; i--) {
1400  if (isspace(index[i - 1]) || index[i - 1] == ')') {
1401  index[i - 1] = '\0';
1402  } else {
1403  break;
1404  }
1405  }
1406  strlcpy(parser->opts, index, sizeof(parser->opts));
1407 
1408  if (scan_only) {
1409  return 0;
1410  }
1411 
1412  /* Parse Action */
1413  if (SigParseAction(s, parser->action) < 0)
1414  goto error;
1415 
1416  if (SigParseProto(s, parser->protocol) < 0)
1417  goto error;
1418 
1419  if (strcmp(parser->direction, "<>") == 0) {
1421  } else if (strcmp(parser->direction, "->") != 0) {
1422  SCLogError("\"%s\" is not a valid direction modifier, "
1423  "\"->\" and \"<>\" are supported.",
1424  parser->direction);
1425  goto error;
1426  }
1427 
1428  /* Parse Address & Ports */
1429  if (SigParseAddress(de_ctx, s, parser->src, SIG_DIREC_SRC ^ addrs_direction) < 0)
1430  goto error;
1431 
1432  if (SigParseAddress(de_ctx, s, parser->dst, SIG_DIREC_DST ^ addrs_direction) < 0)
1433  goto error;
1434 
1435  /* By AWS - Traditionally we should be doing this only for tcp/udp/sctp,
1436  * but we do it for regardless of ip proto, since the dns/dnstcp/dnsudp
1437  * changes that we made sees to it that at this point of time we don't
1438  * set the ip proto for the sig. We do it a bit later. */
1439  if (SigParsePort(de_ctx, s, parser->sp, SIG_DIREC_SRC ^ addrs_direction) < 0)
1440  goto error;
1441  if (SigParsePort(de_ctx, s, parser->dp, SIG_DIREC_DST ^ addrs_direction) < 0)
1442  goto error;
1443 
1444  return 0;
1445 
1446 error:
1447  return -1;
1448 }
1449 
1450 static inline bool CheckAscii(const char *str)
1451 {
1452  for (size_t i = 0; i < strlen(str); i++) {
1453  if (str[i] < 0x20) {
1454  // LF CR TAB
1455  if (str[i] == 0x0a || str[i] == 0x0d || str[i] == 0x09) {
1456  continue;
1457  }
1458  return false;
1459  } else if (str[i] == 0x7f) {
1460  return false;
1461  }
1462  }
1463  return true;
1464 }
1465 
1466 /**
1467  * \brief parse a signature
1468  *
1469  * \param de_ctx detection engine ctx to add it to
1470  * \param s memory structure to store the signature in
1471  * \param sigstr the raw signature as a null terminated string
1472  * \param addrs_direction direction (for bi-directional sigs)
1473  * \param require only scan rule for requires
1474  *
1475  * \param -1 parse error
1476  * \param 0 ok
1477  */
1478 static int SigParse(DetectEngineCtx *de_ctx, Signature *s, const char *sigstr,
1479  uint8_t addrs_direction, SignatureParser *parser, bool requires)
1480 {
1481  SCEnter();
1482 
1483  if (!rs_check_utf8(sigstr)) {
1484  SCLogError("rule is not valid UTF-8");
1485  SCReturnInt(-1);
1486  }
1487 
1488  if (!CheckAscii(sigstr)) {
1489  SCLogError("rule contains invalid (control) characters");
1490  SCReturnInt(-1);
1491  }
1492 
1493  int ret = SigParseBasics(de_ctx, s, sigstr, parser, addrs_direction, requires);
1494  if (ret < 0) {
1495  SCLogDebug("SigParseBasics failed");
1496  SCReturnInt(-1);
1497  }
1498 
1499  /* we can have no options, so make sure we have them */
1500  if (strlen(parser->opts) > 0) {
1501  size_t buffer_size = strlen(parser->opts) + 1;
1502  char input[buffer_size];
1503  char output[buffer_size];
1504  memset(input, 0x00, buffer_size);
1505  memcpy(input, parser->opts, strlen(parser->opts) + 1);
1506 
1507  /* loop the option parsing. Each run processes one option
1508  * and returns the rest of the option string through the
1509  * output variable. */
1510  do {
1511  memset(output, 0x00, buffer_size);
1512  ret = SigParseOptions(de_ctx, s, input, output, buffer_size, requires);
1513  if (ret == 1) {
1514  memcpy(input, output, buffer_size);
1515  }
1516 
1517  } while (ret == 1);
1518 
1519  if (ret < 0) {
1520  /* Suricata didn't meet the rule requirements, skip. */
1521  goto end;
1522  }
1523  }
1524 
1525 end:
1527 
1528  SCReturnInt(ret);
1529 }
1530 
1531 /** \brief check if buffers array still has space left, expand if not
1532  */
1534 {
1535  if (s->init_data->buffers_size >= 64)
1536  return -1;
1537 
1538  if (s->init_data->buffer_index + 1 == s->init_data->buffers_size) {
1539  void *ptr = SCRealloc(s->init_data->buffers,
1540  (s->init_data->buffers_size + 8) * sizeof(SignatureInitDataBuffer));
1541  if (ptr == NULL)
1542  return -1;
1543  s->init_data->buffers = ptr;
1544  for (uint32_t x = s->init_data->buffers_size; x < s->init_data->buffers_size + 8; x++) {
1546  memset(b, 0, sizeof(*b));
1547  }
1548  s->init_data->buffers_size += 8;
1549  }
1550  return 0;
1551 }
1552 
1554 {
1555  Signature *sig = SCCalloc(1, sizeof(Signature));
1556  if (unlikely(sig == NULL))
1557  return NULL;
1558 
1559  sig->init_data = SCCalloc(1, sizeof(SignatureInitData));
1560  if (sig->init_data == NULL) {
1561  SCFree(sig);
1562  return NULL;
1563  }
1564  sig->init_data->mpm_sm_list = -1;
1565 
1566  sig->init_data->buffers = SCCalloc(8, sizeof(SignatureInitDataBuffer));
1567  if (sig->init_data->buffers == NULL) {
1568  SCFree(sig->init_data);
1569  SCFree(sig);
1570  return NULL;
1571  }
1572  sig->init_data->buffers_size = 8;
1573 
1574  /* assign it to -1, so that we can later check if the value has been
1575  * overwritten after the Signature has been parsed, and if it hasn't been
1576  * overwritten, we can then assign the default value of 3 */
1577  sig->prio = -1;
1578 
1579  /* rule interdepency is false, at start */
1580  sig->init_data->is_rule_state_dependant = false;
1581  /* first index is 0 */
1583 
1585  return sig;
1586 }
1587 
1588 /**
1589  * \internal
1590  * \brief Free Metadata list
1591  *
1592  * \param s Pointer to the signature
1593  */
1594 static void SigMetadataFree(Signature *s)
1595 {
1596  SCEnter();
1597 
1598  DetectMetadata *mdata = NULL;
1599  DetectMetadata *next_mdata = NULL;
1600 
1601  if (s == NULL || s->metadata == NULL) {
1602  SCReturn;
1603  }
1604 
1605  SCLogDebug("s %p, s->metadata %p", s, s->metadata);
1606 
1607  for (mdata = s->metadata->list; mdata != NULL;) {
1608  next_mdata = mdata->next;
1609  DetectMetadataFree(mdata);
1610  mdata = next_mdata;
1611  }
1612  SCFree(s->metadata->json_str);
1613  SCFree(s->metadata);
1614  s->metadata = NULL;
1615 
1616  SCReturn;
1617 }
1618 
1619 /**
1620  * \internal
1621  * \brief Free Reference list
1622  *
1623  * \param s Pointer to the signature
1624  */
1625 static void SigRefFree (Signature *s)
1626 {
1627  SCEnter();
1628 
1629  DetectReference *ref = NULL;
1630  DetectReference *next_ref = NULL;
1631 
1632  if (s == NULL) {
1633  SCReturn;
1634  }
1635 
1636  SCLogDebug("s %p, s->references %p", s, s->references);
1637 
1638  for (ref = s->references; ref != NULL;) {
1639  next_ref = ref->next;
1640  DetectReferenceFree(ref);
1641  ref = next_ref;
1642  }
1643 
1644  s->references = NULL;
1645 
1646  SCReturn;
1647 }
1648 
1649 static void SigMatchFreeArrays(DetectEngineCtx *de_ctx, Signature *s, int ctxs)
1650 {
1651  if (s != NULL) {
1652  int type;
1653  for (type = 0; type < DETECT_SM_LIST_MAX; type++) {
1654  if (s->sm_arrays[type] != NULL) {
1655  if (ctxs) {
1656  SigMatchData *smd = s->sm_arrays[type];
1657  while(1) {
1658  if (sigmatch_table[smd->type].Free != NULL) {
1659  sigmatch_table[smd->type].Free(de_ctx, smd->ctx);
1660  }
1661  if (smd->is_last)
1662  break;
1663  smd++;
1664  }
1665  }
1666 
1667  SCFree(s->sm_arrays[type]);
1668  }
1669  }
1670  }
1671 }
1672 
1674 {
1675  if (s == NULL)
1676  return;
1677 
1678  int i;
1679 
1680  if (s->init_data && s->init_data->transforms.cnt) {
1681  for(i = 0; i < s->init_data->transforms.cnt; i++) {
1682  if (s->init_data->transforms.transforms[i].options) {
1683  int transform = s->init_data->transforms.transforms[i].transform;
1684  sigmatch_table[transform].Free(
1686  s->init_data->transforms.transforms[i].options = NULL;
1687  }
1688  }
1689  }
1690  if (s->init_data) {
1691  for (i = 0; i < DETECT_SM_LIST_MAX; i++) {
1692  SigMatch *sm = s->init_data->smlists[i];
1693  while (sm != NULL) {
1694  SigMatch *nsm = sm->next;
1695  SigMatchFree(de_ctx, sm);
1696  sm = nsm;
1697  }
1698  }
1699 
1700  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
1701  SigMatch *sm = s->init_data->buffers[x].head;
1702  while (sm != NULL) {
1703  SigMatch *nsm = sm->next;
1704  SigMatchFree(de_ctx, sm);
1705  sm = nsm;
1706  }
1707  }
1708  if (s->init_data->cidr_dst != NULL)
1710 
1711  if (s->init_data->cidr_src != NULL)
1713 
1714  SCFree(s->init_data->buffers);
1715  s->init_data->buffers = NULL;
1716  }
1717  SigMatchFreeArrays(de_ctx, s, (s->init_data == NULL));
1718  if (s->init_data) {
1719  SCFree(s->init_data);
1720  s->init_data = NULL;
1721  }
1722 
1723  if (s->sp != NULL) {
1724  DetectPortCleanupList(NULL, s->sp);
1725  }
1726  if (s->dp != NULL) {
1727  DetectPortCleanupList(NULL, s->dp);
1728  }
1729 
1730  if (s->msg != NULL)
1731  SCFree(s->msg);
1732 
1733  if (s->addr_src_match4 != NULL) {
1734  SCFree(s->addr_src_match4);
1735  }
1736  if (s->addr_dst_match4 != NULL) {
1737  SCFree(s->addr_dst_match4);
1738  }
1739  if (s->addr_src_match6 != NULL) {
1740  SCFree(s->addr_src_match6);
1741  }
1742  if (s->addr_dst_match6 != NULL) {
1743  SCFree(s->addr_dst_match6);
1744  }
1745  if (s->sig_str != NULL) {
1746  SCFree(s->sig_str);
1747  }
1748 
1749  SigRefFree(s);
1750  SigMetadataFree(s);
1751 
1753 
1754  SCFree(s);
1755 }
1756 
1757 int DetectSignatureAddTransform(Signature *s, int transform, void *options)
1758 {
1759  /* we only support buffers */
1760  if (s->init_data->list == 0) {
1761  SCReturnInt(-1);
1762  }
1763  if (!s->init_data->list_set) {
1764  SCLogError("transforms must directly follow stickybuffers");
1765  SCReturnInt(-1);
1766  }
1768  SCReturnInt(-1);
1769  }
1770 
1773 
1774  s->init_data->transforms.cnt++;
1775  SCLogDebug("Added transform #%d [%s]",
1776  s->init_data->transforms.cnt,
1777  s->sig_str);
1778 
1779  SCReturnInt(0);
1780 }
1781 
1783 {
1784  if (!AppProtoIsValid(alproto)) {
1785  SCLogError("invalid alproto %u", alproto);
1786  return -1;
1787  }
1788 
1789  if (s->alproto != ALPROTO_UNKNOWN) {
1790  alproto = AppProtoCommon(s->alproto, alproto);
1791  if (alproto == ALPROTO_FAILED) {
1792  SCLogError("can't set rule app proto to %s: already set to %s",
1793  AppProtoToString(alproto), AppProtoToString(s->alproto));
1794  return -1;
1795  }
1796  }
1797 
1798  if (AppLayerProtoDetectGetProtoName(alproto) == NULL) {
1799  SCLogError("disabled alproto %s, rule can never match", AppProtoToString(alproto));
1800  return -1;
1801  }
1802  s->alproto = alproto;
1803  s->flags |= SIG_FLAG_APPLAYER;
1804  return 0;
1805 }
1806 
1807 static DetectMatchAddressIPv4 *SigBuildAddressMatchArrayIPv4(
1808  const DetectAddress *head, uint16_t *match4_cnt)
1809 {
1810  uint16_t cnt = 0;
1811 
1812  for (const DetectAddress *da = head; da != NULL; da = da->next) {
1813  cnt++;
1814  }
1815  if (cnt == 0) {
1816  return NULL;
1817  }
1818  DetectMatchAddressIPv4 *addr_match4 = SCCalloc(cnt, sizeof(DetectMatchAddressIPv4));
1819  if (addr_match4 == NULL) {
1820  exit(EXIT_FAILURE);
1821  }
1822 
1823  uint16_t idx = 0;
1824  for (const DetectAddress *da = head; da != NULL; da = da->next) {
1825  addr_match4[idx].ip = SCNtohl(da->ip.addr_data32[0]);
1826  addr_match4[idx].ip2 = SCNtohl(da->ip2.addr_data32[0]);
1827  idx++;
1828  }
1829  *match4_cnt = cnt;
1830  return addr_match4;
1831 }
1832 
1833 static DetectMatchAddressIPv6 *SigBuildAddressMatchArrayIPv6(
1834  const DetectAddress *head, uint16_t *match6_cnt)
1835 {
1836  uint16_t cnt = 0;
1837  for (const DetectAddress *da = head; da != NULL; da = da->next) {
1838  cnt++;
1839  }
1840  if (cnt == 0) {
1841  return NULL;
1842  }
1843 
1844  DetectMatchAddressIPv6 *addr_match6 = SCCalloc(cnt, sizeof(DetectMatchAddressIPv6));
1845  if (addr_match6 == NULL) {
1846  exit(EXIT_FAILURE);
1847  }
1848 
1849  uint16_t idx = 0;
1850  for (const DetectAddress *da = head; da != NULL; da = da->next) {
1851  addr_match6[idx].ip[0] = SCNtohl(da->ip.addr_data32[0]);
1852  addr_match6[idx].ip[1] = SCNtohl(da->ip.addr_data32[1]);
1853  addr_match6[idx].ip[2] = SCNtohl(da->ip.addr_data32[2]);
1854  addr_match6[idx].ip[3] = SCNtohl(da->ip.addr_data32[3]);
1855  addr_match6[idx].ip2[0] = SCNtohl(da->ip2.addr_data32[0]);
1856  addr_match6[idx].ip2[1] = SCNtohl(da->ip2.addr_data32[1]);
1857  addr_match6[idx].ip2[2] = SCNtohl(da->ip2.addr_data32[2]);
1858  addr_match6[idx].ip2[3] = SCNtohl(da->ip2.addr_data32[3]);
1859  idx++;
1860  }
1861  *match6_cnt = cnt;
1862  return addr_match6;
1863 }
1864 
1865 /**
1866  * \internal
1867  * \brief build address match array for cache efficient matching
1868  *
1869  * \param s the signature
1870  */
1871 static void SigBuildAddressMatchArray(Signature *s)
1872 {
1873  /* source addresses */
1874  s->addr_src_match4 =
1875  SigBuildAddressMatchArrayIPv4(s->init_data->src->ipv4_head, &s->addr_src_match4_cnt);
1876  /* destination addresses */
1877  s->addr_dst_match4 =
1878  SigBuildAddressMatchArrayIPv4(s->init_data->dst->ipv4_head, &s->addr_dst_match4_cnt);
1879 
1880  /* source addresses IPv6 */
1881  s->addr_src_match6 =
1882  SigBuildAddressMatchArrayIPv6(s->init_data->src->ipv6_head, &s->addr_src_match6_cnt);
1883  /* destination addresses IPv6 */
1884  s->addr_dst_match6 =
1885  SigBuildAddressMatchArrayIPv6(s->init_data->dst->ipv6_head, &s->addr_dst_match6_cnt);
1886 }
1887 
1888 static int SigMatchListLen(SigMatch *sm)
1889 {
1890  int len = 0;
1891  for (; sm != NULL; sm = sm->next)
1892  len++;
1893 
1894  return len;
1895 }
1896 
1897 /** \brief convert SigMatch list to SigMatchData array
1898  * \note ownership of sm->ctx is transferred to smd->ctx
1899  */
1901 {
1902  int len = SigMatchListLen(head);
1903  if (len == 0)
1904  return NULL;
1905 
1906  SigMatchData *smd = (SigMatchData *)SCCalloc(len, sizeof(SigMatchData));
1907  if (smd == NULL) {
1908  FatalError("initializing the detection engine failed");
1909  }
1910  SigMatchData *out = smd;
1911 
1912  /* Copy sm type and Context into array */
1913  SigMatch *sm = head;
1914  for (; sm != NULL; sm = sm->next, smd++) {
1915  smd->type = sm->type;
1916  smd->ctx = sm->ctx;
1917  sm->ctx = NULL; // SigMatch no longer owns the ctx
1918  smd->is_last = (sm->next == NULL);
1919  }
1920  return out;
1921 }
1922 
1923 extern int g_skip_prefilter;
1924 
1925 static void SigSetupPrefilter(DetectEngineCtx *de_ctx, Signature *s)
1926 {
1927  SCEnter();
1928  SCLogDebug("s %u: set up prefilter/mpm", s->id);
1929  DEBUG_VALIDATE_BUG_ON(s->init_data->mpm_sm != NULL);
1930 
1931  if (s->init_data->prefilter_sm != NULL) {
1932  if (s->init_data->prefilter_sm->type == DETECT_CONTENT) {
1934  if (s->init_data->mpm_sm != NULL) {
1935  s->flags |= SIG_FLAG_PREFILTER;
1936  SCLogDebug("%u: RetrieveFPForSig set", s->id);
1937  SCReturn;
1938  }
1939  /* fall through, this can happen if the mpm doesn't support the pattern */
1940  } else {
1941  s->flags |= SIG_FLAG_PREFILTER;
1942  SCReturn;
1943  }
1944  } else {
1945  SCLogDebug("%u: RetrieveFPForSig", s->id);
1947  if (s->init_data->mpm_sm != NULL) {
1948  s->flags |= SIG_FLAG_PREFILTER;
1949  SCLogDebug("%u: RetrieveFPForSig set", s->id);
1950  SCReturn;
1951  }
1952  }
1953 
1954  SCLogDebug("s %u: no mpm; prefilter? de_ctx->prefilter_setting %u "
1955  "s->init_data->has_possible_prefilter %s",
1957 
1959  SCReturn;
1960 
1963  int prefilter_list = DETECT_TBLSIZE;
1964  /* get the keyword supporting prefilter with the lowest type */
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 (sigmatch_table[sm->type].SupportsPrefilter != NULL) {
1968  if (sigmatch_table[sm->type].SupportsPrefilter(s)) {
1969  prefilter_list = MIN(prefilter_list, sm->type);
1970  }
1971  }
1972  }
1973  }
1974 
1975  /* apply that keyword as prefilter */
1976  if (prefilter_list != DETECT_TBLSIZE) {
1977  for (int i = 0; i < DETECT_SM_LIST_MAX; i++) {
1978  for (SigMatch *sm = s->init_data->smlists[i]; sm != NULL; sm = sm->next) {
1979  if (sm->type == prefilter_list) {
1980  s->init_data->prefilter_sm = sm;
1981  s->flags |= SIG_FLAG_PREFILTER;
1982  SCLogConfig("sid %u: prefilter is on \"%s\"", s->id,
1983  sigmatch_table[sm->type].name);
1984  break;
1985  }
1986  }
1987  }
1988  }
1989  }
1990  SCReturn;
1991 }
1992 
1993 /**
1994  * \internal
1995  * \brief validate a just parsed signature for internal inconsistencies
1996  *
1997  * \param s just parsed signature
1998  *
1999  * \retval 0 invalid
2000  * \retval 1 valid
2001  */
2002 static int SigValidate(DetectEngineCtx *de_ctx, Signature *s)
2003 {
2004  SCEnter();
2005 
2006  uint32_t sig_flags = 0;
2007  int nlists = 0;
2008  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
2009  nlists = MAX(nlists, (int)s->init_data->buffers[x].id);
2010  }
2011  nlists += (nlists > 0);
2012  SCLogDebug("nlists %d", nlists);
2013 
2014  if (s->init_data->curbuf && s->init_data->curbuf->head == NULL) {
2015  SCLogError("rule %u setup buffer %s but didn't add matches to it", s->id,
2017  SCReturnInt(0);
2018  }
2019 
2020  bool has_frame = false;
2021  bool has_app = false;
2022  bool has_pkt = false;
2023  bool has_pmatch = false;
2024 
2025  /* run buffer type validation callbacks if any */
2028  SCReturnInt(0);
2029 
2030  has_pmatch = true;
2031  }
2032 
2033  struct BufferVsDir {
2034  int ts;
2035  int tc;
2036  } bufdir[nlists + 1];
2037  memset(&bufdir, 0, (nlists + 1) * sizeof(struct BufferVsDir));
2038 
2039  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
2042  if (bt == NULL) {
2043  DEBUG_VALIDATE_BUG_ON(1); // should be impossible
2044  continue;
2045  }
2046  SCLogDebug("x %u b->id %u name %s", x, b->id, bt->name);
2047  for (SigMatch *sm = b->head; sm != NULL; sm = sm->next) {
2048  SCLogDebug("sm %u %s", sm->type, sigmatch_table[sm->type].name);
2049  }
2050 
2051  if (b->head == NULL) {
2052  SCLogError("no matches in sticky buffer %s", bt->name);
2053  SCReturnInt(0);
2054  }
2055 
2056  has_frame |= bt->frame;
2057  has_app |= (!bt->frame && !bt->packet);
2058  has_pkt |= bt->packet;
2059 
2060  if ((s->flags & SIG_FLAG_REQUIRE_PACKET) && !bt->packet) {
2061  SCLogError("Signature combines packet "
2062  "specific matches (like dsize, flags, ttl) with stream / "
2063  "state matching by matching on app layer proto (like using "
2064  "http_* keywords).");
2065  SCReturnInt(0);
2066  }
2067 
2069  for (; app != NULL; app = app->next) {
2070  if (app->sm_list == b->id &&
2071  (AppProtoEquals(s->alproto, app->alproto) || s->alproto == 0)) {
2072  SCLogDebug("engine %s dir %d alproto %d",
2074  app->alproto);
2075  SCLogDebug("b->id %d nlists %d", b->id, nlists);
2076  bufdir[b->id].ts += (app->dir == 0);
2077  bufdir[b->id].tc += (app->dir == 1);
2078  }
2079  }
2080 
2082  SCReturnInt(0);
2083  }
2084 
2086  SCReturnInt(0);
2087  }
2089  SCReturnInt(0);
2090  }
2091  }
2092 
2093  int ts_excl = 0;
2094  int tc_excl = 0;
2095  int dir_amb = 0;
2096  for (int x = 0; x < nlists; x++) {
2097  if (bufdir[x].ts == 0 && bufdir[x].tc == 0)
2098  continue;
2099  ts_excl += (bufdir[x].ts > 0 && bufdir[x].tc == 0);
2100  tc_excl += (bufdir[x].ts == 0 && bufdir[x].tc > 0);
2101  dir_amb += (bufdir[x].ts > 0 && bufdir[x].tc > 0);
2102 
2103  SCLogDebug("%s/%d: %d/%d", DetectEngineBufferTypeGetNameById(de_ctx, x), x, bufdir[x].ts,
2104  bufdir[x].tc);
2105  }
2106  if (ts_excl && tc_excl) {
2107  SCLogError("rule %u mixes keywords with conflicting directions", s->id);
2108  SCReturnInt(0);
2109  } else if (ts_excl) {
2110  SCLogDebug("%u: implied rule direction is toserver", s->id);
2112  SCLogError("rule %u mixes keywords with conflicting directions", s->id);
2113  SCReturnInt(0);
2114  }
2115  } else if (tc_excl) {
2116  SCLogDebug("%u: implied rule direction is toclient", s->id);
2118  SCLogError("rule %u mixes keywords with conflicting directions", s->id);
2119  SCReturnInt(0);
2120  }
2121  } else if (dir_amb) {
2122  SCLogDebug("%u: rule direction cannot be deduced from keywords", s->id);
2123  }
2124 
2125  if ((s->flags & SIG_FLAG_REQUIRE_PACKET) &&
2126  (s->flags & SIG_FLAG_REQUIRE_STREAM)) {
2127  SCLogError("can't mix packet keywords with "
2128  "tcp-stream or flow:only_stream. Invalidating signature.");
2129  SCReturnInt(0);
2130  }
2131 
2133  SCLogError("You seem to have mixed keywords "
2134  "that require inspection in both directions. Atm we only "
2135  "support keywords in one direction within a rule.");
2136  SCReturnInt(0);
2137  }
2138 
2139  if (has_pmatch && has_frame) {
2140  SCLogError("can't mix pure content and frame inspection");
2141  SCReturnInt(0);
2142  }
2143  if (has_app && has_frame) {
2144  SCLogError("can't mix app-layer buffer and frame inspection");
2145  SCReturnInt(0);
2146  }
2147  if (has_pkt && has_frame) {
2148  SCLogError("can't mix pkt buffer and frame inspection");
2149  SCReturnInt(0);
2150  }
2151 
2152  /* TCP: corner cases:
2153  * - pkt vs stream vs depth/offset
2154  * - pkt vs stream vs stream_size
2155  */
2156  if (s->proto.proto[IPPROTO_TCP / 8] & (1 << (IPPROTO_TCP % 8))) {
2160  for (SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_PMATCH]; sm != NULL;
2161  sm = sm->next) {
2162  if (sm->type == DETECT_CONTENT &&
2163  (((DetectContentData *)(sm->ctx))->flags &
2166  break;
2167  }
2168  }
2169  /* if stream_size is in use, also inspect packets */
2170  for (SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_MATCH]; sm != NULL;
2171  sm = sm->next) {
2172  if (sm->type == DETECT_STREAM_SIZE) {
2174  break;
2175  }
2176  }
2177  }
2178  }
2179  }
2180  DetectLuaPostSetup(s);
2181 
2183  s->alproto != ALPROTO_TLS && s->alproto != ALPROTO_QUIC) {
2184  SCLogError("Cannot have ja3/ja4 with protocol %s.", AppProtoToString(s->alproto));
2185  SCReturnInt(0);
2186  }
2187  if ((s->flags & SIG_FLAG_FILESTORE) || s->file_flags != 0 ||
2189  if (s->alproto != ALPROTO_UNKNOWN &&
2190  !AppLayerParserSupportsFiles(IPPROTO_TCP, s->alproto))
2191  {
2192  SCLogError("protocol %s doesn't "
2193  "support file matching",
2195  SCReturnInt(0);
2196  }
2198  SCLogError("protocol HTTP2 doesn't support file name matching");
2199  SCReturnInt(0);
2200  }
2201 
2202  if (s->alproto == ALPROTO_HTTP1 || s->alproto == ALPROTO_HTTP) {
2204  }
2205  }
2206 
2207  SCReturnInt(1);
2208 }
2209 
2210 /**
2211  * \internal
2212  * \brief Helper function for SigInit().
2213  */
2214 static Signature *SigInitHelper(DetectEngineCtx *de_ctx, const char *sigstr,
2215  uint8_t dir)
2216 {
2217  SignatureParser parser;
2218  memset(&parser, 0x00, sizeof(parser));
2219 
2220  Signature *sig = SigAlloc();
2221  if (sig == NULL)
2222  goto error;
2223 
2224  sig->sig_str = SCStrdup(sigstr);
2225  if (unlikely(sig->sig_str == NULL)) {
2226  goto error;
2227  }
2228 
2229  /* default gid to 1 */
2230  sig->gid = 1;
2231 
2232  /* We do a first parse of the rule in a requires, or scan-only
2233  * mode. Syntactic errors will be picked up here, but the only
2234  * part of the rule that is validated completely is the "requires"
2235  * keyword. */
2236  int ret = SigParse(de_ctx, sig, sigstr, dir, &parser, true);
2237  if (ret == -4) {
2238  /* Rule requirements not met. */
2239  de_ctx->sigerror_silent = true;
2240  de_ctx->sigerror_ok = true;
2241  de_ctx->sigerror_requires = true;
2242  goto error;
2243  } else if (ret < 0) {
2244  goto error;
2245  }
2246 
2247  /* Check for a SID before continuuing. */
2248  if (sig->id == 0) {
2249  SCLogError("Signature missing required value \"sid\".");
2250  goto error;
2251  }
2252 
2253  /* Now completely parse the rule. */
2254  ret = SigParse(de_ctx, sig, sigstr, dir, &parser, false);
2255  BUG_ON(ret == -4);
2256  if (ret == -3) {
2257  de_ctx->sigerror_silent = true;
2258  de_ctx->sigerror_ok = true;
2259  goto error;
2260  } else if (ret == -2) {
2261  de_ctx->sigerror_silent = true;
2262  goto error;
2263  } else if (ret < 0) {
2264  goto error;
2265  }
2266 
2267  /* signature priority hasn't been overwritten. Using default priority */
2268  if (sig->prio == -1)
2269  sig->prio = DETECT_DEFAULT_PRIO;
2270 
2271  sig->num = de_ctx->signum;
2272  de_ctx->signum++;
2273 
2274  if (sig->alproto != ALPROTO_UNKNOWN) {
2275  int override_needed = 0;
2276  if (sig->proto.flags & DETECT_PROTO_ANY) {
2277  sig->proto.flags &= ~DETECT_PROTO_ANY;
2278  memset(sig->proto.proto, 0x00, sizeof(sig->proto.proto));
2279  override_needed = 1;
2280  } else {
2281  override_needed = 1;
2282  size_t s = 0;
2283  for (s = 0; s < sizeof(sig->proto.proto); s++) {
2284  if (sig->proto.proto[s] != 0x00) {
2285  override_needed = 0;
2286  break;
2287  }
2288  }
2289  }
2290 
2291  /* at this point if we had alert ip and the ip proto was not
2292  * overridden, we use the ip proto that has been configured
2293  * against the app proto in use. */
2294  if (override_needed)
2296  }
2297 
2298  /* set the packet and app layer flags, but only if the
2299  * app layer flag wasn't already set in which case we
2300  * only consider the app layer */
2301  if (!(sig->flags & SIG_FLAG_APPLAYER)) {
2302  if (sig->init_data->smlists[DETECT_SM_LIST_MATCH] != NULL) {
2304  for ( ; sm != NULL; sm = sm->next) {
2305  if (sigmatch_table[sm->type].Match != NULL)
2307  }
2308  } else {
2310  }
2311  }
2312 
2313  if (!(sig->init_data->init_flags & SIG_FLAG_INIT_FLOW)) {
2314  if ((sig->flags & (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)) == 0) {
2315  sig->flags |= SIG_FLAG_TOSERVER;
2316  sig->flags |= SIG_FLAG_TOCLIENT;
2317  }
2318  }
2319 
2320  SCLogDebug("sig %"PRIu32" SIG_FLAG_APPLAYER: %s, SIG_FLAG_PACKET: %s",
2321  sig->id, sig->flags & SIG_FLAG_APPLAYER ? "set" : "not set",
2322  sig->init_data->init_flags & SIG_FLAG_INIT_PACKET ? "set" : "not set");
2323 
2324  SigBuildAddressMatchArray(sig);
2325 
2326  /* run buffer type callbacks if any */
2327  for (uint32_t x = 0; x < DETECT_SM_LIST_MAX; x++) {
2328  if (sig->init_data->smlists[x])
2330  }
2331  for (uint32_t x = 0; x < sig->init_data->buffer_index; x++) {
2333  }
2334 
2335  SigSetupPrefilter(de_ctx, sig);
2336 
2337  /* validate signature, SigValidate will report the error reason */
2338  if (SigValidate(de_ctx, sig) == 0) {
2339  goto error;
2340  }
2341 
2342  /* check what the type of this sig is */
2343  SignatureSetType(de_ctx, sig);
2344 
2345  if (sig->type == SIG_TYPE_IPONLY) {
2346  /* For IPOnly */
2347  if (IPOnlySigParseAddress(de_ctx, sig, parser.src, SIG_DIREC_SRC ^ dir) < 0)
2348  goto error;
2349 
2350  if (IPOnlySigParseAddress(de_ctx, sig, parser.dst, SIG_DIREC_DST ^ dir) < 0)
2351  goto error;
2352  }
2353  return sig;
2354 
2355 error:
2356  if (sig != NULL) {
2357  SigFree(de_ctx, sig);
2358  }
2359  return NULL;
2360 }
2361 
2362 /**
2363  * \brief Checks if a signature has the same source and destination
2364  * \param s parsed signature
2365  *
2366  * \retval true if source and destination are the same, false otherwise
2367  */
2368 static bool SigHasSameSourceAndDestination(const Signature *s)
2369 {
2370  if (!(s->flags & SIG_FLAG_SP_ANY) || !(s->flags & SIG_FLAG_DP_ANY)) {
2371  if (!DetectPortListsAreEqual(s->sp, s->dp)) {
2372  return false;
2373  }
2374  }
2375 
2376  if (!(s->flags & SIG_FLAG_SRC_ANY) || !(s->flags & SIG_FLAG_DST_ANY)) {
2379 
2381  return false;
2382  }
2383 
2384  src = s->init_data->src->ipv6_head;
2385  dst = s->init_data->dst->ipv6_head;
2386 
2388  return false;
2389  }
2390  }
2391 
2392  return true;
2393 }
2394 
2395 /**
2396  * \brief Parses a signature and adds it to the Detection Engine Context.
2397  *
2398  * \param de_ctx Pointer to the Detection Engine Context.
2399  * \param sigstr Pointer to a character string containing the signature to be
2400  * parsed.
2401  *
2402  * \retval Pointer to the Signature instance on success; NULL on failure.
2403  */
2404 Signature *SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
2405 {
2406  SCEnter();
2407 
2408  uint32_t oldsignum = de_ctx->signum;
2409  de_ctx->sigerror_ok = false;
2410  de_ctx->sigerror_silent = false;
2411  de_ctx->sigerror_requires = false;
2412 
2413  Signature *sig;
2414 
2415  if ((sig = SigInitHelper(de_ctx, sigstr, SIG_DIREC_NORMAL)) == NULL) {
2416  goto error;
2417  }
2418 
2420  if (SigHasSameSourceAndDestination(sig)) {
2421  SCLogInfo("Rule with ID %u is bidirectional, but source and destination are the same, "
2422  "treating the rule as unidirectional", sig->id);
2423 
2425  } else {
2426  sig->next = SigInitHelper(de_ctx, sigstr, SIG_DIREC_SWITCHED);
2427  if (sig->next == NULL) {
2428  goto error;
2429  }
2430  }
2431  }
2432 
2433  SCReturnPtr(sig, "Signature");
2434 
2435 error:
2436  if (sig != NULL) {
2437  SigFree(de_ctx, sig);
2438  }
2439  /* if something failed, restore the old signum count
2440  * since we didn't install it */
2441  de_ctx->signum = oldsignum;
2442 
2443  SCReturnPtr(NULL, "Signature");
2444 }
2445 
2446 /**
2447  * \brief The hash free function to be the used by the hash table -
2448  * DetectEngineCtx->dup_sig_hash_table.
2449  *
2450  * \param data Pointer to the data, in our case SigDuplWrapper to be freed.
2451  */
2452 static void DetectParseDupSigFreeFunc(void *data)
2453 {
2454  if (data != NULL)
2455  SCFree(data);
2456 }
2457 
2458 /**
2459  * \brief The hash function to be the used by the hash table -
2460  * DetectEngineCtx->dup_sig_hash_table.
2461  *
2462  * \param ht Pointer to the hash table.
2463  * \param data Pointer to the data, in our case SigDuplWrapper.
2464  * \param datalen Not used in our case.
2465  *
2466  * \retval sw->s->id The generated hash value.
2467  */
2468 static uint32_t DetectParseDupSigHashFunc(HashListTable *ht, void *data, uint16_t datalen)
2469 {
2470  SigDuplWrapper *sw = (SigDuplWrapper *)data;
2471 
2472  return (sw->s->id % ht->array_size);
2473 }
2474 
2475 /**
2476  * \brief The Compare function to be used by the hash table -
2477  * DetectEngineCtx->dup_sig_hash_table.
2478  *
2479  * \param data1 Pointer to the first SigDuplWrapper.
2480  * \param len1 Not used.
2481  * \param data2 Pointer to the second SigDuplWrapper.
2482  * \param len2 Not used.
2483  *
2484  * \retval 1 If the 2 SigDuplWrappers sent as args match.
2485  * \retval 0 If the 2 SigDuplWrappers sent as args do not match.
2486  */
2487 static char DetectParseDupSigCompareFunc(void *data1, uint16_t len1, void *data2,
2488  uint16_t len2)
2489 {
2490  SigDuplWrapper *sw1 = (SigDuplWrapper *)data1;
2491  SigDuplWrapper *sw2 = (SigDuplWrapper *)data2;
2492 
2493  if (sw1 == NULL || sw2 == NULL ||
2494  sw1->s == NULL || sw2->s == NULL)
2495  return 0;
2496 
2497  /* sid and gid match required */
2498  if (sw1->s->id == sw2->s->id && sw1->s->gid == sw2->s->gid) return 1;
2499 
2500  return 0;
2501 }
2502 
2503 /**
2504  * \brief Initializes the hash table that is used to cull duplicate sigs.
2505  *
2506  * \param de_ctx Pointer to the detection engine context.
2507  *
2508  * \retval 0 On success.
2509  * \retval -1 On failure.
2510  */
2512 {
2514  DetectParseDupSigHashFunc,
2515  DetectParseDupSigCompareFunc,
2516  DetectParseDupSigFreeFunc);
2517  if (de_ctx->dup_sig_hash_table == NULL)
2518  return -1;
2519 
2520  return 0;
2521 }
2522 
2523 /**
2524  * \brief Frees the hash table that is used to cull duplicate sigs.
2525  *
2526  * \param de_ctx Pointer to the detection engine context that holds this table.
2527  */
2529 {
2530  if (de_ctx->dup_sig_hash_table != NULL)
2532 
2533  de_ctx->dup_sig_hash_table = NULL;
2534 }
2535 
2536 /**
2537  * \brief Check if a signature is a duplicate.
2538  *
2539  * There are 3 types of return values for this function.
2540  *
2541  * - 0, which indicates that the Signature is not a duplicate
2542  * and has to be added to the detection engine list.
2543  * - 1, Signature is duplicate, and the existing signature in
2544  * the list shouldn't be replaced with this duplicate.
2545  * - 2, Signature is duplicate, and the existing signature in
2546  * the list should be replaced with this duplicate.
2547  *
2548  * \param de_ctx Pointer to the detection engine context.
2549  * \param sig Pointer to the Signature that has to be checked.
2550  *
2551  * \retval 2 If Signature is duplicate and the existing signature in
2552  * the list should be chucked out and replaced with this.
2553  * \retval 1 If Signature is duplicate, and should be chucked out.
2554  * \retval 0 If Signature is not a duplicate.
2555  */
2556 static inline int DetectEngineSignatureIsDuplicate(DetectEngineCtx *de_ctx,
2557  Signature *sig)
2558 {
2559  /* we won't do any NULL checks on the args */
2560 
2561  /* return value */
2562  int ret = 0;
2563 
2564  SigDuplWrapper *sw_dup = NULL;
2565  SigDuplWrapper *sw = NULL;
2566 
2567  /* used for making a duplicate_sig_hash_table entry */
2568  sw = SCCalloc(1, sizeof(SigDuplWrapper));
2569  if (unlikely(sw == NULL)) {
2570  exit(EXIT_FAILURE);
2571  }
2572  sw->s = sig;
2573 
2574  /* check if we have a duplicate entry for this signature */
2575  sw_dup = HashListTableLookup(de_ctx->dup_sig_hash_table, (void *)sw, 0);
2576  /* we don't have a duplicate entry for this sig */
2577  if (sw_dup == NULL) {
2578  /* add it to the hash table */
2579  HashListTableAdd(de_ctx->dup_sig_hash_table, (void *)sw, 0);
2580 
2581  /* add the s_prev entry for the previously loaded sw in the hash_table */
2582  if (de_ctx->sig_list != NULL) {
2583  SigDuplWrapper *sw_old = NULL;
2584  SigDuplWrapper sw_tmp;
2585  memset(&sw_tmp, 0, sizeof(SigDuplWrapper));
2586 
2587  /* the topmost sig would be the last loaded sig */
2588  sw_tmp.s = de_ctx->sig_list;
2590  (void *)&sw_tmp, 0);
2591  /* sw_old == NULL case is impossible */
2592  sw_old->s_prev = sig;
2593  }
2594 
2595  ret = 0;
2596  goto end;
2597  }
2598 
2599  /* if we have reached here we have a duplicate entry for this signature.
2600  * Check the signature revision. Store the signature with the latest rev
2601  * and discard the other one */
2602  if (sw->s->rev <= sw_dup->s->rev) {
2603  ret = 1;
2604  SCFree(sw);
2605  sw = NULL;
2606  goto end;
2607  }
2608 
2609  /* the new sig is of a newer revision than the one that is already in the
2610  * list. Remove the old sig from the list */
2611  if (sw_dup->s_prev == NULL) {
2612  SigDuplWrapper sw_temp;
2613  memset(&sw_temp, 0, sizeof(SigDuplWrapper));
2614  if (sw_dup->s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2615  sw_temp.s = sw_dup->s->next->next;
2616  de_ctx->sig_list = sw_dup->s->next->next;
2617  SigFree(de_ctx, sw_dup->s->next);
2618  } else {
2619  sw_temp.s = sw_dup->s->next;
2620  de_ctx->sig_list = sw_dup->s->next;
2621  }
2622  SigDuplWrapper *sw_next = NULL;
2623  if (sw_temp.s != NULL) {
2625  (void *)&sw_temp, 0);
2626  sw_next->s_prev = sw_dup->s_prev;
2627  }
2628  SigFree(de_ctx, sw_dup->s);
2629  } else {
2630  SigDuplWrapper sw_temp;
2631  memset(&sw_temp, 0, sizeof(SigDuplWrapper));
2632  if (sw_dup->s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2633  sw_temp.s = sw_dup->s->next->next;
2634  /* If previous signature is bidirectional,
2635  * it has 2 items in the linked list.
2636  * So we need to change next->next instead of next
2637  */
2639  sw_dup->s_prev->next->next = sw_dup->s->next->next;
2640  } else {
2641  sw_dup->s_prev->next = sw_dup->s->next->next;
2642  }
2643  SigFree(de_ctx, sw_dup->s->next);
2644  } else {
2645  sw_temp.s = sw_dup->s->next;
2647  sw_dup->s_prev->next->next = sw_dup->s->next;
2648  } else {
2649  sw_dup->s_prev->next = sw_dup->s->next;
2650  }
2651  }
2652  SigDuplWrapper *sw_next = NULL;
2653  if (sw_temp.s != NULL) {
2655  (void *)&sw_temp, 0);
2656  sw_next->s_prev = sw_dup->s_prev;
2657  }
2658  SigFree(de_ctx, sw_dup->s);
2659  }
2660 
2661  /* make changes to the entry to reflect the presence of the new sig */
2662  sw_dup->s = sig;
2663  sw_dup->s_prev = NULL;
2664 
2665  if (de_ctx->sig_list != NULL) {
2666  SigDuplWrapper sw_tmp;
2667  memset(&sw_tmp, 0, sizeof(SigDuplWrapper));
2668  sw_tmp.s = de_ctx->sig_list;
2670  (void *)&sw_tmp, 0);
2671  if (sw_old->s != sw_dup->s) {
2672  // Link on top of the list if there was another element
2673  sw_old->s_prev = sig;
2674  }
2675  }
2676 
2677  /* this is duplicate, but a duplicate that replaced the existing sig entry */
2678  ret = 2;
2679 
2680  SCFree(sw);
2681 
2682 end:
2683  return ret;
2684 }
2685 
2686 /**
2687  * \brief Parse and append a Signature into the Detection Engine Context
2688  * signature list.
2689  *
2690  * If the signature is bidirectional it should append two signatures
2691  * (with the addresses switched) into the list. Also handle duplicate
2692  * signatures. In case of duplicate sigs, use the ones that have the
2693  * latest revision. We use the sid and the msg to identify duplicate
2694  * sigs. If 2 sigs have the same sid and gid, they are duplicates.
2695  *
2696  * \param de_ctx Pointer to the Detection Engine Context.
2697  * \param sigstr Pointer to a character string containing the signature to be
2698  * parsed.
2699  * \param sig_file Pointer to a character string containing the filename from
2700  * which signature is read
2701  * \param lineno Line number from where signature is read
2702  *
2703  * \retval Pointer to the head Signature in the detection engine ctx sig_list
2704  * on success; NULL on failure.
2705  */
2707 {
2708  Signature *sig = SigInit(de_ctx, sigstr);
2709  if (sig == NULL) {
2710  return NULL;
2711  }
2712 
2713  /* checking for the status of duplicate signature */
2714  int dup_sig = DetectEngineSignatureIsDuplicate(de_ctx, sig);
2715  /* a duplicate signature that should be chucked out. Check the previously
2716  * called function details to understand the different return values */
2717  if (dup_sig == 1) {
2718  SCLogError("Duplicate signature \"%s\"", sigstr);
2719  goto error;
2720  } else if (dup_sig == 2) {
2721  SCLogWarning("Signature with newer revision,"
2722  " so the older sig replaced by this new signature \"%s\"",
2723  sigstr);
2724  }
2725 
2727  if (sig->next != NULL) {
2728  sig->next->next = de_ctx->sig_list;
2729  } else {
2730  goto error;
2731  }
2732  } else {
2733  /* if this sig is the first one, sig_list should be null */
2734  sig->next = de_ctx->sig_list;
2735  }
2736 
2737  de_ctx->sig_list = sig;
2738 
2739  /**
2740  * In DetectEngineAppendSig(), the signatures are prepended and we always return the first one
2741  * so if the signature is bidirectional, the returned sig will point through "next" ptr
2742  * to the cloned signatures with the switched addresses
2743  */
2744  return (dup_sig == 0 || dup_sig == 2) ? sig : NULL;
2745 
2746 error:
2747  /* free the 2nd sig bidir may have set up */
2748  if (sig != NULL && sig->next != NULL) {
2749  SigFree(de_ctx, sig->next);
2750  sig->next = NULL;
2751  }
2752  if (sig != NULL) {
2753  SigFree(de_ctx, sig);
2754  }
2755  return NULL;
2756 }
2757 
2758 static DetectParseRegex *g_detect_parse_regex_list = NULL;
2759 
2760 int DetectParsePcreExec(DetectParseRegex *parse_regex, pcre2_match_data **match, const char *str,
2761  int start_offset, int options)
2762 {
2763  *match = pcre2_match_data_create_from_pattern(parse_regex->regex, NULL);
2764  if (*match)
2765  return pcre2_match(parse_regex->regex, (PCRE2_SPTR8)str, strlen(str), options, start_offset,
2766  *match, parse_regex->context);
2767  return -1;
2768 }
2769 
2771 {
2772  if (r->regex) {
2773  pcre2_code_free(r->regex);
2774  }
2775  if (r->context) {
2776  pcre2_match_context_free(r->context);
2777  }
2778 }
2779 
2781 {
2782  DetectParseRegex *r = g_detect_parse_regex_list;
2783  while (r) {
2784  DetectParseRegex *next = r->next;
2785 
2787 
2788  SCFree(r);
2789  r = next;
2790  }
2791  g_detect_parse_regex_list = NULL;
2792 }
2793 
2794 /** \brief add regex and/or study to at exit free list
2795  */
2797 {
2798  DetectParseRegex *r = SCCalloc(1, sizeof(*r));
2799  if (r == NULL) {
2800  FatalError("failed to alloc memory for pcre free list");
2801  }
2802  r->regex = detect_parse->regex;
2803  r->next = g_detect_parse_regex_list;
2804  g_detect_parse_regex_list = r;
2805 }
2806 
2807 bool DetectSetupParseRegexesOpts(const char *parse_str, DetectParseRegex *detect_parse, int opts)
2808 {
2809  int en;
2810  PCRE2_SIZE eo;
2811 
2812  detect_parse->regex =
2813  pcre2_compile((PCRE2_SPTR8)parse_str, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
2814  if (detect_parse->regex == NULL) {
2815  PCRE2_UCHAR errbuffer[256];
2816  pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
2817  SCLogError("pcre compile of \"%s\" failed at "
2818  "offset %d: %s",
2819  parse_str, en, errbuffer);
2820  return false;
2821  }
2822  detect_parse->context = pcre2_match_context_create(NULL);
2823  if (detect_parse->context == NULL) {
2824  SCLogError("pcre2 could not create match context");
2825  pcre2_code_free(detect_parse->regex);
2826  detect_parse->regex = NULL;
2827  return false;
2828  }
2829  pcre2_set_match_limit(detect_parse->context, SC_MATCH_LIMIT_DEFAULT);
2830  pcre2_set_recursion_limit(detect_parse->context, SC_MATCH_LIMIT_RECURSION_DEFAULT);
2831  DetectParseRegexAddToFreeList(detect_parse);
2832 
2833  return true;
2834 }
2835 
2836 DetectParseRegex *DetectSetupPCRE2(const char *parse_str, int opts)
2837 {
2838  int en;
2839  PCRE2_SIZE eo;
2840  DetectParseRegex *detect_parse = SCCalloc(1, sizeof(DetectParseRegex));
2841  if (detect_parse == NULL) {
2842  return NULL;
2843  }
2844 
2845  detect_parse->regex =
2846  pcre2_compile((PCRE2_SPTR8)parse_str, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
2847  if (detect_parse->regex == NULL) {
2848  PCRE2_UCHAR errbuffer[256];
2849  pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
2850  SCLogError("pcre2 compile of \"%s\" failed at "
2851  "offset %d: %s",
2852  parse_str, (int)eo, errbuffer);
2853  SCFree(detect_parse);
2854  return NULL;
2855  }
2856 
2857  detect_parse->next = g_detect_parse_regex_list;
2858  g_detect_parse_regex_list = detect_parse;
2859  return detect_parse;
2860 }
2861 
2863  pcre2_match_data *match_data, uint32_t number, PCRE2_UCHAR *buffer, PCRE2_SIZE *bufflen)
2864 {
2865  int r = pcre2_substring_copy_bynumber(match_data, number, buffer, bufflen);
2866  if (r == PCRE2_ERROR_UNSET) {
2867  buffer[0] = 0;
2868  *bufflen = 0;
2869  return 0;
2870  }
2871  return r;
2872 }
2873 
2875  pcre2_match_data *match_data, uint32_t number, PCRE2_UCHAR **bufferptr, PCRE2_SIZE *bufflen)
2876 {
2877  int r = pcre2_substring_get_bynumber(match_data, number, bufferptr, bufflen);
2878  if (r == PCRE2_ERROR_UNSET) {
2879  *bufferptr = NULL;
2880  *bufflen = 0;
2881  return 0;
2882  }
2883  return r;
2884 }
2885 
2886 void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
2887 {
2888  if (!DetectSetupParseRegexesOpts(parse_str, detect_parse, 0)) {
2889  FatalError("pcre compile and study failed");
2890  }
2891 }
2892 
2893 
2894 /*
2895  * TESTS
2896  */
2897 
2898 #ifdef UNITTESTS
2899 #include "detect-engine-alert.h"
2900 #include "packet.h"
2901 
2902 static int SigParseTest01 (void)
2903 {
2904  int result = 1;
2905  Signature *sig = NULL;
2906 
2908  if (de_ctx == NULL)
2909  goto end;
2910 
2911  sig = SigInit(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1;)");
2912  if (sig == NULL)
2913  result = 0;
2914 
2915 end:
2916  if (sig != NULL) SigFree(de_ctx, sig);
2917  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2918  return result;
2919 }
2920 
2921 static int SigParseTest02 (void)
2922 {
2923  int result = 0;
2924  Signature *sig = NULL;
2925  DetectPort *port = NULL;
2926 
2928 
2929  if (de_ctx == NULL)
2930  goto end;
2931 
2934 
2935  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;)");
2936  if (sig == NULL) {
2937  goto end;
2938  }
2939 
2940  int r = DetectPortParse(de_ctx, &port, "0:20");
2941  if (r < 0)
2942  goto end;
2943 
2944  if (DetectPortCmp(sig->sp, port) == PORT_EQ) {
2945  result = 1;
2946  } else {
2947  DetectPortPrint(port); printf(" != "); DetectPortPrint(sig->sp); printf(": ");
2948  }
2949 
2950 end:
2951  if (port != NULL)
2953  if (sig != NULL)
2954  SigFree(de_ctx, sig);
2955  if (de_ctx != NULL)
2957  return result;
2958 }
2959 
2960 /**
2961  * \test SigParseTest03 test for invalid direction operator in rule
2962  */
2963 static int SigParseTest03 (void)
2964 {
2965  int result = 1;
2966  Signature *sig = NULL;
2967 
2969  if (de_ctx == NULL)
2970  goto end;
2971 
2972  sig = SigInit(de_ctx, "alert tcp 1.2.3.4 any <- !1.2.3.4 any (msg:\"SigParseTest03\"; sid:1;)");
2973  if (sig != NULL) {
2974  result = 0;
2975  printf("expected NULL got sig ptr %p: ",sig);
2976  }
2977 
2978 end:
2979  if (sig != NULL) SigFree(de_ctx, sig);
2980  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2981  return result;
2982 }
2983 
2984 static int SigParseTest04 (void)
2985 {
2986  int result = 1;
2987  Signature *sig = NULL;
2988 
2990  if (de_ctx == NULL)
2991  goto end;
2992 
2993  sig = SigInit(de_ctx, "alert tcp 1.2.3.4 1024: -> !1.2.3.4 1024: (msg:\"SigParseTest04\"; sid:1;)");
2994  if (sig == NULL)
2995  result = 0;
2996 
2997 end:
2998  if (sig != NULL) SigFree(de_ctx, sig);
2999  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3000  return result;
3001 }
3002 
3003 /** \test Port validation */
3004 static int SigParseTest05 (void)
3005 {
3006  int result = 0;
3007  Signature *sig = NULL;
3008 
3010  if (de_ctx == NULL)
3011  goto end;
3012 
3013  sig = SigInit(de_ctx, "alert tcp 1.2.3.4 1024:65536 -> !1.2.3.4 any (msg:\"SigParseTest05\"; sid:1;)");
3014  if (sig == NULL) {
3015  result = 1;
3016  } else {
3017  printf("signature didn't fail to parse as we expected: ");
3018  }
3019 
3020 end:
3021  if (sig != NULL) SigFree(de_ctx, sig);
3022  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3023  return result;
3024 }
3025 
3026 /** \test Parsing bug debugging at 2010-03-18 */
3027 static int SigParseTest06 (void)
3028 {
3029  int result = 0;
3030  Signature *sig = NULL;
3031 
3033  if (de_ctx == NULL)
3034  goto end;
3035 
3036  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;)");
3037  if (sig != NULL) {
3038  result = 1;
3039  } else {
3040  printf("signature failed to parse: ");
3041  }
3042 
3043 end:
3044  if (sig != NULL)
3045  SigFree(de_ctx, sig);
3046  if (de_ctx != NULL)
3048  return result;
3049 }
3050 
3051 /**
3052  * \test Parsing duplicate sigs.
3053  */
3054 static int SigParseTest07(void)
3055 {
3056  int result = 0;
3057 
3059  if (de_ctx == NULL)
3060  goto end;
3061 
3062  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
3063  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
3064 
3065  result = (de_ctx->sig_list != NULL && de_ctx->sig_list->next == NULL);
3066 
3067 end:
3068  if (de_ctx != NULL)
3070  return result;
3071 }
3072 
3073 /**
3074  * \test Parsing duplicate sigs.
3075  */
3076 static int SigParseTest08(void)
3077 {
3078  int result = 0;
3079 
3081  if (de_ctx == NULL)
3082  goto end;
3083 
3084  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
3085  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:2;)");
3086 
3087  result = (de_ctx->sig_list != NULL && de_ctx->sig_list->next == NULL &&
3088  de_ctx->sig_list->rev == 2);
3089 
3090 end:
3091  if (de_ctx != NULL)
3093  return result;
3094 }
3095 
3096 /**
3097  * \test Parsing duplicate sigs.
3098  */
3099 static int SigParseTest09(void)
3100 {
3101  int result = 1;
3102 
3104  if (de_ctx == NULL)
3105  goto end;
3106 
3107  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
3108  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:2;)");
3109  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:6;)");
3110  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:4;)");
3111  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:2;)");
3112  result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
3113  de_ctx->sig_list->rev == 2);
3114  if (result == 0)
3115  goto end;
3116  result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
3117  de_ctx->sig_list->next->rev == 6);
3118  if (result == 0)
3119  goto end;
3120 
3121  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:1;)");
3122  result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
3123  de_ctx->sig_list->rev == 2);
3124  if (result == 0)
3125  goto end;
3126  result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
3127  de_ctx->sig_list->next->rev == 6);
3128  if (result == 0)
3129  goto end;
3130 
3131  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:4;)");
3132  result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
3133  de_ctx->sig_list->rev == 4);
3134  if (result == 0)
3135  goto end;
3136  result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
3137  de_ctx->sig_list->next->rev == 6);
3138  if (result == 0)
3139  goto end;
3140 
3141 end:
3142  if (de_ctx != NULL)
3144  return result;
3145 }
3146 
3147 /**
3148  * \test Parsing duplicate sigs.
3149  */
3150 static int SigParseTest10(void)
3151 {
3152  int result = 1;
3153 
3155  if (de_ctx == NULL)
3156  goto end;
3157 
3158  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
3159  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:1;)");
3160  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:3; rev:1;)");
3161  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:4; rev:1;)");
3162  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:5; rev:1;)");
3163  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:3; rev:2;)");
3164  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:2;)");
3165 
3166  result &= ((de_ctx->sig_list->id == 2) &&
3167  (de_ctx->sig_list->next->id == 3) &&
3168  (de_ctx->sig_list->next->next->id == 5) &&
3169  (de_ctx->sig_list->next->next->next->id == 4) &&
3170  (de_ctx->sig_list->next->next->next->next->id == 1));
3171 
3172 end:
3173  if (de_ctx != NULL)
3175  return result;
3176 }
3177 
3178 /**
3179  * \test Parsing sig with trailing space(s) as reported by
3180  * Morgan Cox on oisf-users.
3181  */
3182 static int SigParseTest11(void)
3183 {
3184  int result = 0;
3185 
3187  if (de_ctx == NULL)
3188  goto end;
3189 
3190  Signature *s = NULL;
3191 
3193  "drop tcp any any -> any 80 (msg:\"Snort_Inline is blocking the http link\"; sid:1;) ");
3194  if (s == NULL) {
3195  printf("sig 1 didn't parse: ");
3196  goto end;
3197  }
3198 
3199  s = DetectEngineAppendSig(de_ctx, "drop tcp any any -> any 80 (msg:\"Snort_Inline is blocking "
3200  "the http link\"; sid:2;) ");
3201  if (s == NULL) {
3202  printf("sig 2 didn't parse: ");
3203  goto end;
3204  }
3205 
3206  result = 1;
3207 end:
3208  if (de_ctx != NULL)
3210  return result;
3211 }
3212 
3213 /**
3214  * \test file_data with rawbytes
3215  */
3216 static int SigParseTest12(void)
3217 {
3218  int result = 0;
3219 
3221  if (de_ctx == NULL)
3222  goto end;
3223 
3224  Signature *s = NULL;
3225 
3226  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (file_data; content:\"abc\"; rawbytes; sid:1;)");
3227  if (s != NULL) {
3228  printf("sig 1 should have given an error: ");
3229  goto end;
3230  }
3231 
3232  result = 1;
3233 end:
3234  if (de_ctx != NULL)
3236  return result;
3237 }
3238 
3239 /**
3240  * \test packet/stream sig
3241  */
3242 static int SigParseTest13(void)
3243 {
3244  int result = 0;
3245 
3247  if (de_ctx == NULL)
3248  goto end;
3249 
3250  Signature *s = NULL;
3251 
3252  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; sid:1;)");
3253  if (s == NULL) {
3254  printf("sig 1 invalidated: failure");
3255  goto end;
3256  }
3257 
3258  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
3259  printf("sig doesn't have stream flag set\n");
3260  goto end;
3261  }
3262 
3263  if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
3264  printf("sig has packet flag set\n");
3265  goto end;
3266  }
3267 
3268  result = 1;
3269 
3270 end:
3271  if (de_ctx != NULL)
3273  return result;
3274 }
3275 
3276 /**
3277  * \test packet/stream sig
3278  */
3279 static int SigParseTest14(void)
3280 {
3281  int result = 0;
3282 
3284  if (de_ctx == NULL)
3285  goto end;
3286 
3287  Signature *s = NULL;
3288 
3289  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; dsize:>0; sid:1;)");
3290  if (s == NULL) {
3291  printf("sig 1 invalidated: failure");
3292  goto end;
3293  }
3294 
3295  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
3296  printf("sig doesn't have packet flag set\n");
3297  goto end;
3298  }
3299 
3300  if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
3301  printf("sig has stream flag set\n");
3302  goto end;
3303  }
3304 
3305  result = 1;
3306 
3307 end:
3308  if (de_ctx != NULL)
3310  return result;
3311 }
3312 
3313 /**
3314  * \test packet/stream sig
3315  */
3316 static int SigParseTest15(void)
3317 {
3318  int result = 0;
3319 
3321  if (de_ctx == NULL)
3322  goto end;
3323 
3324  Signature *s = NULL;
3325 
3326  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:5; sid:1;)");
3327  if (s == NULL) {
3328  printf("sig 1 invalidated: failure");
3329  goto end;
3330  }
3331 
3332  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
3333  printf("sig doesn't have packet flag set\n");
3334  goto end;
3335  }
3336 
3337  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
3338  printf("sig doesn't have stream flag set\n");
3339  goto end;
3340  }
3341 
3342  result = 1;
3343 
3344 end:
3345  if (de_ctx != NULL)
3347  return result;
3348 }
3349 
3350 /**
3351  * \test packet/stream sig
3352  */
3353 static int SigParseTest16(void)
3354 {
3355  int result = 0;
3356 
3358  if (de_ctx == NULL)
3359  goto end;
3360 
3361  Signature *s = NULL;
3362 
3363  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; depth:5; sid:1;)");
3364  if (s == NULL) {
3365  printf("sig 1 invalidated: failure");
3366  goto end;
3367  }
3368 
3369  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
3370  printf("sig doesn't have packet flag set\n");
3371  goto end;
3372  }
3373 
3374  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
3375  printf("sig doesn't have stream flag set\n");
3376  goto end;
3377  }
3378 
3379  result = 1;
3380 
3381 end:
3382  if (de_ctx != NULL)
3384  return result;
3385 }
3386 
3387 /**
3388  * \test packet/stream sig
3389  */
3390 static int SigParseTest17(void)
3391 {
3392  int result = 0;
3393 
3395  if (de_ctx == NULL)
3396  goto end;
3397 
3398  Signature *s = NULL;
3399 
3400  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:1; depth:5; sid:1;)");
3401  if (s == NULL) {
3402  printf("sig 1 invalidated: failure");
3403  goto end;
3404  }
3405 
3406  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
3407  printf("sig doesn't have packet flag set\n");
3408  goto end;
3409  }
3410 
3411  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
3412  printf("sig doesn't have stream flag set\n");
3413  goto end;
3414  }
3415 
3416  result = 1;
3417 
3418 end:
3419  if (de_ctx != NULL)
3421  return result;
3422 }
3423 
3424 /** \test sid value too large. Bug #779 */
3425 static int SigParseTest18 (void)
3426 {
3427  int result = 0;
3428 
3430  if (de_ctx == NULL)
3431  goto end;
3432 
3433  if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:99999999999999999999;)") != NULL)
3434  goto end;
3435 
3436  result = 1;
3437 end:
3438  if (de_ctx != NULL)
3440  return result;
3441 }
3442 
3443 /** \test gid value too large. Related to bug #779 */
3444 static int SigParseTest19 (void)
3445 {
3446  int result = 0;
3447 
3449  if (de_ctx == NULL)
3450  goto end;
3451 
3452  if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1; gid:99999999999999999999;)") != NULL)
3453  goto end;
3454 
3455  result = 1;
3456 end:
3457  if (de_ctx != NULL)
3459  return result;
3460 }
3461 
3462 /** \test rev value too large. Related to bug #779 */
3463 static int SigParseTest20 (void)
3464 {
3465  int result = 0;
3466 
3468  if (de_ctx == NULL)
3469  goto end;
3470 
3471  if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1; rev:99999999999999999999;)") != NULL)
3472  goto end;
3473 
3474  result = 1;
3475 end:
3476  if (de_ctx != NULL)
3478  return result;
3479 }
3480 
3481 /** \test address parsing */
3482 static int SigParseTest21 (void)
3483 {
3484  int result = 0;
3485 
3487  if (de_ctx == NULL)
3488  goto end;
3489 
3490  if (DetectEngineAppendSig(de_ctx, "alert tcp [1.2.3.4, 1.2.3.5] any -> !1.2.3.4 any (sid:1;)") == NULL)
3491  goto end;
3492 
3493  result = 1;
3494 end:
3495  if (de_ctx != NULL)
3497  return result;
3498 }
3499 
3500 /** \test address parsing */
3501 static int SigParseTest22 (void)
3502 {
3503  int result = 0;
3504 
3506  if (de_ctx == NULL)
3507  goto end;
3508 
3509  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)
3510  goto end;
3511 
3512  result = 1;
3513 end:
3514  if (de_ctx != NULL)
3516  return result;
3517 }
3518 
3519 /**
3520  * \test rule ending in carriage return
3521  */
3522 static int SigParseTest23(void)
3523 {
3526 
3527  Signature *s = NULL;
3528 
3529  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:1; depth:5; sid:1;)\r");
3530  FAIL_IF_NULL(s);
3531 
3533  PASS;
3534 }
3535 
3536 /** \test Direction operator validation (invalid) */
3537 static int SigParseBidirecTest06 (void)
3538 {
3539  int result = 1;
3540  Signature *sig = NULL;
3541 
3543  if (de_ctx == NULL)
3544  goto end;
3545 
3546  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any - 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3547  if (sig == NULL)
3548  result = 1;
3549 
3550 end:
3551  if (sig != NULL) SigFree(de_ctx, sig);
3552  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3553  return result;
3554 }
3555 
3556 /** \test Direction operator validation (invalid) */
3557 static int SigParseBidirecTest07 (void)
3558 {
3559  int result = 1;
3560  Signature *sig = NULL;
3561 
3563  if (de_ctx == NULL)
3564  goto end;
3565 
3566  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <- 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3567  if (sig == NULL)
3568  result = 1;
3569 
3570 end:
3571  if (sig != NULL) SigFree(de_ctx, sig);
3572  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3573  return result;
3574 }
3575 
3576 /** \test Direction operator validation (invalid) */
3577 static int SigParseBidirecTest08 (void)
3578 {
3579  int result = 1;
3580  Signature *sig = NULL;
3581 
3583  if (de_ctx == NULL)
3584  goto end;
3585 
3586  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any < 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3587  if (sig == NULL)
3588  result = 1;
3589 
3590 end:
3591  if (sig != NULL) SigFree(de_ctx, sig);
3592  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3593  return result;
3594 }
3595 
3596 /** \test Direction operator validation (invalid) */
3597 static int SigParseBidirecTest09 (void)
3598 {
3599  int result = 1;
3600  Signature *sig = NULL;
3601 
3603  if (de_ctx == NULL)
3604  goto end;
3605 
3606  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any > 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3607  if (sig == NULL)
3608  result = 1;
3609 
3610 end:
3611  if (sig != NULL) SigFree(de_ctx, sig);
3612  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3613  return result;
3614 }
3615 
3616 /** \test Direction operator validation (invalid) */
3617 static int SigParseBidirecTest10 (void)
3618 {
3619  int result = 1;
3620  Signature *sig = NULL;
3621 
3623  if (de_ctx == NULL)
3624  goto end;
3625 
3626  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -< 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3627  if (sig == NULL)
3628  result = 1;
3629 
3630 end:
3631  if (sig != NULL) SigFree(de_ctx, sig);
3632  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3633  return result;
3634 }
3635 
3636 /** \test Direction operator validation (invalid) */
3637 static int SigParseBidirecTest11 (void)
3638 {
3639  int result = 1;
3640  Signature *sig = NULL;
3641 
3643  if (de_ctx == NULL)
3644  goto end;
3645 
3646  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any >- 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3647  if (sig == NULL)
3648  result = 1;
3649 
3650 end:
3651  if (sig != NULL) SigFree(de_ctx, sig);
3652  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3653  return result;
3654 }
3655 
3656 /** \test Direction operator validation (invalid) */
3657 static int SigParseBidirecTest12 (void)
3658 {
3659  int result = 1;
3660  Signature *sig = NULL;
3661 
3663  if (de_ctx == NULL)
3664  goto end;
3665 
3666  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any >< 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3667  if (sig == NULL)
3668  result = 1;
3669 
3670 end:
3671  if (sig != NULL) SigFree(de_ctx, sig);
3672  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3673  return result;
3674 }
3675 
3676 /** \test Direction operator validation (valid) */
3677 static int SigParseBidirecTest13 (void)
3678 {
3679  int result = 1;
3680  Signature *sig = NULL;
3681 
3683  if (de_ctx == NULL)
3684  goto end;
3685 
3686  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <> 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3687  if (sig != NULL)
3688  result = 1;
3689 
3690 end:
3691  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3692  return result;
3693 }
3694 
3695 /** \test Direction operator validation (valid) */
3696 static int SigParseBidirecTest14 (void)
3697 {
3698  int result = 1;
3699  Signature *sig = NULL;
3700 
3702  if (de_ctx == NULL)
3703  goto end;
3704 
3705  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3706  if (sig != NULL)
3707  result = 1;
3708 
3709 end:
3710  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3711  return result;
3712 }
3713 
3714 /** \test Ensure that we don't set bidirectional in a
3715  * normal (one direction) Signature
3716  */
3717 static int SigTestBidirec01 (void)
3718 {
3719  Signature *sig = NULL;
3720  int result = 0;
3721 
3723  if (de_ctx == NULL)
3724  goto end;
3725 
3726  sig = DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 1024:65535 -> !1.2.3.4 any (msg:\"SigTestBidirec01\"; sid:1;)");
3727  if (sig == NULL)
3728  goto end;
3729  if (sig->next != NULL)
3730  goto end;
3732  goto end;
3733  if (de_ctx->signum != 1)
3734  goto end;
3735 
3736  result = 1;
3737 
3738 end:
3739  if (de_ctx != NULL) {
3743  }
3744  return result;
3745 }
3746 
3747 /** \test Ensure that we set a bidirectional Signature correctly */
3748 static int SigTestBidirec02 (void)
3749 {
3750  int result = 0;
3751  Signature *sig = NULL;
3752  Signature *copy = NULL;
3753 
3755  if (de_ctx == NULL)
3756  goto end;
3757 
3758  de_ctx->flags |= DE_QUIET;
3759 
3760  sig = DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 1024:65535 <> !1.2.3.4 any (msg:\"SigTestBidirec02\"; sid:1;)");
3761  if (sig == NULL)
3762  goto end;
3763  if (de_ctx->sig_list != sig)
3764  goto end;
3766  goto end;
3767  if (sig->next == NULL)
3768  goto end;
3769  if (de_ctx->signum != 2)
3770  goto end;
3771  copy = sig->next;
3772  if (copy->next != NULL)
3773  goto end;
3774  if (!(copy->init_data->init_flags & SIG_FLAG_INIT_BIDIREC))
3775  goto end;
3776 
3777  result = 1;
3778 
3779 end:
3780  if (de_ctx != NULL) {
3784  }
3785 
3786  return result;
3787 }
3788 
3789 /** \test Ensure that we set a bidirectional Signature correctly
3790 * and we install it with the rest of the signatures, checking
3791 * also that it match with the correct addr directions
3792 */
3793 static int SigTestBidirec03 (void)
3794 {
3795  int result = 0;
3796  Signature *sig = NULL;
3797  Packet *p = NULL;
3798 
3800  if (de_ctx == NULL)
3801  goto end;
3802 
3803  de_ctx->flags |= DE_QUIET;
3804 
3805  const char *sigs[3];
3806  sigs[0] = "alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 1\"; sid:1;)";
3807  sigs[1] = "alert tcp any any <> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)";
3808  sigs[2] = "alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 3\"; sid:3;)";
3809  UTHAppendSigs(de_ctx, sigs, 3);
3810 
3811  /* Checking that bidirectional rules are set correctly */
3812  sig = de_ctx->sig_list;
3813  if (sig == NULL)
3814  goto end;
3815  if (sig->next == NULL)
3816  goto end;
3817  if (sig->next->next == NULL)
3818  goto end;
3819  if (sig->next->next->next == NULL)
3820  goto end;
3821  if (sig->next->next->next->next != NULL)
3822  goto end;
3823  if (de_ctx->signum != 4)
3824  goto end;
3825 
3826  uint8_t rawpkt1_ether[] = {
3827  0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
3828  0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
3829  0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
3830  0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
3831  0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
3832  0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
3833  0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
3834  0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
3835  0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
3836  0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
3837  0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
3838  0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
3839  0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
3840  0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
3841  0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
3842  0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
3843  0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
3844  0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
3845  0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
3846  0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
3847  0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
3848  0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
3849  0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
3850  0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
3851  0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
3852  0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
3853  0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
3854  0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
3855  0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
3856  0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
3857  0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
3858  0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
3859  0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
3860  0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
3861  0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3862  0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3863  0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
3864  0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
3865  0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
3866  0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
3867  0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
3868  0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
3869  0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
3870  0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3871  0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
3872  0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
3873  0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
3874  0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
3875  0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3876  0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
3877  0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
3878  0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
3879  0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
3880  0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
3881  0x76,0x65,0x0d,0x0a,0x0d,0x0a }; /* end rawpkt1_ether */
3882 
3884  p = UTHBuildPacketFromEth(rawpkt1_ether, sizeof(rawpkt1_ether));
3885  if (p == NULL) {
3886  SCLogDebug("Error building packet");
3887  goto end;
3888  }
3889  UTHMatchPackets(de_ctx, &p, 1);
3890 
3891  uint32_t sids[3] = {1, 2, 3};
3892  uint32_t results[3] = {1, 1, 1};
3893  result = UTHCheckPacketMatchResults(p, sids, results, 1);
3894 
3895 end:
3896  if (p != NULL) {
3897  PacketRecycle(p);
3898  SCFree(p);
3899  }
3900  FlowShutdown();
3901  return result;
3902 }
3903 
3904 /** \test Ensure that we set a bidirectional Signature correctly
3905 * and we install it with the rest of the signatures, checking
3906 * also that it match with the correct addr directions
3907 */
3908 static int SigTestBidirec04 (void)
3909 {
3910  int result = 0;
3911  Signature *sig = NULL;
3912  Packet *p = NULL;
3913 
3915  if (de_ctx == NULL)
3916  goto end;
3917 
3918  de_ctx->flags |= DE_QUIET;
3919 
3920  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> any any (msg:\"SigTestBidirec03 sid 1\"; sid:1;)");
3921  if (sig == NULL)
3922  goto end;
3923  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <> any any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)");
3924  if (sig == NULL)
3925  goto end;
3926  if ( !(sig->init_data->init_flags & SIG_FLAG_INIT_BIDIREC))
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 (de_ctx->signum != 3)
3935  goto end;
3936 
3937  sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> any any (msg:\"SigTestBidirec03 sid 3\"; sid:3;)");
3938  if (sig == NULL)
3939  goto end;
3940  if (sig->next == NULL)
3941  goto end;
3942  if (sig->next->next == NULL)
3943  goto end;
3944  if (sig->next->next->next == NULL)
3945  goto end;
3946  if (sig->next->next->next->next != NULL)
3947  goto end;
3948  if (de_ctx->signum != 4)
3949  goto end;
3950 
3951  uint8_t rawpkt1_ether[] = {
3952  0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
3953  0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
3954  0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
3955  0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
3956  0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
3957  0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
3958  0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
3959  0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
3960  0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
3961  0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
3962  0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
3963  0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
3964  0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
3965  0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
3966  0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
3967  0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
3968  0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
3969  0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
3970  0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
3971  0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
3972  0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
3973  0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
3974  0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
3975  0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
3976  0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
3977  0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
3978  0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
3979  0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
3980  0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
3981  0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
3982  0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
3983  0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
3984  0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
3985  0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
3986  0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3987  0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3988  0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
3989  0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
3990  0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
3991  0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
3992  0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
3993  0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
3994  0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
3995  0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3996  0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
3997  0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
3998  0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
3999  0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
4000  0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
4001  0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
4002  0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
4003  0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
4004  0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
4005  0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
4006  0x76,0x65,0x0d,0x0a,0x0d,0x0a }; /* end rawpkt1_ether */
4007 
4008  p = PacketGetFromAlloc();
4009  if (unlikely(p == NULL))
4010  return 0;
4012  ThreadVars th_v;
4013  DetectEngineThreadCtx *det_ctx;
4014 
4015  memset(&th_v, 0, sizeof(th_v));
4016 
4018  DecodeEthernet(&th_v, &dtv, p, rawpkt1_ether, sizeof(rawpkt1_ether));
4019  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
4020 
4021  /* At this point we have a list of 4 signatures. The last one
4022  is a copy of the second one. If we receive a packet
4023  with source 192.168.1.1 80, all the sids should match */
4024 
4026  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
4027 
4028  /* only sid 2 should match with a packet going to 192.168.1.1 port 80 */
4029  if (PacketAlertCheck(p, 1) <= 0 && PacketAlertCheck(p, 3) <= 0 &&
4030  PacketAlertCheck(p, 2) == 1) {
4031  result = 1;
4032  }
4033 
4034  if (p != NULL) {
4035  PacketRecycle(p);
4036  }
4037  FlowShutdown();
4038  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
4039 
4040 end:
4041  if (de_ctx != NULL) {
4045  }
4046 
4047  if (p != NULL)
4048  SCFree(p);
4049  return result;
4050 }
4051 
4052 /**
4053  * \test check that we don't allow invalid negation options
4054  */
4055 static int SigParseTestNegation01 (void)
4056 {
4059  de_ctx->flags |= DE_QUIET;
4060  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp !any any -> any any (sid:1;)");
4061  FAIL_IF_NOT_NULL(s);
4063  PASS;
4064 }
4065 
4066 /**
4067  * \test check that we don't allow invalid negation options
4068  */
4069 static int SigParseTestNegation02 (void)
4070 {
4071  int result = 0;
4073  Signature *s=NULL;
4074 
4076  if (de_ctx == NULL)
4077  goto end;
4078  de_ctx->flags |= DE_QUIET;
4079 
4080  s = SigInit(de_ctx,"alert tcp any !any -> any any (msg:\"SigTest41-02 src ip is !any \"; classtype:misc-activity; sid:410002; rev:1;)");
4081  if (s != NULL) {
4082  SigFree(de_ctx, s);
4083  goto end;
4084  }
4085 
4086  result = 1;
4087 end:
4088  if (de_ctx != NULL)
4090  return result;
4091 }
4092 /**
4093  * \test check that we don't allow invalid negation options
4094  */
4095 static int SigParseTestNegation03 (void)
4096 {
4097  int result = 0;
4099  Signature *s=NULL;
4100 
4102  if (de_ctx == NULL)
4103  goto end;
4104  de_ctx->flags |= DE_QUIET;
4105 
4106  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;)");
4107  if (s != NULL) {
4108  SigFree(de_ctx, s);
4109  goto end;
4110  }
4111 
4112  result = 1;
4113 end:
4114  if (de_ctx != NULL)
4116  return result;
4117 }
4118 /**
4119  * \test check that we don't allow invalid negation options
4120  */
4121 static int SigParseTestNegation04 (void)
4122 {
4123  int result = 0;
4125  Signature *s=NULL;
4126 
4128  if (de_ctx == NULL)
4129  goto end;
4130  de_ctx->flags |= DE_QUIET;
4131 
4132  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;)");
4133  if (s != NULL) {
4134  SigFree(de_ctx, s);
4135  goto end;
4136  }
4137 
4138  result = 1;
4139 end:
4140  if (de_ctx != NULL)
4142  return result;
4143 }
4144 /**
4145  * \test check that we don't allow invalid negation options
4146  */
4147 static int SigParseTestNegation05 (void)
4148 {
4149  int result = 0;
4151  Signature *s=NULL;
4152 
4154  if (de_ctx == NULL)
4155  goto end;
4156  de_ctx->flags |= DE_QUIET;
4157 
4158  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;)");
4159  if (s != NULL) {
4160  SigFree(de_ctx, s);
4161  goto end;
4162  }
4163 
4164  result = 1;
4165 end:
4166  if (de_ctx != NULL)
4168  return result;
4169 }
4170 /**
4171  * \test check that we don't allow invalid negation options
4172  */
4173 static int SigParseTestNegation06 (void)
4174 {
4175  int result = 0;
4177  Signature *s=NULL;
4178 
4180  if (de_ctx == NULL)
4181  goto end;
4182  de_ctx->flags |= DE_QUIET;
4183 
4184  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;)");
4185  if (s != NULL) {
4186  SigFree(de_ctx, s);
4187  goto end;
4188  }
4189 
4190  result = 1;
4191 end:
4192  if (de_ctx != NULL)
4194  return result;
4195 }
4196 
4197 /**
4198  * \test check that we don't allow invalid negation options
4199  */
4200 static int SigParseTestNegation07 (void)
4201 {
4204  de_ctx->flags |= DE_QUIET;
4206  de_ctx, "alert tcp any any -> [192.168.0.2,!192.168.0.0/24] any (sid:410006;)");
4207  FAIL_IF_NOT_NULL(s);
4209  PASS;
4210 }
4211 
4212 /**
4213  * \test check valid negation bug 1079
4214  */
4215 static int SigParseTestNegation08 (void)
4216 {
4217  int result = 0;
4219  Signature *s=NULL;
4220 
4222  if (de_ctx == NULL)
4223  goto end;
4224  de_ctx->flags |= DE_QUIET;
4225 
4226  s = SigInit(de_ctx,"alert tcp any any -> [192.168.0.0/16,!192.168.0.0/24] any (sid:410006; rev:1;)");
4227  if (s == NULL) {
4228  goto end;
4229  }
4230 
4231  result = 1;
4232 end:
4233  if (de_ctx != NULL)
4235  return result;
4236 }
4237 
4238 /**
4239  * \test mpm
4240  */
4241 static int SigParseTestMpm01 (void)
4242 {
4243  int result = 0;
4244  Signature *sig = NULL;
4245 
4247  if (de_ctx == NULL)
4248  goto end;
4249 
4250  sig = SigInit(de_ctx, "alert tcp any any -> any any (msg:\"mpm test\"; content:\"abcd\"; sid:1;)");
4251  if (sig == NULL) {
4252  printf("sig failed to init: ");
4253  goto end;
4254  }
4255 
4256  if (sig->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
4257  printf("sig doesn't have content list: ");
4258  goto end;
4259  }
4260 
4261  result = 1;
4262 end:
4263  if (sig != NULL)
4264  SigFree(de_ctx, sig);
4266  return result;
4267 }
4268 
4269 /**
4270  * \test mpm
4271  */
4272 static int SigParseTestMpm02 (void)
4273 {
4274  int result = 0;
4275  Signature *sig = NULL;
4276 
4278  if (de_ctx == NULL)
4279  goto end;
4280 
4281  sig = SigInit(de_ctx, "alert tcp any any -> any any (msg:\"mpm test\"; content:\"abcd\"; content:\"abcdef\"; sid:1;)");
4282  if (sig == NULL) {
4283  printf("sig failed to init: ");
4284  goto end;
4285  }
4286 
4287  if (sig->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
4288  printf("sig doesn't have content list: ");
4289  goto end;
4290  }
4291 
4292  result = 1;
4293 end:
4294  if (sig != NULL)
4295  SigFree(de_ctx, sig);
4297  return result;
4298 }
4299 
4300 /**
4301  * \test test tls (app layer) rule
4302  */
4303 static int SigParseTestAppLayerTLS01(void)
4304 {
4305  int result = 0;
4307  Signature *s=NULL;
4308 
4310  if (de_ctx == NULL)
4311  goto end;
4312  de_ctx->flags |= DE_QUIET;
4313 
4314  s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS01 \"; sid:410006; rev:1;)");
4315  if (s == NULL) {
4316  printf("parsing sig failed: ");
4317  goto end;
4318  }
4319 
4320  if (s->alproto == 0) {
4321  printf("alproto not set: ");
4322  goto end;
4323  }
4324 
4325  result = 1;
4326 end:
4327  if (s != NULL)
4328  SigFree(de_ctx, s);
4329  if (de_ctx != NULL)
4331 
4332  return result;
4333 }
4334 
4335 /**
4336  * \test test tls (app layer) rule
4337  */
4338 static int SigParseTestAppLayerTLS02(void)
4339 {
4340  int result = 0;
4342  Signature *s=NULL;
4343 
4345  if (de_ctx == NULL)
4346  goto end;
4347  de_ctx->flags |= DE_QUIET;
4348 
4349  s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS02 \"; tls.version:1.0; sid:410006; rev:1;)");
4350  if (s == NULL) {
4351  printf("parsing sig failed: ");
4352  goto end;
4353  }
4354 
4355  if (s->alproto == 0) {
4356  printf("alproto not set: ");
4357  goto end;
4358  }
4359 
4360  result = 1;
4361 end:
4362  if (s != NULL)
4363  SigFree(de_ctx, s);
4364  if (de_ctx != NULL)
4366  return result;
4367 }
4368 
4369 /**
4370  * \test test tls (app layer) rule
4371  */
4372 static int SigParseTestAppLayerTLS03(void)
4373 {
4374  int result = 0;
4376  Signature *s=NULL;
4377 
4379  if (de_ctx == NULL)
4380  goto end;
4381  de_ctx->flags |= DE_QUIET;
4382 
4383  s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS03 \"; tls.version:2.5; sid:410006; rev:1;)");
4384  if (s != NULL) {
4385  SigFree(de_ctx, s);
4386  goto end;
4387  }
4388 
4389  result = 1;
4390 end:
4391  if (de_ctx != NULL)
4393  return result;
4394 }
4395 
4396 static int SigParseTestUnbalancedQuotes01(void)
4397 {
4399  Signature *s;
4400 
4403  de_ctx->flags |= DE_QUIET;
4404 
4405  s = SigInit(de_ctx,
4406  "alert http any any -> any any (msg:\"SigParseTestUnbalancedQuotes01\"; "
4407  "pcre:\"/\\/[a-z]+\\.php\\?[a-z]+?=\\d{7}&[a-z]+?=\\d{7,8}$/U\" "
4408  "flowbits:set,et.exploitkitlanding; classtype:trojan-activity; sid:2017078; rev:5;)");
4409  FAIL_IF_NOT_NULL(s);
4410 
4411  PASS;
4412 }
4413 
4414 static int SigParseTestContentGtDsize01(void)
4415 {
4418  de_ctx->flags |= DE_QUIET;
4419 
4420  Signature *s = SigInit(de_ctx,
4421  "alert http any any -> any any ("
4422  "dsize:21; content:\"0123456789001234567890|00 00|\"; "
4423  "sid:1; rev:1;)");
4424  FAIL_IF_NOT_NULL(s);
4425 
4426  PASS;
4427 }
4428 
4429 static int SigParseTestContentGtDsize02(void)
4430 {
4433  de_ctx->flags |= DE_QUIET;
4434 
4435  Signature *s = SigInit(de_ctx,
4436  "alert http any any -> any any ("
4437  "dsize:21; content:\"0123456789|00 00|\"; offset:10; "
4438  "sid:1; rev:1;)");
4439  FAIL_IF_NOT_NULL(s);
4440 
4441  PASS;
4442 }
4443 
4444 static int CountSigsWithSid(const DetectEngineCtx *de_ctx, const uint32_t sid)
4445 {
4446  int cnt = 0;
4447  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
4448  if (sid == s->id)
4449  cnt++;
4450  }
4451  return cnt;
4452 }
4453 
4454 static int SigParseBidirWithSameSrcAndDest01(void)
4455 {
4458  de_ctx->flags |= DE_QUIET;
4459 
4460  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any <> any any (sid:1;)");
4461  FAIL_IF_NULL(s);
4462  FAIL_IF_NOT(CountSigsWithSid(de_ctx, 1) == 1);
4464 
4465  s = DetectEngineAppendSig(de_ctx, "alert tcp any [80, 81] <> any [81, 80] (sid:2;)");
4466  FAIL_IF_NULL(s);
4467  FAIL_IF_NOT(CountSigsWithSid(de_ctx, 2) == 1);
4469 
4471  "alert tcp [1.2.3.4, 5.6.7.8] [80, 81] <> [5.6.7.8, 1.2.3.4] [81, 80] (sid:3;)");
4472  FAIL_IF_NULL(s);
4473  FAIL_IF_NOT(CountSigsWithSid(de_ctx, 3) == 1);
4475 
4477  PASS;
4478 }
4479 
4480 static int SigParseBidirWithSameSrcAndDest02(void)
4481 {
4484  de_ctx->flags |= DE_QUIET;
4485 
4486  // Source is a subset of destination
4488  de_ctx, "alert tcp 1.2.3.4 any <> [1.2.3.4, 5.6.7.8, ::1] any (sid:1;)");
4489  FAIL_IF_NULL(s);
4490  FAIL_IF_NOT(CountSigsWithSid(de_ctx, 1) == 2);
4492 
4493  // Source is a subset of destination
4495  de_ctx, "alert tcp [1.2.3.4, ::1] [80, 81, 82] <> [1.2.3.4, ::1] [80, 81] (sid:2;)");
4496  FAIL_IF_NULL(s);
4497  FAIL_IF_NOT(CountSigsWithSid(de_ctx, 2) == 2);
4499 
4500  // Source intersects with destination
4502  "alert tcp [1.2.3.4, ::1, ABCD:AAAA::1] [80] <> [1.2.3.4, ::1] [80, 81] (sid:3;)");
4503  FAIL_IF_NULL(s);
4504  FAIL_IF_NOT(CountSigsWithSid(de_ctx, 3) == 2);
4506 
4507  // mix in negation, these are the same
4509  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;)");
4510  FAIL_IF_NULL(s);
4511  FAIL_IF_NOT(CountSigsWithSid(de_ctx, 4) == 1);
4513 
4514  // mix in negation, these are not the same
4516  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;)");
4517  FAIL_IF_NULL(s);
4518  FAIL_IF_NOT(CountSigsWithSid(de_ctx, 5) == 2);
4520 
4522  PASS;
4523 }
4524 
4525 static int SigParseTestActionReject(void)
4526 {
4529 
4531  de_ctx, "reject tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1;)");
4532 #ifdef HAVE_LIBNET11
4533  FAIL_IF_NULL(sig);
4535 #else
4536  FAIL_IF_NOT_NULL(sig);
4537 #endif
4538 
4540  PASS;
4541 }
4542 
4543 static int SigParseTestActionDrop(void)
4544 {
4547 
4549  de_ctx, "drop tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1;)");
4550  FAIL_IF_NULL(sig);
4551  FAIL_IF_NOT(sig->action & ACTION_DROP);
4552 
4554  PASS;
4555 }
4556 
4557 #endif /* UNITTESTS */
4558 
4559 #ifdef UNITTESTS
4560 void DetectParseRegisterTests (void);
4561 #include "tests/detect-parse.c"
4562 #endif
4563 
4565 {
4566 #ifdef UNITTESTS
4568 
4569  UtRegisterTest("SigParseTest01", SigParseTest01);
4570  UtRegisterTest("SigParseTest02", SigParseTest02);
4571  UtRegisterTest("SigParseTest03", SigParseTest03);
4572  UtRegisterTest("SigParseTest04", SigParseTest04);
4573  UtRegisterTest("SigParseTest05", SigParseTest05);
4574  UtRegisterTest("SigParseTest06", SigParseTest06);
4575  UtRegisterTest("SigParseTest07", SigParseTest07);
4576  UtRegisterTest("SigParseTest08", SigParseTest08);
4577  UtRegisterTest("SigParseTest09", SigParseTest09);
4578  UtRegisterTest("SigParseTest10", SigParseTest10);
4579  UtRegisterTest("SigParseTest11", SigParseTest11);
4580  UtRegisterTest("SigParseTest12", SigParseTest12);
4581  UtRegisterTest("SigParseTest13", SigParseTest13);
4582  UtRegisterTest("SigParseTest14", SigParseTest14);
4583  UtRegisterTest("SigParseTest15", SigParseTest15);
4584  UtRegisterTest("SigParseTest16", SigParseTest16);
4585  UtRegisterTest("SigParseTest17", SigParseTest17);
4586  UtRegisterTest("SigParseTest18", SigParseTest18);
4587  UtRegisterTest("SigParseTest19", SigParseTest19);
4588  UtRegisterTest("SigParseTest20", SigParseTest20);
4589  UtRegisterTest("SigParseTest21 -- address with space", SigParseTest21);
4590  UtRegisterTest("SigParseTest22 -- address with space", SigParseTest22);
4591  UtRegisterTest("SigParseTest23 -- carriage return", SigParseTest23);
4592 
4593  UtRegisterTest("SigParseBidirecTest06", SigParseBidirecTest06);
4594  UtRegisterTest("SigParseBidirecTest07", SigParseBidirecTest07);
4595  UtRegisterTest("SigParseBidirecTest08", SigParseBidirecTest08);
4596  UtRegisterTest("SigParseBidirecTest09", SigParseBidirecTest09);
4597  UtRegisterTest("SigParseBidirecTest10", SigParseBidirecTest10);
4598  UtRegisterTest("SigParseBidirecTest11", SigParseBidirecTest11);
4599  UtRegisterTest("SigParseBidirecTest12", SigParseBidirecTest12);
4600  UtRegisterTest("SigParseBidirecTest13", SigParseBidirecTest13);
4601  UtRegisterTest("SigParseBidirecTest14", SigParseBidirecTest14);
4602  UtRegisterTest("SigTestBidirec01", SigTestBidirec01);
4603  UtRegisterTest("SigTestBidirec02", SigTestBidirec02);
4604  UtRegisterTest("SigTestBidirec03", SigTestBidirec03);
4605  UtRegisterTest("SigTestBidirec04", SigTestBidirec04);
4606  UtRegisterTest("SigParseTestNegation01", SigParseTestNegation01);
4607  UtRegisterTest("SigParseTestNegation02", SigParseTestNegation02);
4608  UtRegisterTest("SigParseTestNegation03", SigParseTestNegation03);
4609  UtRegisterTest("SigParseTestNegation04", SigParseTestNegation04);
4610  UtRegisterTest("SigParseTestNegation05", SigParseTestNegation05);
4611  UtRegisterTest("SigParseTestNegation06", SigParseTestNegation06);
4612  UtRegisterTest("SigParseTestNegation07", SigParseTestNegation07);
4613  UtRegisterTest("SigParseTestNegation08", SigParseTestNegation08);
4614  UtRegisterTest("SigParseTestMpm01", SigParseTestMpm01);
4615  UtRegisterTest("SigParseTestMpm02", SigParseTestMpm02);
4616  UtRegisterTest("SigParseTestAppLayerTLS01", SigParseTestAppLayerTLS01);
4617  UtRegisterTest("SigParseTestAppLayerTLS02", SigParseTestAppLayerTLS02);
4618  UtRegisterTest("SigParseTestAppLayerTLS03", SigParseTestAppLayerTLS03);
4619  UtRegisterTest("SigParseTestUnbalancedQuotes01", SigParseTestUnbalancedQuotes01);
4620 
4621  UtRegisterTest("SigParseTestContentGtDsize01",
4622  SigParseTestContentGtDsize01);
4623  UtRegisterTest("SigParseTestContentGtDsize02",
4624  SigParseTestContentGtDsize02);
4625 
4626  UtRegisterTest("SigParseBidirWithSameSrcAndDest01",
4627  SigParseBidirWithSameSrcAndDest01);
4628  UtRegisterTest("SigParseBidirWithSameSrcAndDest02",
4629  SigParseBidirWithSameSrcAndDest02);
4630  UtRegisterTest("SigParseTestActionReject", SigParseTestActionReject);
4631  UtRegisterTest("SigParseTestActionDrop", SigParseTestActionDrop);
4632 #endif /* UNITTESTS */
4633 }
DETECT_TBLSIZE_STATIC
@ DETECT_TBLSIZE_STATIC
Definition: detect-engine-register.h:340
DetectAddressListsAreEqual
bool DetectAddressListsAreEqual(DetectAddress *list1, DetectAddress *list2)
Checks if two address group lists are equal.
Definition: detect-engine-address.c:349
DetectIPProtoRemoveAllSMs
void DetectIPProtoRemoveAllSMs(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-ipproto.c:430
SignatureParser_
Definition: detect-parse.c: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:1782
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:2511
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:1310
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:1532
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:1320
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:1318
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
SIG_DIREC_SRC
@ SIG_DIREC_SRC
Definition: detect-parse.h:58
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.
AppLayerGetProtoByName
AppProto AppLayerGetProtoByName(const char *alproto_name)
Given a protocol string, returns the corresponding internal protocol id.
Definition: app-layer.c:1001
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:71
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:952
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:1516
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
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:2836
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:1314
ctx
struct Thresholds ctx
AppLayerParserSupportsFiles
bool AppLayerParserSupportsFiles(uint8_t ipproto, AppProto alproto)
Definition: app-layer-parser.c:1164
SigDuplWrapper_::s_prev
Signature * s_prev
Definition: detect-parse.c:171
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:855
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:119
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2698
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:1144
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:956
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:990
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:2528
DetectParsePcreExec
int DetectParsePcreExec(DetectParseRegex *parse_regex, pcre2_match_data **match, const char *str, int start_offset, int options)
Definition: detect-parse.c:2760
DetectBufferType_
Definition: detect.h:458
DetectContentData_
Definition: detect-content.h:93
PORT_EQ
@ PORT_EQ
Definition: detect.h:207
DetectEngineCtx_::sigerror_ok
bool sigerror_ok
Definition: detect.h:953
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:1286
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:1305
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:2796
util-unittest.h
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
SIG_DIREC_NORMAL
@ SIG_DIREC_NORMAL
Definition: detect-parse.h:51
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:832
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:2780
DetectEngineAppInspectionEngine_::sm_list
uint16_t sm_list
Definition: detect.h:439
SIGMATCH_QUOTES_MANDATORY
#define SIGMATCH_QUOTES_MANDATORY
Definition: detect.h:1520
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:4564
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:1673
DetectEngineThreadCtx_
Definition: detect.h:1110
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:2886
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
SIG_DIREC_SWITCHED
@ SIG_DIREC_SWITCHED
Definition: detect-parse.h:52
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:1037
SigMatchList2DataArray
SigMatchData * SigMatchList2DataArray(SigMatch *head)
convert SigMatch list to SigMatchData array
Definition: detect-parse.c:1900
pkt-var.h
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
Definition: detect-engine.c:3437
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:2874
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2404
DetectPort_
Port structure for detection engine.
Definition: detect.h:219
SigTableElmt_::alternative
uint16_t alternative
Definition: detect.h:1318
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:1134
SignatureInitDataBufferCheckExpand
int SignatureInitDataBufferCheckExpand(Signature *s)
check if buffers array still has space left, expand if not
Definition: detect-parse.c:1533
SIGMATCH_HANDLE_NEGATION
#define SIGMATCH_HANDLE_NEGATION
Definition: detect.h:1524
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:1288
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:73
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:1290
DetectEngineCtx_::dup_sig_hash_table
HashListTable * dup_sig_hash_table
Definition: detect.h:894
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:2706
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:1321
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:3664
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:863
DetectEngineAppInspectionEngineSignatureFree
void DetectEngineAppInspectionEngineSignatureFree(DetectEngineCtx *de_ctx, Signature *s)
free app inspect engines for a signature
Definition: detect-engine.c:836
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:1038
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:1004
DetectMatchAddressIPv6_::ip
uint32_t ip[4]
Definition: detect.h:194
SIGMATCH_OPTIONAL_OPT
#define SIGMATCH_OPTIONAL_OPT
Definition: detect.h:1513
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:1013
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:285
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:1530
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:1307
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
SIG_DIREC_DST
@ SIG_DIREC_DST
Definition: detect-parse.h:59
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:2659
DetectSignatureAddTransform
int DetectSignatureAddTransform(Signature *s, int transform, void *options)
Definition: detect-parse.c:1757
DETECT_PCRE_RELATIVE_NEXT
#define DETECT_PCRE_RELATIVE_NEXT
Definition: detect-pcre.h:34
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:2862
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:1504
DetectEngineBufferRunValidateCallback
bool DetectEngineBufferRunValidateCallback(const DetectEngineCtx *de_ctx, const int id, const Signature *s, const char **sigerror)
Definition: detect-engine.c:1336
DetectEngineCtx_::sigerror
const char * sigerror
Definition: detect.h:951
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:2770
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:857
SigAlloc
Signature * SigAlloc(void)
Definition: detect-parse.c:1553
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:875
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:2807
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
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