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