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