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  StorageInit();
664  TagInitCtx();
665  StorageFinalize();
666  HostInitConfig(1);
667 
668  SCLogDebug("running tests");
669  FAIL_IF_NOT(UTHGenericTest(p, 7, sigs, sid, (uint32_t *)results, 5));
670  SCLogDebug("running tests done");
671 
672  Host *src = HostLookupHostFromHash(&p[1]->src);
673  FAIL_IF_NULL(src);
674  FAIL_IF_NOT_NULL(HostGetStorageById(src, host_tag_id));
675 
676  Host *dst = HostLookupHostFromHash(&p[1]->dst);
677  FAIL_IF_NULL(dst);
678 
679  void *tag = HostGetStorageById(dst, host_tag_id);
680  FAIL_IF_NULL(tag);
681 
682  DetectTagDataEntry *iter = tag;
683 
684  /* check internal state */
685  FAIL_IF_NOT(iter->gid == 1);
686  FAIL_IF_NOT(iter->sid == 2);
687  FAIL_IF_NOT(iter->packets == 4);
688  FAIL_IF_NOT(iter->count == 4);
689 
690  HostRelease(src);
691  HostRelease(dst);
692 
693  UTHFreePackets(p, 7);
694 
695  HostShutdown();
696  TagDestroyCtx();
697  StorageCleanup();
698  PASS;
699 }
700 
701 /**
702  * \test host tagging: seconds
703  */
704 static int DetectTagTestPacket02 (void)
705 {
706  uint8_t *buf = (uint8_t *)"Hi all!";
707  uint8_t *buf2 = (uint8_t *)"lalala!";
708  uint16_t buf_len = strlen((char *)buf);
709  uint16_t buf_len2 = strlen((char *)buf2);
710 
712  ThreadVars th_v;
713  DetectEngineThreadCtx *det_ctx = NULL;
714  memset(&dtv, 0, sizeof(DecodeThreadVars));
715  memset(&th_v, 0, sizeof(th_v));
716 
717  StorageInit();
718  TagInitCtx();
719  StorageFinalize();
720  HostInitConfig(1);
721 
724  de_ctx->flags |= DE_QUIET;
725 
726  Packet *p[7];
727  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
728  "192.168.1.5", "192.168.1.1",
729  41424, 80);
730  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
731  "192.168.1.5", "192.168.1.1",
732  41424, 80);
733  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
734  "192.168.1.5", "192.168.1.9",
735  41424, 80);
736  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
737  "192.168.1.5", "192.168.1.9",
738  41424, 80);
739  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
740  "192.168.1.1", "192.168.1.9",
741  41424, 80);
742  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
743  "192.168.1.1", "192.168.1.11",
744  41424, 80);
745  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
746  "192.168.1.5", "192.168.1.11",
747  41424, 80);
748 
749  const char *sigs[5];
750  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host,3,seconds,src; sid:1;)";
751  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host,8,seconds,dst; sid:2;)";
752  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
753  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
754  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
755 
756  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
757  uint32_t sid[5] = {1,2,3,4,5};
758  int numsigs = 5;
759 
760  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
761 
762  //de_ctx->flags |= DE_QUIET;
763 
764  int32_t results[7][5] = {
765  {1, 1, 0, 0, 0},
766  {0, 0, 0, 0, 0},
767  {0, 0, 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  };
773 
774  int num_packets = 7;
776  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
777 
778  int i = 0;
779  for (; i < num_packets; i++) {
780  SCLogDebug("packet %d", i);
781  p[i]->ts = TimeGet();
782  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
783  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
784 
786  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
787 
788  /* see if the PKT_HAS_TAG is set on the packet if needed */
789  bool expect = (i == 1 || i == 4);
790  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
791  }
792 
793  UTHFreePackets(p, 7);
794  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
796 
797  HostShutdown();
798  TagDestroyCtx();
799  StorageCleanup();
800  PASS;
801 }
802 
803 /**
804  * \test host tagging: bytes
805  */
806 static int DetectTagTestPacket03 (void)
807 {
808  uint8_t *buf = (uint8_t *)"Hi all!";
809  uint8_t *buf2 = (uint8_t *)"lalala!";
810  uint16_t buf_len = strlen((char *)buf);
811  uint16_t buf_len2 = strlen((char *)buf2);
812 
814  ThreadVars th_v;
815  DetectEngineThreadCtx *det_ctx = NULL;
816  memset(&dtv, 0, sizeof(DecodeThreadVars));
817  memset(&th_v, 0, sizeof(th_v));
818 
819  StorageInit();
820  TagInitCtx();
821  StorageFinalize();
822  HostInitConfig(1);
823 
826 
827  de_ctx->flags |= DE_QUIET;
828 
829  Packet *p[7];
830  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
831  "192.168.1.5", "192.168.1.1",
832  41424, 80);
833  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
834  "192.168.1.5", "192.168.1.1",
835  41424, 80);
836  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
837  "192.168.1.5", "192.168.1.9",
838  41424, 80);
839  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
840  "192.168.1.5", "192.168.1.9",
841  41424, 80);
842  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
843  "192.168.1.1", "192.168.1.9",
844  41424, 80);
845  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
846  "192.168.1.1", "192.168.1.11",
847  41424, 80);
848  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
849  "192.168.1.5", "192.168.1.11",
850  41424, 80);
851 
852  const char *sigs[5];
853  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host, 150, bytes, src; sid:1;)";
854  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host, 150, bytes, dst; sid:2;)";
855  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
856  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
857  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
858 
859  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
860  uint32_t sid[5] = {1,2,3,4,5};
861  int numsigs = 5;
862 
863  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
864 
865  int32_t results[7][5] = {
866  {1, 1, 0, 0, 0},
867  {0, 0, 0, 0, 0},
868  {0, 0, 0, 0, 0},
869  {0, 0, 0, 0, 0},
870  {0, 0, 0, 0, 0},
871  {0, 0, 0, 0, 0},
872  {0, 0, 0, 0, 0}
873  };
874 
875  int num_packets = 7;
877  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
878 
879  int i = 0;
880  for (; i < num_packets; i++) {
881  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
882 
883  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
884 
885  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
886 
887  /* see if the PKT_HAS_TAG is set on the packet if needed */
888  bool expect = (i == 1 || i == 2 || i == 4);
889  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
890  }
891 
892  UTHFreePackets(p, 7);
893  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
895 
896  HostShutdown();
897  TagDestroyCtx();
898  StorageCleanup();
899  PASS;
900 }
901 
902 /**
903  * \test session tagging: packets
904  */
905 static int DetectTagTestPacket04 (void)
906 {
907  uint8_t *buf = (uint8_t *)"Hi all!";
908  uint8_t *buf2 = (uint8_t *)"lalala!";
909  uint16_t buf_len = strlen((char *)buf);
910  uint16_t buf_len2 = strlen((char *)buf2);
911 
912  Flow *f = NULL;
913  TcpSession ssn;
914 
915  memset(&f, 0, sizeof(f));
916  memset(&ssn, 0, sizeof(ssn));
917 
918  StorageInit();
919  TagInitCtx();
920  StorageFinalize();
921  HostInitConfig(1);
922  FlowInitConfig(1);
923 
924  f = FlowAlloc();
925  FAIL_IF_NULL(f);
926  FLOW_INITIALIZE(f);
927  f->protoctx = (void *)&ssn;
928  f->flags |= FLOW_IPV4;
929  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
930  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
931 
933  ThreadVars th_v;
934  DetectEngineThreadCtx *det_ctx = NULL;
935  memset(&dtv, 0, sizeof(DecodeThreadVars));
936  memset(&th_v, 0, sizeof(th_v));
937 
940  de_ctx->flags |= DE_QUIET;
941 
942  Packet *p[7];
943  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
944  "192.168.1.5", "192.168.1.1",
945  41424, 80);
946  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
947  "192.168.1.5", "192.168.1.1",
948  41424, 80);
949  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
950  "192.168.1.5", "192.168.1.1",
951  41424, 80);
952  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
953  "192.168.1.5", "192.168.1.1",
954  41424, 80);
955  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
956  "192.168.1.1", "192.168.1.5",
957  80, 41424);
958  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
959  "192.168.1.1", "192.168.1.5",
960  80, 41424);
961  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
962  "192.168.1.5", "192.168.1.1",
963  80, 41424);
964 
965  const char *sigs[5];
966  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,4,packets; sid:1;)";
967  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
968  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
969  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
970  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
971 
972  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
973  uint32_t sid[5] = {1,2,3,4,5};
974  int numsigs = 5;
975 
976  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
977 
978  int32_t results[7][5] = {
979  {1, 0, 0, 0, 0},
980  {0, 0, 0, 0, 0},
981  {0, 0, 0, 0, 0},
982  {0, 0, 0, 0, 0},
983  {0, 0, 0, 0, 0},
984  {0, 0, 0, 0, 0},
985  {0, 0, 0, 0, 0}
986  };
987 
988  int num_packets = 7;
990  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
991 
992  int i = 0;
993  for (; i < num_packets; i++) {
994  p[i]->flow = f;
995  p[i]->flow->protoctx = &ssn;
996  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
997 
998  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
999 
1000  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1001  /* see if the PKT_HAS_TAG is set on the packet if needed */
1002  bool expect = (i == 1 || i == 2 || i == 3);
1003  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1004  }
1005 
1006  UTHFreePackets(p, 7);
1007  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1009 
1010  /* clean up flow */
1011  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1012  FlowClearMemory(f, proto_map);
1013  FLOW_DESTROY(f);
1014  FlowFree(f);
1015 
1016  FlowShutdown();
1017  HostShutdown();
1018  TagDestroyCtx();
1019  StorageCleanup();
1020  PASS;
1021 }
1022 
1023 /**
1024  * \test session tagging: seconds
1025  */
1026 static int DetectTagTestPacket05 (void)
1027 {
1028  uint8_t *buf = (uint8_t *)"Hi all!";
1029  uint8_t *buf2 = (uint8_t *)"lalala!";
1030  uint16_t buf_len = strlen((char *)buf);
1031  uint16_t buf_len2 = strlen((char *)buf2);
1032 
1033  Flow *f = NULL;
1034  TcpSession ssn;
1035 
1036  memset(&f, 0, sizeof(f));
1037  memset(&ssn, 0, sizeof(ssn));
1038 
1039  StorageInit();
1040  TagInitCtx();
1041  StorageFinalize();
1042  HostInitConfig(1);
1043  FlowInitConfig(1);
1044 
1045  f = FlowAlloc();
1046  FAIL_IF_NULL(f);
1047  FLOW_INITIALIZE(f);
1048  f->protoctx = (void *)&ssn;
1049  f->flags |= FLOW_IPV4;
1050  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
1051  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
1052 
1054  ThreadVars th_v;
1055  DetectEngineThreadCtx *det_ctx = NULL;
1056  memset(&dtv, 0, sizeof(DecodeThreadVars));
1057  memset(&th_v, 0, sizeof(th_v));
1058 
1061  de_ctx->flags |= DE_QUIET;
1062 
1063  Packet *p[7];
1064  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1065  "192.168.1.5", "192.168.1.1",
1066  41424, 80);
1067  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1068  "192.168.1.5", "192.168.1.1",
1069  41424, 80);
1070  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1071  "192.168.1.5", "192.168.1.1",
1072  41424, 80);
1073  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1074  "192.168.1.5", "192.168.1.1",
1075  41424, 80);
1076  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1077  "192.168.1.1", "192.168.1.5",
1078  80, 41424);
1079  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1080  "192.168.1.1", "192.168.1.5",
1081  80, 41424);
1082  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1083  "192.168.1.5", "192.168.1.1",
1084  80, 41424);
1085 
1086  const char *sigs[5];
1087  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,8,seconds; sid:1;)";
1088  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
1089  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
1090  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
1091  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
1092 
1093  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
1094  uint32_t sid[5] = {1,2,3,4,5};
1095  int numsigs = 5;
1096 
1097  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
1098 
1099  int32_t results[7][5] = {
1100  {1, 0, 0, 0, 0},
1101  {0, 0, 0, 0, 0},
1102  {0, 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  };
1108 
1109  int num_packets = 7;
1111  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1112 
1113  int i = 0;
1114  for (; i < num_packets; i++) {
1115  p[i]->flow = f;
1116  p[i]->flow->protoctx = &ssn;
1117 
1118  SCLogDebug("packet %d", i);
1119  p[i]->ts = TimeGet();
1120  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1121 
1122  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
1123 
1125 
1126  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1127  /* see if the PKT_HAS_TAG is set on the packet if needed */
1128  bool expect = (i == 1 || i == 2 || i == 3 || i == 4);
1129  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1130  }
1131 
1132  UTHFreePackets(p, 7);
1133  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1135 
1136  /* clean up flow */
1137  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1138  FlowClearMemory(f, proto_map);
1139  FLOW_DESTROY(f);
1140  FlowFree(f);
1141 
1142  FlowShutdown();
1143  HostShutdown();
1144  TagDestroyCtx();
1145  StorageCleanup();
1146  PASS;
1147 }
1148 
1149 /**
1150  * \test session tagging: bytes
1151  */
1152 static int DetectTagTestPacket06 (void)
1153 {
1154  uint8_t *buf = (uint8_t *)"Hi all!";
1155  uint8_t *buf2 = (uint8_t *)"lalala!";
1156  uint16_t buf_len = strlen((char *)buf);
1157  uint16_t buf_len2 = strlen((char *)buf2);
1158 
1159  Flow *f = NULL;
1160  TcpSession ssn;
1161 
1162  memset(&f, 0, sizeof(f));
1163  memset(&ssn, 0, sizeof(ssn));
1164 
1165  StorageInit();
1166  TagInitCtx();
1167  StorageFinalize();
1168  HostInitConfig(1);
1169  FlowInitConfig(1);
1170 
1171  f = FlowAlloc();
1172  FAIL_IF_NULL(f);
1173  FLOW_INITIALIZE(f);
1174  f->protoctx = (void *)&ssn;
1175  f->flags |= FLOW_IPV4;
1176  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
1177  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
1178 
1180  ThreadVars th_v;
1181  DetectEngineThreadCtx *det_ctx = NULL;
1182  memset(&dtv, 0, sizeof(DecodeThreadVars));
1183  memset(&th_v, 0, sizeof(th_v));
1184 
1187  de_ctx->flags |= DE_QUIET;
1188 
1189  Packet *p[7];
1190  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1191  "192.168.1.5", "192.168.1.1",
1192  41424, 80);
1193  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1194  "192.168.1.5", "192.168.1.1",
1195  41424, 80);
1196  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1197  "192.168.1.5", "192.168.1.1",
1198  41424, 80);
1199  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1200  "192.168.1.5", "192.168.1.1",
1201  41424, 80);
1202  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1203  "192.168.1.1", "192.168.1.5",
1204  80, 41424);
1205  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1206  "192.168.1.1", "192.168.1.5",
1207  80, 41424);
1208  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1209  "192.168.1.5", "192.168.1.1",
1210  80, 41424);
1211 
1212  const char *sigs[5];
1213  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,150,bytes; sid:1;)";
1214  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
1215  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
1216  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
1217  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
1218 
1219  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
1220  uint32_t sid[5] = {1,2,3,4,5};
1221  int numsigs = 5;
1222 
1223  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
1224 
1225  int32_t results[7][5] = {
1226  {1, 0, 0, 0, 0},
1227  {0, 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  };
1234 
1235  int num_packets = 7;
1237  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1238 
1239  int i = 0;
1240  for (; i < num_packets; i++) {
1241  p[i]->flow = f;
1242  p[i]->flow->protoctx = &ssn;
1243  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1244 
1245  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
1246 
1247  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1248 
1249  /* see if the PKT_HAS_TAG is set on the packet if needed */
1250  bool expect = (i == 1 || i == 2);
1251  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1252  }
1253 
1254  UTHFreePackets(p, 7);
1255  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1257 
1258  /* clean up flow */
1259  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1260  FlowClearMemory(f, proto_map);
1261  FLOW_DESTROY(f);
1262  FlowFree(f);
1263 
1264  FlowShutdown();
1265  HostShutdown();
1266  TagDestroyCtx();
1267  StorageCleanup();
1268  PASS;
1269 }
1270 
1271 /**
1272  * \test session tagging: bytes, where a 2nd match makes us tag more
1273  */
1274 static int DetectTagTestPacket07 (void)
1275 {
1276  uint8_t *buf = (uint8_t *)"Hi all!";
1277  uint8_t *buf2 = (uint8_t *)"lalala!";
1278  uint16_t buf_len = strlen((char *)buf);
1279  uint16_t buf_len2 = strlen((char *)buf2);
1280 
1281  Flow *f = NULL;
1282  TcpSession ssn;
1283 
1284  memset(&f, 0, sizeof(f));
1285  memset(&ssn, 0, sizeof(ssn));
1286 
1287  StorageInit();
1288  TagInitCtx();
1289  StorageFinalize();
1290  HostInitConfig(1);
1291  FlowInitConfig(1);
1292 
1293  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  PASS;
1390 }
1391 
1392 #endif /* UNITTESTS */
1393 
1394 /**
1395  * \brief this function registers unit tests for DetectTag
1396  */
1398 {
1399 #ifdef UNITTESTS
1400  UtRegisterTest("DetectTagTestPacket01", DetectTagTestPacket01);
1401  UtRegisterTest("DetectTagTestPacket02", DetectTagTestPacket02);
1402  UtRegisterTest("DetectTagTestPacket03", DetectTagTestPacket03);
1403  UtRegisterTest("DetectTagTestPacket04", DetectTagTestPacket04);
1404  UtRegisterTest("DetectTagTestPacket05", DetectTagTestPacket05);
1405  UtRegisterTest("DetectTagTestPacket06", DetectTagTestPacket06);
1406  UtRegisterTest("DetectTagTestPacket07", DetectTagTestPacket07);
1407 #endif /* UNITTESTS */
1408 }
1409 
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
DETECT_TAG_METRIC_BYTES
@ DETECT_TAG_METRIC_BYTES
Definition: detect-tag.h:57
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:275
DetectTagDataEntry_
Definition: detect-tag.h:69
Flow_::proto
uint8_t proto
Definition: flow.h:378
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:356
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:932
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:336
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2643
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:611
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:2420
TAG_MAX_LAST_TIME_SEEN
#define TAG_MAX_LAST_TIME_SEEN
Definition: detect-engine-tag.h:37
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:441
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:359
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:547
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
DETECT_TAG_METRIC_SECONDS
@ DETECT_TAG_METRIC_SECONDS
Definition: detect-tag.h:56
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:1244
Packet_::ts
SCTime_t ts
Definition: decode.h:555
SCEnter
#define SCEnter(...)
Definition: util-debug.h:277
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:3369
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:279
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:1097
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:1314
Flow_::src
FlowAddress src
Definition: flow.h:359
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:2204
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:691
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3605
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:510
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:571
HostStorageId_
Definition: host-storage.h:31
DetectEngineTagRegisterTests
void DetectEngineTagRegisterTests(void)
this function registers unit tests for DetectTag
Definition: detect-engine-tag.c:1397
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
DETECT_TAG_METRIC_PACKET
@ DETECT_TAG_METRIC_PACKET
Definition: detect-tag.h:55
Flow_::flags
uint32_t flags
Definition: flow.h:421
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:2604
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:934
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:644
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:1256
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:281
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