suricata
detect-engine-tag.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 detect-engine-tag.c
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
23  *
24  * Implements a global context to store data related to hosts flagged
25  * tag keyword
26  */
27 
28 #include "suricata-common.h"
29 #include "detect-engine.h"
30 #include "util-hash.h"
31 #include "util-atomic.h"
32 #include "util-time.h"
33 #include "util-hashlist.h"
34 #include "detect-engine-tag.h"
35 #include "detect-engine-build.h"
36 #include "detect-tag.h"
37 #include "host.h"
38 #include "host-storage.h"
39 #include "flow-storage.h"
40 
41 #include "util-unittest.h"
42 #include "util-unittest-helper.h"
43 #include "flow-util.h"
44 #include "stream-tcp-private.h"
45 
46 SC_ATOMIC_DECLARE(unsigned int, num_tags); /**< Atomic counter, to know if we
47  have tagged hosts/sessions,
48  to avoid locking */
49 static HostStorageId host_tag_id = { .id = -1 }; /**< Host storage id for tags */
50 static FlowStorageId flow_tag_id = { .id = -1 }; /**< Flow storage id for tags */
51 
52 void TagInitCtx(void)
53 {
54  SC_ATOMIC_INIT(num_tags);
55 
56  host_tag_id = HostStorageRegister("tag", sizeof(void *), NULL, DetectTagDataListFree);
57  if (host_tag_id.id == -1) {
58  FatalError("Can't initiate host storage for tag");
59  }
60  flow_tag_id = FlowStorageRegister("tag", sizeof(void *), NULL, DetectTagDataListFree);
61  if (flow_tag_id.id == -1) {
62  FatalError("Can't initiate flow storage for tag");
63  }
64 }
65 
66 /**
67  * \brief Destroy tag context hash tables
68  *
69  * \param tag_ctx Tag Context
70  *
71  */
72 void TagDestroyCtx(void)
73 {
74 #ifdef DEBUG
75  BUG_ON(SC_ATOMIC_GET(num_tags) != 0);
76 #endif
77 }
78 
79 int TagHostHasTag(Host *host)
80 {
81  return HostGetStorageById(host, host_tag_id) ? 1 : 0;
82 }
83 
84 static DetectTagDataEntry *DetectTagDataCopy(DetectTagDataEntry *dtd)
85 {
87  if (unlikely(tde == NULL)) {
88  return NULL;
89  }
90 
91  tde->sid = dtd->sid;
92  tde->gid = dtd->gid;
93  tde->flags = dtd->flags;
94  tde->metric = dtd->metric;
95  tde->count = dtd->count;
96 
97  tde->first_ts = dtd->first_ts;
98  tde->last_ts = dtd->last_ts;
99  return tde;
100 }
101 
102 /**
103  * \brief This function is used to add a tag to a session (type session)
104  * or update it if it's already installed. The number of times to
105  * allow an update is limited by DETECT_TAG_MATCH_LIMIT. This way
106  * repetitive matches to the same rule are limited of setting tags,
107  * to avoid DOS attacks
108  *
109  * \param p pointer to the current packet
110  * \param tde pointer to the new DetectTagDataEntry
111  *
112  * \retval 0 if the tde was added successfully
113  * \retval 1 if an entry of this sid/gid already exist and was updated
114  */
116 {
117  uint8_t updated = 0;
118  uint16_t tag_cnt = 0;
119  DetectTagDataEntry *iter = NULL;
120 
121  if (p->flow == NULL)
122  return 1;
123 
124  iter = FlowGetStorageById(p->flow, flow_tag_id);
125  if (iter != NULL) {
126  /* First iterate installed entries searching a duplicated sid/gid */
127  for (; iter != NULL; iter = iter->next) {
128  tag_cnt++;
129 
130  if (iter->sid == tde->sid && iter->gid == tde->gid) {
131  iter->cnt_match++;
132 
133  /* If so, update data, unless the maximum MATCH limit is
134  * reached. This prevents possible DOS attacks */
135  if (iter->cnt_match < DETECT_TAG_MATCH_LIMIT) {
136  /* Reset time and counters */
137  iter->first_ts = iter->last_ts = tde->first_ts;
138  iter->packets = 0;
139  iter->bytes = 0;
140  }
141  updated = 1;
142  break;
143  }
144  }
145  }
146 
147  /* If there was no entry of this rule, prepend the new tde */
148  if (updated == 0 && tag_cnt < DETECT_TAG_MAX_TAGS) {
149  DetectTagDataEntry *new_tde = DetectTagDataCopy(tde);
150  if (new_tde != NULL) {
151  new_tde->next = FlowGetStorageById(p->flow, flow_tag_id);
152  FlowSetStorageById(p->flow, flow_tag_id, new_tde);
153  SCLogDebug(
154  "adding tag with first_ts %" PRIu64, (uint64_t)SCTIME_SECS(new_tde->first_ts));
155  (void) SC_ATOMIC_ADD(num_tags, 1);
156  }
157  } else if (tag_cnt == DETECT_TAG_MAX_TAGS) {
158  SCLogDebug("Max tags for sessions reached (%"PRIu16")", tag_cnt);
159  }
160 
161  return updated;
162 }
163 
164 /**
165  * \brief Add a tag entry for a host. If it already exist, update it.
166  *
167  * \param tag_ctx Tag context for hosts
168  * \param tde Tag data
169  * \param p packet
170  *
171  * \retval 0 if it was added, 1 if it was updated
172  */
174 {
175  SCEnter();
176 
177  uint8_t updated = 0;
178  uint16_t ntags = 0;
179  Host *host = NULL;
180 
181  /* Lookup host in the hash. If it doesn't exist yet it's
182  * created. */
183  if (tde->flags & TAG_ENTRY_FLAG_DIR_SRC) {
184  host = HostGetHostFromHash(&p->src);
185  } else if (tde->flags & TAG_ENTRY_FLAG_DIR_DST) {
186  host = HostGetHostFromHash(&p->dst);
187  }
188  /* no host for us */
189  if (host == NULL) {
190  SCLogDebug("host tag not added: no host");
191  return -1;
192  }
193 
194  void *tag = HostGetStorageById(host, host_tag_id);
195  if (tag == NULL) {
196  /* get a new tde as the one we have is on the stack */
197  DetectTagDataEntry *new_tde = DetectTagDataCopy(tde);
198  if (new_tde != NULL) {
199  HostSetStorageById(host, host_tag_id, new_tde);
200  (void) SC_ATOMIC_ADD(num_tags, 1);
201  SCLogDebug("host tag added");
202  }
203  } else {
204  /* Append the tag to the list of this host */
205  SCLogDebug("updating existing host");
206 
207  /* First iterate installed entries searching a duplicated sid/gid */
208  DetectTagDataEntry *iter = NULL;
209 
210  for (iter = tag; iter != NULL; iter = iter->next) {
211  ntags++;
212  if (iter->sid == tde->sid && iter->gid == tde->gid) {
213  iter->cnt_match++;
214  /* If so, update data, unless the maximum MATCH limit is
215  * reached. This prevents possible DOS attacks */
216  if (iter->cnt_match < DETECT_TAG_MATCH_LIMIT) {
217  /* Reset time and counters */
218  iter->first_ts = iter->last_ts = tde->first_ts;
219  iter->packets = 0;
220  iter->bytes = 0;
221  }
222  updated = 1;
223  break;
224  }
225  }
226 
227  /* If there was no entry of this rule, append the new tde */
228  if (updated == 0 && ntags < DETECT_TAG_MAX_TAGS) {
229  /* get a new tde as the one we have is on the stack */
230  DetectTagDataEntry *new_tde = DetectTagDataCopy(tde);
231  if (new_tde != NULL) {
232  (void) SC_ATOMIC_ADD(num_tags, 1);
233 
234  new_tde->next = tag;
235  HostSetStorageById(host, host_tag_id, new_tde);
236  }
237  } else if (ntags == DETECT_TAG_MAX_TAGS) {
238  SCLogDebug("Max tags for sessions reached (%"PRIu16")", ntags);
239  }
240  }
241 
242  HostRelease(host);
243  SCReturnInt(updated);
244 }
245 
246 static void TagHandlePacketFlow(Flow *f, Packet *p)
247 {
248  if (FlowGetStorageById(f, flow_tag_id) == NULL)
249  return;
250 
251  DetectTagDataEntry *tde = NULL;
252  DetectTagDataEntry *prev = NULL;
253  DetectTagDataEntry *iter = FlowGetStorageById(f, flow_tag_id);
254  uint8_t flag_added = 0;
255 
256  while (iter != NULL) {
257  /* update counters */
258  iter->last_ts = p->ts;
259  switch (iter->metric) {
261  iter->packets++;
262  break;
264  iter->bytes += GET_PKT_LEN(p);
265  break;
266  }
267 
268  /* If this packet triggered the rule with tag, we dont need
269  * to log it (the alert will log it) */
270  if (!(iter->flags & TAG_ENTRY_FLAG_SKIPPED_FIRST)) {
272  p->flags |= PKT_FIRST_TAG;
273  } else {
274  /* Update metrics; remove if tag expired; and set alerts */
275  switch (iter->metric) {
277  if (iter->packets > iter->count) {
278  SCLogDebug("flow tag expired: packets %u > %u",
279  iter->packets, iter->count);
280  /* tag expired */
281  if (prev != NULL) {
282  tde = iter;
283  prev->next = iter->next;
284  iter = iter->next;
285  SCFree(tde);
286  (void) SC_ATOMIC_SUB(num_tags, 1);
287  continue;
288  } else {
289  FlowSetStorageById(p->flow, flow_tag_id, iter->next);
290  tde = iter;
291  iter = iter->next;
292  SCFree(tde);
293  (void) SC_ATOMIC_SUB(num_tags, 1);
294  continue;
295  }
296  } else if (flag_added == 0) {
297  /* It's matching the tag. Add it to be logged and
298  * update "flag_added" to add the packet once. */
299  p->flags |= PKT_HAS_TAG;
300  flag_added++;
301  }
302  break;
304  if (iter->bytes > iter->count) {
305  /* tag expired */
306  SCLogDebug("flow tag expired: bytes %u > %u",
307  iter->bytes, iter->count);
308  if (prev != NULL) {
309  tde = iter;
310  prev->next = iter->next;
311  iter = iter->next;
312  SCFree(tde);
313  (void) SC_ATOMIC_SUB(num_tags, 1);
314  continue;
315  } else {
316  FlowSetStorageById(p->flow, flow_tag_id, iter->next);
317  tde = iter;
318  iter = iter->next;
319  SCFree(tde);
320  (void) SC_ATOMIC_SUB(num_tags, 1);
321  continue;
322  }
323  } else if (flag_added == 0) {
324  /* It's matching the tag. Add it to be logged and
325  * update "flag_added" to add the packet once. */
326  p->flags |= PKT_HAS_TAG;
327  flag_added++;
328  }
329  break;
331  /* last_ts handles this metric, but also a generic time based
332  * expiration to prevent dead sessions/hosts */
333  if (SCTIME_SECS(iter->last_ts) - SCTIME_SECS(iter->first_ts) > iter->count) {
334  // cast needed as gcc and clang behave differently
335  SCLogDebug("flow tag expired: %" PRIu64 " - %" PRIu64 " = %" PRIu64 " > %u",
336  (uint64_t)SCTIME_SECS(iter->last_ts),
337  (uint64_t)SCTIME_SECS(iter->first_ts),
338  (uint64_t)(SCTIME_SECS(iter->last_ts) -
339  SCTIME_SECS(iter->first_ts)),
340  iter->count);
341  /* tag expired */
342  if (prev != NULL) {
343  tde = iter;
344  prev->next = iter->next;
345  iter = iter->next;
346  SCFree(tde);
347  (void) SC_ATOMIC_SUB(num_tags, 1);
348  continue;
349  } else {
350  FlowSetStorageById(p->flow, flow_tag_id, iter->next);
351  tde = iter;
352  iter = iter->next;
353  SCFree(tde);
354  (void) SC_ATOMIC_SUB(num_tags, 1);
355  continue;
356  }
357  } else if (flag_added == 0) {
358  /* It's matching the tag. Add it to be logged and
359  * update "flag_added" to add the packet once. */
360  p->flags |= PKT_HAS_TAG;
361  flag_added++;
362  }
363  break;
364  }
365 
366  }
367 
368  prev = iter;
369  iter = iter->next;
370  }
371 }
372 
373 static void TagHandlePacketHost(Host *host, Packet *p)
374 {
375  DetectTagDataEntry *tde = NULL;
376  DetectTagDataEntry *prev = NULL;
377  DetectTagDataEntry *iter;
378  uint8_t flag_added = 0;
379 
380  iter = HostGetStorageById(host, host_tag_id);
381  prev = NULL;
382  while (iter != NULL) {
383  /* update counters */
384  iter->last_ts = p->ts;
385  switch (iter->metric) {
387  iter->packets++;
388  break;
390  iter->bytes += GET_PKT_LEN(p);
391  break;
392  }
393 
394  /* If this packet triggered the rule with tag, we dont need
395  * to log it (the alert will log it) */
396  if (!(iter->flags & TAG_ENTRY_FLAG_SKIPPED_FIRST)) {
398  } else {
399  /* Update metrics; remove if tag expired; and set alerts */
400  switch (iter->metric) {
402  if (iter->packets > iter->count) {
403  SCLogDebug("host tag expired: packets %u > %u", iter->packets, iter->count);
404  /* tag expired */
405  if (prev != NULL) {
406  tde = iter;
407  prev->next = iter->next;
408  iter = iter->next;
409  SCFree(tde);
410  (void) SC_ATOMIC_SUB(num_tags, 1);
411  continue;
412  } else {
413  tde = iter;
414  iter = iter->next;
415  SCFree(tde);
416  (void) SC_ATOMIC_SUB(num_tags, 1);
417  HostSetStorageById(host, host_tag_id, iter);
418  continue;
419  }
420  } else if (flag_added == 0) {
421  /* It's matching the tag. Add it to be logged and
422  * update "flag_added" to add the packet once. */
423  p->flags |= PKT_HAS_TAG;
424  flag_added++;
425  }
426  break;
428  if (iter->bytes > iter->count) {
429  SCLogDebug("host tag expired: bytes %u > %u", iter->bytes, iter->count);
430  /* tag expired */
431  if (prev != NULL) {
432  tde = iter;
433  prev->next = iter->next;
434  iter = iter->next;
435  SCFree(tde);
436  (void) SC_ATOMIC_SUB(num_tags, 1);
437  continue;
438  } else {
439  tde = iter;
440  iter = iter->next;
441  SCFree(tde);
442  (void) SC_ATOMIC_SUB(num_tags, 1);
443  HostSetStorageById(host, host_tag_id, iter);
444  continue;
445  }
446  } else if (flag_added == 0) {
447  /* It's matching the tag. Add it to be logged and
448  * update "flag_added" to add the packet once. */
449  p->flags |= PKT_HAS_TAG;
450  flag_added++;
451  }
452  break;
454  /* last_ts handles this metric, but also a generic time based
455  * expiration to prevent dead sessions/hosts */
456  if (SCTIME_SECS(iter->last_ts) - SCTIME_SECS(iter->first_ts) > iter->count) {
457  SCLogDebug("host tag expired: %" PRIu64 " - %" PRIu64 " = %" PRIu64 " > %u",
458  (uint64_t)SCTIME_SECS(iter->last_ts),
459  (uint64_t)SCTIME_SECS(iter->first_ts),
460  (uint64_t)(SCTIME_SECS(iter->last_ts) -
461  SCTIME_SECS(iter->first_ts)),
462  iter->count);
463  /* tag expired */
464  if (prev != NULL) {
465  tde = iter;
466  prev->next = iter->next;
467  iter = iter->next;
468  SCFree(tde);
469  (void) SC_ATOMIC_SUB(num_tags, 1);
470  continue;
471  } else {
472  tde = iter;
473  iter = iter->next;
474  SCFree(tde);
475  (void) SC_ATOMIC_SUB(num_tags, 1);
476  HostSetStorageById(host, host_tag_id, iter);
477  continue;
478  }
479  } else if (flag_added == 0) {
480  /* It's matching the tag. Add it to be logged and
481  * update "flag_added" to add the packet once. */
482  p->flags |= PKT_HAS_TAG;
483  flag_added++;
484  }
485  break;
486  }
487 
488  }
489 
490  prev = iter;
491  iter = iter->next;
492  }
493 }
494 
495 static Host *GetLockedSrcHost(Packet *p)
496 {
497  if (p->host_src == NULL) {
499  } else {
500  HostLock(p->host_src);
501  }
502  return p->host_src;
503 }
504 
505 static Host *GetLockedDstHost(Packet *p)
506 {
507  if (p->host_dst == NULL) {
509  } else {
510  HostLock(p->host_dst);
511  }
512  return p->host_dst;
513 }
514 
515 /**
516  * \brief Search tags for src and dst. Update entries of the tag, remove if necessary
517  *
518  * \param de_ctx Detect context
519  * \param det_ctx Detect thread context
520  * \param p packet
521  *
522  */
524 {
525  SCEnter();
526 
527  /* If there's no tag, get out of here */
528  unsigned int current_tags = SC_ATOMIC_GET(num_tags);
529  if (current_tags == 0)
530  SCReturn;
531 
532  /* First update and get session tags */
533  if (p->flow != NULL) {
534  TagHandlePacketFlow(p->flow, p);
535  }
536 
537  Host *src = GetLockedSrcHost(p);
538  if (src != NULL) {
539  if (TagHostHasTag(src)) {
540  TagHandlePacketHost(src, p);
541  }
542  HostUnlock(src);
543  }
544 
545  Host *dst = GetLockedDstHost(p);
546  if (dst != NULL) {
547  if (TagHostHasTag(dst)) {
548  TagHandlePacketHost(dst, p);
549  }
550  HostUnlock(dst);
551  }
552 
553  SCReturn;
554 }
555 
556 /**
557  * \brief Removes the entries exceeding the max timeout value
558  *
559  * \param tag_ctx Tag context
560  * \param ts the current time
561  *
562  * \retval 1 no tags or tags removed -- host is free to go (from tag perspective)
563  * \retval 0 still active tags
564  */
566 {
567  DetectTagDataEntry *tde = NULL;
568  DetectTagDataEntry *tmp = NULL;
569  DetectTagDataEntry *prev = NULL;
570  int retval = 1;
571 
572  tmp = HostGetStorageById(host, host_tag_id);
573  if (tmp == NULL)
574  return 1;
575 
576  prev = NULL;
577  while (tmp != NULL) {
579  if (SCTIME_CMP_GTE(timeout_at, ts)) {
580  prev = tmp;
581  tmp = tmp->next;
582  retval = 0;
583  continue;
584  }
585 
586  /* timed out */
587 
588  if (prev != NULL) {
589  prev->next = tmp->next;
590 
591  tde = tmp;
592  tmp = tde->next;
593 
594  SCFree(tde);
595  (void) SC_ATOMIC_SUB(num_tags, 1);
596  } else {
597  HostSetStorageById(host, host_tag_id, tmp->next);
598 
599  tde = tmp;
600  tmp = tde->next;
601 
602  SCFree(tde);
603  (void) SC_ATOMIC_SUB(num_tags, 1);
604  }
605  }
606  return retval;
607 }
608 
609 #ifdef UNITTESTS
610 
611 /**
612  * \test host tagging: packets
613  */
614 static int DetectTagTestPacket01 (void)
615 {
616  uint8_t *buf = (uint8_t *)"Hi all!";
617  uint8_t *buf2 = (uint8_t *)"lalala!";
618  uint16_t buf_len = strlen((char *)buf);
619  uint16_t buf_len2 = strlen((char *)buf2);
620 
621  Packet *p[7];
622  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
623  "192.168.1.5", "192.168.1.1",
624  41424, 80);
625  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
626  "192.168.1.5", "192.168.1.1",
627  41424, 80);
628  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
629  "192.168.1.5", "192.168.1.9",
630  41424, 80);
631  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
632  "192.168.1.5", "192.168.1.9",
633  41424, 80);
634  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
635  "192.168.1.1", "192.168.1.9",
636  41424, 80);
637  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
638  "192.168.1.1", "192.168.1.11",
639  41424, 80);
640  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
641  "192.168.1.5", "192.168.1.11",
642  41424, 80);
643 
644  const char *sigs[5];
645  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host,3,packets,src; sid:1;)";
646  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host,4,packets,dst; sid:2;)";
647  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
648  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
649  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
650 
651  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
652  uint32_t sid[5] = {1,2,3,4,5};
653 
654  int32_t results[7][5] = {
655  {1, 1, 0, 0, 0},
656  {0, 0, 0, 0, 0},
657  {0, 0, 0, 0, 0},
658  {0, 0, 0, 0, 0},
659  {0, 0, 0, 0, 0},
660  {0, 0, 0, 0, 0},
661  {0, 0, 0, 0, 0}
662  };
663  StorageCleanup();
664  StorageInit();
665  TagInitCtx();
666  StorageFinalize();
667  HostInitConfig(1);
668 
669  SCLogDebug("running tests");
670  FAIL_IF_NOT(UTHGenericTest(p, 7, sigs, sid, (uint32_t *)results, 5));
671  SCLogDebug("running tests done");
672 
673  Host *src = HostLookupHostFromHash(&p[1]->src);
674  FAIL_IF_NULL(src);
675  FAIL_IF_NOT_NULL(HostGetStorageById(src, host_tag_id));
676 
677  Host *dst = HostLookupHostFromHash(&p[1]->dst);
678  FAIL_IF_NULL(dst);
679 
680  void *tag = HostGetStorageById(dst, host_tag_id);
681  FAIL_IF_NULL(tag);
682 
683  DetectTagDataEntry *iter = tag;
684 
685  /* check internal state */
686  FAIL_IF_NOT(iter->gid == 1);
687  FAIL_IF_NOT(iter->sid == 2);
688  FAIL_IF_NOT(iter->packets == 4);
689  FAIL_IF_NOT(iter->count == 4);
690 
691  HostRelease(src);
692  HostRelease(dst);
693 
694  UTHFreePackets(p, 7);
695 
696  HostShutdown();
697  TagDestroyCtx();
698  StorageCleanup();
699  PASS;
700 }
701 
702 /**
703  * \test host tagging: seconds
704  */
705 static int DetectTagTestPacket02 (void)
706 {
707  uint8_t *buf = (uint8_t *)"Hi all!";
708  uint8_t *buf2 = (uint8_t *)"lalala!";
709  uint16_t buf_len = strlen((char *)buf);
710  uint16_t buf_len2 = strlen((char *)buf2);
711 
713  ThreadVars th_v;
714  DetectEngineThreadCtx *det_ctx = NULL;
715  memset(&dtv, 0, sizeof(DecodeThreadVars));
716  memset(&th_v, 0, sizeof(th_v));
717 
718  StorageCleanup();
719  StorageInit();
720  TagInitCtx();
721  StorageFinalize();
722  HostInitConfig(1);
723 
726  de_ctx->flags |= DE_QUIET;
727 
728  Packet *p[7];
729  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
730  "192.168.1.5", "192.168.1.1",
731  41424, 80);
732  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
733  "192.168.1.5", "192.168.1.1",
734  41424, 80);
735  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
736  "192.168.1.5", "192.168.1.9",
737  41424, 80);
738  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
739  "192.168.1.5", "192.168.1.9",
740  41424, 80);
741  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
742  "192.168.1.1", "192.168.1.9",
743  41424, 80);
744  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
745  "192.168.1.1", "192.168.1.11",
746  41424, 80);
747  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
748  "192.168.1.5", "192.168.1.11",
749  41424, 80);
750 
751  const char *sigs[5];
752  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host,3,seconds,src; sid:1;)";
753  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host,8,seconds,dst; sid:2;)";
754  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
755  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
756  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
757 
758  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
759  uint32_t sid[5] = {1,2,3,4,5};
760  int numsigs = 5;
761 
762  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
763 
764  //de_ctx->flags |= DE_QUIET;
765 
766  int32_t results[7][5] = {
767  {1, 1, 0, 0, 0},
768  {0, 0, 0, 0, 0},
769  {0, 0, 0, 0, 0},
770  {0, 0, 0, 0, 0},
771  {0, 0, 0, 0, 0},
772  {0, 0, 0, 0, 0},
773  {0, 0, 0, 0, 0}
774  };
775 
776  int num_packets = 7;
778  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
779 
780  int i = 0;
781  for (; i < num_packets; i++) {
782  SCLogDebug("packet %d", i);
783  p[i]->ts = TimeGet();
784  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
785  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
786 
788  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
789 
790  /* see if the PKT_HAS_TAG is set on the packet if needed */
791  bool expect = (i == 1 || i == 4);
792  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
793  }
794 
795  UTHFreePackets(p, 7);
796  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
798 
799  HostShutdown();
800  TagDestroyCtx();
801  StorageCleanup();
802  StatsThreadCleanup(&th_v);
803  PASS;
804 }
805 
806 /**
807  * \test host tagging: bytes
808  */
809 static int DetectTagTestPacket03 (void)
810 {
811  uint8_t *buf = (uint8_t *)"Hi all!";
812  uint8_t *buf2 = (uint8_t *)"lalala!";
813  uint16_t buf_len = strlen((char *)buf);
814  uint16_t buf_len2 = strlen((char *)buf2);
815 
817  ThreadVars th_v;
818  DetectEngineThreadCtx *det_ctx = NULL;
819  memset(&dtv, 0, sizeof(DecodeThreadVars));
820  memset(&th_v, 0, sizeof(th_v));
821 
822  StorageCleanup();
823  StorageInit();
824  TagInitCtx();
825  StorageFinalize();
826  HostInitConfig(1);
827 
830 
831  de_ctx->flags |= DE_QUIET;
832 
833  Packet *p[7];
834  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
835  "192.168.1.5", "192.168.1.1",
836  41424, 80);
837  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
838  "192.168.1.5", "192.168.1.1",
839  41424, 80);
840  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
841  "192.168.1.5", "192.168.1.9",
842  41424, 80);
843  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
844  "192.168.1.5", "192.168.1.9",
845  41424, 80);
846  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
847  "192.168.1.1", "192.168.1.9",
848  41424, 80);
849  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
850  "192.168.1.1", "192.168.1.11",
851  41424, 80);
852  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
853  "192.168.1.5", "192.168.1.11",
854  41424, 80);
855 
856  const char *sigs[5];
857  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host, 150, bytes, src; sid:1;)";
858  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host, 150, bytes, dst; sid:2;)";
859  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
860  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
861  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
862 
863  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
864  uint32_t sid[5] = {1,2,3,4,5};
865  int numsigs = 5;
866 
867  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
868 
869  int32_t results[7][5] = {
870  {1, 1, 0, 0, 0},
871  {0, 0, 0, 0, 0},
872  {0, 0, 0, 0, 0},
873  {0, 0, 0, 0, 0},
874  {0, 0, 0, 0, 0},
875  {0, 0, 0, 0, 0},
876  {0, 0, 0, 0, 0}
877  };
878 
879  int num_packets = 7;
881  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
882 
883  int i = 0;
884  for (; i < num_packets; i++) {
885  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
886 
887  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
888 
889  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
890 
891  /* see if the PKT_HAS_TAG is set on the packet if needed */
892  bool expect = (i == 1 || i == 2 || i == 4);
893  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
894  }
895 
896  UTHFreePackets(p, 7);
897  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
899 
900  HostShutdown();
901  TagDestroyCtx();
902  StorageCleanup();
903  StatsThreadCleanup(&th_v);
904  PASS;
905 }
906 
907 /**
908  * \test session tagging: packets
909  */
910 static int DetectTagTestPacket04 (void)
911 {
912  uint8_t *buf = (uint8_t *)"Hi all!";
913  uint8_t *buf2 = (uint8_t *)"lalala!";
914  uint16_t buf_len = strlen((char *)buf);
915  uint16_t buf_len2 = strlen((char *)buf2);
916 
917  TcpSession ssn;
918  memset(&ssn, 0, sizeof(ssn));
919 
920  StorageCleanup();
921  StorageInit();
922  TagInitCtx();
923  StorageFinalize();
924  HostInitConfig(1);
925  FlowInitConfig(1);
926 
927  Flow *f = FlowAlloc();
928  FAIL_IF_NULL(f);
929  FLOW_INITIALIZE(f);
930  f->protoctx = (void *)&ssn;
931  f->flags |= FLOW_IPV4;
932  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
933  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
934 
936  ThreadVars th_v;
937  DetectEngineThreadCtx *det_ctx = NULL;
938  memset(&dtv, 0, sizeof(DecodeThreadVars));
939  memset(&th_v, 0, sizeof(th_v));
940 
943  de_ctx->flags |= DE_QUIET;
944 
945  Packet *p[7];
946  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
947  "192.168.1.5", "192.168.1.1",
948  41424, 80);
949  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
950  "192.168.1.5", "192.168.1.1",
951  41424, 80);
952  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
953  "192.168.1.5", "192.168.1.1",
954  41424, 80);
955  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
956  "192.168.1.5", "192.168.1.1",
957  41424, 80);
958  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
959  "192.168.1.1", "192.168.1.5",
960  80, 41424);
961  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
962  "192.168.1.1", "192.168.1.5",
963  80, 41424);
964  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
965  "192.168.1.5", "192.168.1.1",
966  80, 41424);
967 
968  const char *sigs[5];
969  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,4,packets; sid:1;)";
970  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
971  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
972  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
973  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
974 
975  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
976  uint32_t sid[5] = {1,2,3,4,5};
977  int numsigs = 5;
978 
979  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
980 
981  int32_t results[7][5] = {
982  {1, 0, 0, 0, 0},
983  {0, 0, 0, 0, 0},
984  {0, 0, 0, 0, 0},
985  {0, 0, 0, 0, 0},
986  {0, 0, 0, 0, 0},
987  {0, 0, 0, 0, 0},
988  {0, 0, 0, 0, 0}
989  };
990 
991  int num_packets = 7;
993  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
994 
995  int i = 0;
996  for (; i < num_packets; i++) {
997  p[i]->flow = f;
998  p[i]->flow->protoctx = &ssn;
999  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1000 
1001  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
1002 
1003  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1004  /* see if the PKT_HAS_TAG is set on the packet if needed */
1005  bool expect = (i == 1 || i == 2 || i == 3);
1006  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1007  }
1008 
1009  UTHFreePackets(p, 7);
1010  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1012 
1013  /* clean up flow */
1014  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1015  FlowClearMemory(f, proto_map);
1016  FLOW_DESTROY(f);
1017  FlowFree(f);
1018 
1019  FlowShutdown();
1020  HostShutdown();
1021  TagDestroyCtx();
1022  StorageCleanup();
1023  StatsThreadCleanup(&th_v);
1024  PASS;
1025 }
1026 
1027 /**
1028  * \test session tagging: seconds
1029  */
1030 static int DetectTagTestPacket05 (void)
1031 {
1032  uint8_t *buf = (uint8_t *)"Hi all!";
1033  uint8_t *buf2 = (uint8_t *)"lalala!";
1034  uint16_t buf_len = strlen((char *)buf);
1035  uint16_t buf_len2 = strlen((char *)buf2);
1036 
1037  TcpSession ssn;
1038  memset(&ssn, 0, sizeof(ssn));
1039 
1040  StorageCleanup();
1041  StorageInit();
1042  TagInitCtx();
1043  StorageFinalize();
1044  HostInitConfig(1);
1045  FlowInitConfig(1);
1046 
1047  Flow *f = FlowAlloc();
1048  FAIL_IF_NULL(f);
1049  FLOW_INITIALIZE(f);
1050  f->protoctx = (void *)&ssn;
1051  f->flags |= FLOW_IPV4;
1052  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
1053  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
1054 
1056  ThreadVars th_v;
1057  DetectEngineThreadCtx *det_ctx = NULL;
1058  memset(&dtv, 0, sizeof(DecodeThreadVars));
1059  memset(&th_v, 0, sizeof(th_v));
1060 
1063  de_ctx->flags |= DE_QUIET;
1064 
1065  Packet *p[7];
1066  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1067  "192.168.1.5", "192.168.1.1",
1068  41424, 80);
1069  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1070  "192.168.1.5", "192.168.1.1",
1071  41424, 80);
1072  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1073  "192.168.1.5", "192.168.1.1",
1074  41424, 80);
1075  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1076  "192.168.1.5", "192.168.1.1",
1077  41424, 80);
1078  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1079  "192.168.1.1", "192.168.1.5",
1080  80, 41424);
1081  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1082  "192.168.1.1", "192.168.1.5",
1083  80, 41424);
1084  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1085  "192.168.1.5", "192.168.1.1",
1086  80, 41424);
1087 
1088  const char *sigs[5];
1089  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,8,seconds; sid:1;)";
1090  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
1091  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
1092  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
1093  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
1094 
1095  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
1096  uint32_t sid[5] = {1,2,3,4,5};
1097  int numsigs = 5;
1098 
1099  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
1100 
1101  int32_t results[7][5] = {
1102  {1, 0, 0, 0, 0},
1103  {0, 0, 0, 0, 0},
1104  {0, 0, 0, 0, 0},
1105  {0, 0, 0, 0, 0},
1106  {0, 0, 0, 0, 0},
1107  {0, 0, 0, 0, 0},
1108  {0, 0, 0, 0, 0}
1109  };
1110 
1111  int num_packets = 7;
1113  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1114 
1115  int i = 0;
1116  for (; i < num_packets; i++) {
1117  p[i]->flow = f;
1118  p[i]->flow->protoctx = &ssn;
1119 
1120  SCLogDebug("packet %d", i);
1121  p[i]->ts = TimeGet();
1122  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1123 
1124  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
1125 
1127 
1128  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1129  /* see if the PKT_HAS_TAG is set on the packet if needed */
1130  bool expect = (i == 1 || i == 2 || i == 3 || i == 4);
1131  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1132  }
1133 
1134  UTHFreePackets(p, 7);
1135  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1137 
1138  /* clean up flow */
1139  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1140  FlowClearMemory(f, proto_map);
1141  FLOW_DESTROY(f);
1142  FlowFree(f);
1143 
1144  FlowShutdown();
1145  HostShutdown();
1146  TagDestroyCtx();
1147  StorageCleanup();
1148  StatsThreadCleanup(&th_v);
1149  PASS;
1150 }
1151 
1152 /**
1153  * \test session tagging: bytes
1154  */
1155 static int DetectTagTestPacket06 (void)
1156 {
1157  uint8_t *buf = (uint8_t *)"Hi all!";
1158  uint8_t *buf2 = (uint8_t *)"lalala!";
1159  uint16_t buf_len = strlen((char *)buf);
1160  uint16_t buf_len2 = strlen((char *)buf2);
1161 
1162  TcpSession ssn;
1163  memset(&ssn, 0, sizeof(ssn));
1164 
1165  StorageCleanup();
1166  StorageInit();
1167  TagInitCtx();
1168  StorageFinalize();
1169  HostInitConfig(1);
1170  FlowInitConfig(1);
1171 
1172  Flow *f = FlowAlloc();
1173  FAIL_IF_NULL(f);
1174  FLOW_INITIALIZE(f);
1175  f->protoctx = (void *)&ssn;
1176  f->flags |= FLOW_IPV4;
1177  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
1178  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
1179 
1181  ThreadVars th_v;
1182  DetectEngineThreadCtx *det_ctx = NULL;
1183  memset(&dtv, 0, sizeof(DecodeThreadVars));
1184  memset(&th_v, 0, sizeof(th_v));
1185 
1188  de_ctx->flags |= DE_QUIET;
1189 
1190  Packet *p[7];
1191  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1192  "192.168.1.5", "192.168.1.1",
1193  41424, 80);
1194  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1195  "192.168.1.5", "192.168.1.1",
1196  41424, 80);
1197  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1198  "192.168.1.5", "192.168.1.1",
1199  41424, 80);
1200  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1201  "192.168.1.5", "192.168.1.1",
1202  41424, 80);
1203  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1204  "192.168.1.1", "192.168.1.5",
1205  80, 41424);
1206  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1207  "192.168.1.1", "192.168.1.5",
1208  80, 41424);
1209  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1210  "192.168.1.5", "192.168.1.1",
1211  80, 41424);
1212 
1213  const char *sigs[5];
1214  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,150,bytes; sid:1;)";
1215  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
1216  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
1217  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
1218  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
1219 
1220  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
1221  uint32_t sid[5] = {1,2,3,4,5};
1222  int numsigs = 5;
1223 
1224  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
1225 
1226  int32_t results[7][5] = {
1227  {1, 0, 0, 0, 0},
1228  {0, 0, 0, 0, 0},
1229  {0, 0, 0, 0, 0},
1230  {0, 0, 0, 0, 0},
1231  {0, 0, 0, 0, 0},
1232  {0, 0, 0, 0, 0},
1233  {0, 0, 0, 0, 0}
1234  };
1235 
1236  int num_packets = 7;
1238  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1239 
1240  int i = 0;
1241  for (; i < num_packets; i++) {
1242  p[i]->flow = f;
1243  p[i]->flow->protoctx = &ssn;
1244  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1245 
1246  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
1247 
1248  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1249 
1250  /* see if the PKT_HAS_TAG is set on the packet if needed */
1251  bool expect = (i == 1 || i == 2);
1252  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1253  }
1254 
1255  UTHFreePackets(p, 7);
1256  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1258 
1259  /* clean up flow */
1260  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1261  FlowClearMemory(f, proto_map);
1262  FLOW_DESTROY(f);
1263  FlowFree(f);
1264 
1265  FlowShutdown();
1266  HostShutdown();
1267  TagDestroyCtx();
1268  StorageCleanup();
1269  StatsThreadCleanup(&th_v);
1270  PASS;
1271 }
1272 
1273 /**
1274  * \test session tagging: bytes, where a 2nd match makes us tag more
1275  */
1276 static int DetectTagTestPacket07 (void)
1277 {
1278  uint8_t *buf = (uint8_t *)"Hi all!";
1279  uint8_t *buf2 = (uint8_t *)"lalala!";
1280  uint16_t buf_len = strlen((char *)buf);
1281  uint16_t buf_len2 = strlen((char *)buf2);
1282 
1283  TcpSession ssn;
1284  memset(&ssn, 0, sizeof(ssn));
1285 
1286  StorageCleanup();
1287  StorageInit();
1288  TagInitCtx();
1289  StorageFinalize();
1290  HostInitConfig(1);
1291  FlowInitConfig(1);
1292 
1293  Flow *f = FlowAlloc();
1294  FAIL_IF_NULL(f);
1295  FLOW_INITIALIZE(f);
1296  f->protoctx = (void *)&ssn;
1297  f->flags |= FLOW_IPV4;
1298  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
1299  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
1300 
1302  ThreadVars th_v;
1303  DetectEngineThreadCtx *det_ctx = NULL;
1304  memset(&dtv, 0, sizeof(DecodeThreadVars));
1305  memset(&th_v, 0, sizeof(th_v));
1306 
1309  de_ctx->flags |= DE_QUIET;
1310 
1311  Packet *p[7];
1312  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1313  "192.168.1.5", "192.168.1.1",
1314  41424, 80);
1315  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1316  "192.168.1.5", "192.168.1.1",
1317  41424, 80);
1318  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1319  "192.168.1.5", "192.168.1.1",
1320  41424, 80);
1321  p[3] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1322  "192.168.1.5", "192.168.1.1",
1323  41424, 80);
1324  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1325  "192.168.1.1", "192.168.1.5",
1326  80, 41424);
1327  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1328  "192.168.1.1", "192.168.1.5",
1329  80, 41424);
1330  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1331  "192.168.1.5", "192.168.1.1",
1332  80, 41424);
1333 
1334  const char *sigs[5];
1335  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,150,bytes; sid:1;)";
1336  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
1337  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
1338  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
1339  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
1340 
1341  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
1342  uint32_t sid[5] = {1,2,3,4,5};
1343  int numsigs = 5;
1344 
1345  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
1346  int32_t results[7][5] = {
1347  {1, 0, 0, 0, 0},
1348  {0, 0, 0, 0, 0},
1349  {0, 0, 0, 0, 0},
1350  {1, 0, 0, 0, 0},
1351  {0, 0, 0, 0, 0},
1352  {0, 0, 0, 0, 0},
1353  {0, 0, 0, 0, 0}
1354  };
1355 
1356  int num_packets = 7;
1358  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1359 
1360  int i = 0;
1361  for (; i < num_packets; i++) {
1362  p[i]->flow = f;
1363  p[i]->flow->protoctx = &ssn;
1364  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1365 
1366  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
1367 
1368  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1369 
1370  /* see if the PKT_HAS_TAG is set on the packet if needed */
1371  bool expect = (i == 1 || i == 2 || i == 3 || i == 4 || i == 5);
1372  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1373  }
1374 
1375  UTHFreePackets(p, 7);
1376  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1378 
1379  /* clean up flow */
1380  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1381  FlowClearMemory(f, proto_map);
1382  FLOW_DESTROY(f);
1383  FlowFree(f);
1384 
1385  FlowShutdown();
1386  HostShutdown();
1387  TagDestroyCtx();
1388  StorageCleanup();
1389  StatsThreadCleanup(&th_v);
1390  PASS;
1391 }
1392 
1393 #endif /* UNITTESTS */
1394 
1395 /**
1396  * \brief this function registers unit tests for DetectTag
1397  */
1399 {
1400 #ifdef UNITTESTS
1401  UtRegisterTest("DetectTagTestPacket01", DetectTagTestPacket01);
1402  UtRegisterTest("DetectTagTestPacket02", DetectTagTestPacket02);
1403  UtRegisterTest("DetectTagTestPacket03", DetectTagTestPacket03);
1404  UtRegisterTest("DetectTagTestPacket04", DetectTagTestPacket04);
1405  UtRegisterTest("DetectTagTestPacket05", DetectTagTestPacket05);
1406  UtRegisterTest("DetectTagTestPacket06", DetectTagTestPacket06);
1407  UtRegisterTest("DetectTagTestPacket07", DetectTagTestPacket07);
1408 #endif /* UNITTESTS */
1409 }
1410 
FlowStorageId
Definition: flow-storage.h:31
DETECT_TAG_MATCH_LIMIT
#define DETECT_TAG_MATCH_LIMIT
Definition: detect-tag.h:32
DetectTagDataEntry_::bytes
uint32_t bytes
Definition: detect-tag.h:80
host.h
HostUnlock
void HostUnlock(Host *h)
Definition: host.c:472
TagInitCtx
void TagInitCtx(void)
Definition: detect-engine-tag.c:52
ts
uint64_t ts
Definition: source-erf-file.c:55
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
host-storage.h
SC_ATOMIC_DECLARE
SC_ATOMIC_DECLARE(unsigned int, num_tags)
StorageInit
void StorageInit(void)
Definition: util-storage.c:70
util-hashlist.h
flow-util.h
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
Definition: util-atomic.h:314
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
Packet_::host_src
struct Host_ * host_src
Definition: decode.h:622
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
HostStorageRegister
HostStorageId HostStorageRegister(const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void(*Free)(void *))
Register a Host storage.
Definition: host-storage.c:59
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:279
DetectTagDataEntry_
Definition: detect-tag.h:69
Flow_::proto
uint8_t proto
Definition: flow.h:370
DetectTagDataEntry_::cnt_match
uint16_t cnt_match
Definition: detect-tag.h:73
Packet_::flags
uint32_t flags
Definition: decode.h:544
Flow_
Flow data structure.
Definition: flow.h:348
DETECT_TAG_METRIC_BYTES
@ DETECT_TAG_METRIC_BYTES
Definition: detect-tag.h:57
HostRelease
void HostRelease(Host *h)
Definition: host.c:461
util-hash.h
DetectTagDataEntry_::sid
uint32_t sid
Definition: detect-tag.h:76
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:332
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:933
HostGetHostFromHash
Host * HostGetHostFromHash(Address *a)
Definition: host.c:486
TAG_ENTRY_FLAG_SKIPPED_FIRST
#define TAG_ENTRY_FLAG_SKIPPED_FIRST
Definition: detect-tag.h:90
DetectTagDataListFree
void DetectTagDataListFree(void *ptr)
this function will free all the entries of a list DetectTagDataEntry
Definition: detect-tag.c:338
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2634
StorageCleanup
void StorageCleanup(void)
Definition: util-storage.c:78
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:621
HostGetStorageById
void * HostGetStorageById(Host *h, HostStorageId id)
Get a value from a given Host storage.
Definition: host-storage.c:88
TAG_ENTRY_FLAG_DIR_SRC
#define TAG_ENTRY_FLAG_DIR_SRC
Definition: detect-tag.h:88
DE_QUIET
#define DE_QUIET
Definition: detect.h:330
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:2416
DETECT_TAG_METRIC_PACKET
@ DETECT_TAG_METRIC_PACKET
Definition: detect-tag.h:55
TAG_MAX_LAST_TIME_SEEN
#define TAG_MAX_LAST_TIME_SEEN
Definition: detect-engine-tag.h:37
DETECT_TAG_METRIC_SECONDS
@ DETECT_TAG_METRIC_SECONDS
Definition: detect-tag.h:56
DetectTagDataEntry_::metric
uint8_t metric
Definition: detect-tag.h:71
detect-tag.h
Packet_::host_dst
struct Host_ * host_dst
Definition: decode.h:623
UTHBuildPacketReal
Packet * UTHBuildPacketReal(uint8_t *payload, uint16_t payload_len, uint8_t ipproto, const char *src, const char *dst, uint16_t sport, uint16_t dport)
UTHBuildPacketReal is a function that create tcp/udp packets for unittests specifying ip and port sou...
Definition: util-unittest-helper.c:260
Flow_::protoctx
void * protoctx
Definition: flow.h:433
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:100
util-unittest.h
DetectTagDataEntry_::flags
uint8_t flags
Definition: detect-tag.h:70
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
DetectTagDataEntry_::gid
uint32_t gid
Definition: detect-tag.h:77
tag
uint32_t tag
Definition: decode-vntag.h:0
Flow_::dst
FlowAddress dst
Definition: flow.h:351
DETECT_TAG_MAX_TAGS
#define DETECT_TAG_MAX_TAGS
Definition: detect-tag.h:35
FlowInitConfig
void FlowInitConfig(bool quiet)
initialize the configuration
Definition: flow.c:549
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:38
DetectTagDataEntry_::count
uint32_t count
Definition: detect-tag.h:75
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
TagHostHasTag
int TagHostHasTag(Host *host)
Definition: detect-engine-tag.c:79
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
TAG_ENTRY_FLAG_DIR_DST
#define TAG_ENTRY_FLAG_DIR_DST
Definition: detect-tag.h:89
DetectEngineThreadCtx_
Definition: detect.h:1245
Packet_::ts
SCTime_t ts
Definition: decode.h:555
SCEnter
#define SCEnter(...)
Definition: util-debug.h:281
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
Definition: detect-engine.c:3364
FlowSetStorageById
int FlowSetStorageById(Flow *f, FlowStorageId id, void *ptr)
Definition: flow-storage.c:45
util-atomic.h
FlowStorageRegister
FlowStorageId FlowStorageRegister(const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void(*Free)(void *))
Definition: flow-storage.c:66
util-time.h
HostLock
void HostLock(Host *h)
Definition: host.c:467
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:317
detect-engine-tag.h
SC_ATOMIC_SUB
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:341
SCReturn
#define SCReturn
Definition: util-debug.h:283
TimeSetIncrementTime
void TimeSetIncrementTime(uint32_t tv_sec)
increment the time in the engine
Definition: util-time.c:180
FlowGetProtoMapping
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition: flow-util.c:99
Packet_
Definition: decode.h:501
detect-engine-build.h
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:208
TimeGet
SCTime_t TimeGet(void)
Definition: util-time.c:152
stream-tcp-private.h
StorageFinalize
int StorageFinalize(void)
Definition: util-storage.c:140
SCTime_t
Definition: util-time.h:40
FlowClearMemory
int FlowClearMemory(Flow *f, uint8_t proto_map)
Function clear the flow memory before queueing it to spare flow queue.
Definition: flow.c:1099
DetectTagDataEntry_::first_ts
SCTime_t first_ts
Definition: detect-tag.h:82
FlowGetStorageById
void * FlowGetStorageById(const Flow *f, FlowStorageId id)
Definition: flow-storage.c:40
PKT_FIRST_TAG
#define PKT_FIRST_TAG
Definition: decode.h:1318
Flow_::src
FlowAddress src
Definition: flow.h:351
TagHandlePacket
void TagHandlePacket(const DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
Search tags for src and dst. Update entries of the tag, remove if necessary.
Definition: detect-engine-tag.c:523
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2194
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:33
TagTimeoutCheck
int TagTimeoutCheck(Host *host, SCTime_t ts)
Removes the entries exceeding the max timeout value.
Definition: detect-engine-tag.c:565
DetectTagDataEntry_::packets
uint32_t packets
Definition: detect-tag.h:79
flow-storage.h
Packet_::flow
struct Flow_ * flow
Definition: decode.h:546
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
FlowFree
void FlowFree(Flow *f)
cleanup & free the memory of a flow
Definition: flow-util.c:84
FlowShutdown
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:693
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3596
SCTIME_SECS
#define SCTIME_SECS(t)
Definition: util-time.h:57
DetectTagDataEntry_::last_ts
SCTime_t last_ts
Definition: detect-tag.h:83
HostShutdown
void HostShutdown(void)
shutdown the flow engine
Definition: host.c:296
FatalError
#define FatalError(...)
Definition: util-debug.h:514
UTHGenericTest
int UTHGenericTest(Packet **pkt, int numpkts, const char *sigs[], uint32_t sids[], uint32_t *results, int numsigs)
UTHGenericTest: function that perform a generic check taking care of as maximum common unittest eleme...
Definition: util-unittest-helper.c:581
HostStorageId_
Definition: host-storage.h:31
DetectEngineTagRegisterTests
void DetectEngineTagRegisterTests(void)
this function registers unit tests for DetectTag
Definition: detect-engine-tag.c:1398
HostStorageId_::id
int id
Definition: host-storage.h:32
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SCTIME_CMP_GTE
#define SCTIME_CMP_GTE(a, b)
Definition: util-time.h:103
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:963
Flow_::flags
uint32_t flags
Definition: flow.h:413
TagFlowAdd
int TagFlowAdd(Packet *p, DetectTagDataEntry *tde)
This function is used to add a tag to a session (type session) or update it if it's already installed...
Definition: detect-engine-tag.c:115
src
uint16_t src
Definition: app-layer-dnp3.h:5
TagHashAddTag
int TagHashAddTag(DetectTagDataEntry *tde, Packet *p)
Add a tag entry for a host. If it already exist, update it.
Definition: detect-engine-tag.c:173
FlowStorageId::id
int id
Definition: flow-storage.h:32
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2595
DetectTagDataEntry_::next
struct DetectTagDataEntry_ * next
Definition: detect-tag.h:84
HostLookupHostFromHash
Host * HostLookupHostFromHash(Address *a)
look up a host in the hash
Definition: host.c:585
Packet_::dst
Address dst
Definition: decode.h:506
HostInitConfig
void HostInitConfig(bool quiet)
initialize the configuration
Definition: host.c:168
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:935
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:654
dst
uint16_t dst
Definition: app-layer-dnp3.h:4
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:375
TcpSession_
Definition: stream-tcp-private.h:283
PKT_HAS_TAG
#define PKT_HAS_TAG
Definition: decode.h:1260
FlowAlloc
Flow * FlowAlloc(void)
allocate a flow
Definition: flow-util.c:56
SCTIME_ADD_SECS
#define SCTIME_ADD_SECS(ts, s)
Definition: util-time.h:64
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
Host_
Definition: host.h:58
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:285
StatsThreadCleanup
void StatsThreadCleanup(ThreadVars *tv)
Definition: counters.c:1324
HostSetStorageById
int HostSetStorageById(Host *h, HostStorageId id, void *ptr)
Store a pointer in a given Host storage.
Definition: host-storage.c:75
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:119
Packet_::src
Address src
Definition: decode.h:505
TagDestroyCtx
void TagDestroyCtx(void)
Destroy tag context hash tables.
Definition: detect-engine-tag.c:72
UTHFreePackets
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:456