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  StatsThreadInit(&th_v.stats);
718 
719  StorageCleanup();
720  StorageInit();
721  TagInitCtx();
722  StorageFinalize();
723  HostInitConfig(1);
724 
727  de_ctx->flags |= DE_QUIET;
728 
729  Packet *p[7];
730  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
731  "192.168.1.5", "192.168.1.1",
732  41424, 80);
733  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
734  "192.168.1.5", "192.168.1.1",
735  41424, 80);
736  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
737  "192.168.1.5", "192.168.1.9",
738  41424, 80);
739  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
740  "192.168.1.5", "192.168.1.9",
741  41424, 80);
742  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
743  "192.168.1.1", "192.168.1.9",
744  41424, 80);
745  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
746  "192.168.1.1", "192.168.1.11",
747  41424, 80);
748  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
749  "192.168.1.5", "192.168.1.11",
750  41424, 80);
751 
752  const char *sigs[5];
753  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host,3,seconds,src; sid:1;)";
754  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host,8,seconds,dst; sid:2;)";
755  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
756  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
757  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
758 
759  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
760  uint32_t sid[5] = {1,2,3,4,5};
761  int numsigs = 5;
762 
763  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
764 
765  //de_ctx->flags |= DE_QUIET;
766 
767  int32_t results[7][5] = {
768  {1, 1, 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  {0, 0, 0, 0, 0}
775  };
776 
777  int num_packets = 7;
779  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
780 
781  int i = 0;
782  for (; i < num_packets; i++) {
783  SCLogDebug("packet %d", i);
784  p[i]->ts = TimeGet();
785  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
786  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
787 
789  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
790 
791  /* see if the PKT_HAS_TAG is set on the packet if needed */
792  bool expect = (i == 1 || i == 4);
793  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
794  }
795 
796  UTHFreePackets(p, 7);
797  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
799 
800  HostShutdown();
801  TagDestroyCtx();
802  StorageCleanup();
803  StatsThreadCleanup(&th_v.stats);
804  PASS;
805 }
806 
807 /**
808  * \test host tagging: bytes
809  */
810 static int DetectTagTestPacket03 (void)
811 {
812  uint8_t *buf = (uint8_t *)"Hi all!";
813  uint8_t *buf2 = (uint8_t *)"lalala!";
814  uint16_t buf_len = strlen((char *)buf);
815  uint16_t buf_len2 = strlen((char *)buf2);
816 
818  ThreadVars th_v;
819  DetectEngineThreadCtx *det_ctx = NULL;
820  memset(&dtv, 0, sizeof(DecodeThreadVars));
821  memset(&th_v, 0, sizeof(th_v));
822  StatsThreadInit(&th_v.stats);
823 
824  StorageCleanup();
825  StorageInit();
826  TagInitCtx();
827  StorageFinalize();
828  HostInitConfig(1);
829 
832 
833  de_ctx->flags |= DE_QUIET;
834 
835  Packet *p[7];
836  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
837  "192.168.1.5", "192.168.1.1",
838  41424, 80);
839  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
840  "192.168.1.5", "192.168.1.1",
841  41424, 80);
842  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
843  "192.168.1.5", "192.168.1.9",
844  41424, 80);
845  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
846  "192.168.1.5", "192.168.1.9",
847  41424, 80);
848  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
849  "192.168.1.1", "192.168.1.9",
850  41424, 80);
851  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
852  "192.168.1.1", "192.168.1.11",
853  41424, 80);
854  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
855  "192.168.1.5", "192.168.1.11",
856  41424, 80);
857 
858  const char *sigs[5];
859  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host, 150, bytes, src; sid:1;)";
860  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host, 150, bytes, dst; sid:2;)";
861  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
862  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
863  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
864 
865  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
866  uint32_t sid[5] = {1,2,3,4,5};
867  int numsigs = 5;
868 
869  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
870 
871  int32_t results[7][5] = {
872  {1, 1, 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  {0, 0, 0, 0, 0},
878  {0, 0, 0, 0, 0}
879  };
880 
881  int num_packets = 7;
883  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
884 
885  int i = 0;
886  for (; i < num_packets; i++) {
887  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
888 
889  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
890 
891  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
892 
893  /* see if the PKT_HAS_TAG is set on the packet if needed */
894  bool expect = (i == 1 || i == 2 || i == 4);
895  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
896  }
897 
898  UTHFreePackets(p, 7);
899  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
901 
902  HostShutdown();
903  TagDestroyCtx();
904  StorageCleanup();
905  StatsThreadCleanup(&th_v.stats);
906  PASS;
907 }
908 
909 /**
910  * \test session tagging: packets
911  */
912 static int DetectTagTestPacket04 (void)
913 {
914  uint8_t *buf = (uint8_t *)"Hi all!";
915  uint8_t *buf2 = (uint8_t *)"lalala!";
916  uint16_t buf_len = strlen((char *)buf);
917  uint16_t buf_len2 = strlen((char *)buf2);
918 
919  TcpSession ssn;
920  memset(&ssn, 0, sizeof(ssn));
921 
922  StorageCleanup();
923  StorageInit();
924  TagInitCtx();
925  StorageFinalize();
926  HostInitConfig(1);
927  FlowInitConfig(1);
928 
929  Flow *f = FlowAlloc();
930  FAIL_IF_NULL(f);
931  FLOW_INITIALIZE(f);
932  f->protoctx = (void *)&ssn;
933  f->flags |= FLOW_IPV4;
934  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
935  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
936 
938  ThreadVars th_v;
939  DetectEngineThreadCtx *det_ctx = NULL;
940  memset(&dtv, 0, sizeof(DecodeThreadVars));
941  memset(&th_v, 0, sizeof(th_v));
942  StatsThreadInit(&th_v.stats);
943 
946  de_ctx->flags |= DE_QUIET;
947 
948  Packet *p[7];
949  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
950  "192.168.1.5", "192.168.1.1",
951  41424, 80);
952  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
953  "192.168.1.5", "192.168.1.1",
954  41424, 80);
955  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
956  "192.168.1.5", "192.168.1.1",
957  41424, 80);
958  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
959  "192.168.1.5", "192.168.1.1",
960  41424, 80);
961  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
962  "192.168.1.1", "192.168.1.5",
963  80, 41424);
964  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
965  "192.168.1.1", "192.168.1.5",
966  80, 41424);
967  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
968  "192.168.1.5", "192.168.1.1",
969  80, 41424);
970 
971  const char *sigs[5];
972  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,4,packets; sid:1;)";
973  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
974  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
975  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
976  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
977 
978  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
979  uint32_t sid[5] = {1,2,3,4,5};
980  int numsigs = 5;
981 
982  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
983 
984  int32_t results[7][5] = {
985  {1, 0, 0, 0, 0},
986  {0, 0, 0, 0, 0},
987  {0, 0, 0, 0, 0},
988  {0, 0, 0, 0, 0},
989  {0, 0, 0, 0, 0},
990  {0, 0, 0, 0, 0},
991  {0, 0, 0, 0, 0}
992  };
993 
994  int num_packets = 7;
996  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
997 
998  int i = 0;
999  for (; i < num_packets; i++) {
1000  p[i]->flow = f;
1001  p[i]->flow->protoctx = &ssn;
1002  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1003 
1004  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
1005 
1006  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1007  /* see if the PKT_HAS_TAG is set on the packet if needed */
1008  bool expect = (i == 1 || i == 2 || i == 3);
1009  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1010  }
1011 
1012  UTHFreePackets(p, 7);
1013  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1015 
1016  /* clean up flow */
1017  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1018  FlowClearMemory(f, proto_map);
1019  FLOW_DESTROY(f);
1020  FlowFree(f);
1021 
1022  FlowShutdown();
1023  HostShutdown();
1024  TagDestroyCtx();
1025  StorageCleanup();
1026  StatsThreadCleanup(&th_v.stats);
1027  PASS;
1028 }
1029 
1030 /**
1031  * \test session tagging: seconds
1032  */
1033 static int DetectTagTestPacket05 (void)
1034 {
1035  uint8_t *buf = (uint8_t *)"Hi all!";
1036  uint8_t *buf2 = (uint8_t *)"lalala!";
1037  uint16_t buf_len = strlen((char *)buf);
1038  uint16_t buf_len2 = strlen((char *)buf2);
1039 
1040  TcpSession ssn;
1041  memset(&ssn, 0, sizeof(ssn));
1042 
1043  StorageCleanup();
1044  StorageInit();
1045  TagInitCtx();
1046  StorageFinalize();
1047  HostInitConfig(1);
1048  FlowInitConfig(1);
1049 
1050  Flow *f = FlowAlloc();
1051  FAIL_IF_NULL(f);
1052  FLOW_INITIALIZE(f);
1053  f->protoctx = (void *)&ssn;
1054  f->flags |= FLOW_IPV4;
1055  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
1056  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
1057 
1059  ThreadVars th_v;
1060  DetectEngineThreadCtx *det_ctx = NULL;
1061  memset(&dtv, 0, sizeof(DecodeThreadVars));
1062  memset(&th_v, 0, sizeof(th_v));
1063  StatsThreadInit(&th_v.stats);
1064 
1067  de_ctx->flags |= DE_QUIET;
1068 
1069  Packet *p[7];
1070  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1071  "192.168.1.5", "192.168.1.1",
1072  41424, 80);
1073  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1074  "192.168.1.5", "192.168.1.1",
1075  41424, 80);
1076  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1077  "192.168.1.5", "192.168.1.1",
1078  41424, 80);
1079  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1080  "192.168.1.5", "192.168.1.1",
1081  41424, 80);
1082  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1083  "192.168.1.1", "192.168.1.5",
1084  80, 41424);
1085  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1086  "192.168.1.1", "192.168.1.5",
1087  80, 41424);
1088  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1089  "192.168.1.5", "192.168.1.1",
1090  80, 41424);
1091 
1092  const char *sigs[5];
1093  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,8,seconds; sid:1;)";
1094  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
1095  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
1096  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
1097  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
1098 
1099  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
1100  uint32_t sid[5] = {1,2,3,4,5};
1101  int numsigs = 5;
1102 
1103  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
1104 
1105  int32_t results[7][5] = {
1106  {1, 0, 0, 0, 0},
1107  {0, 0, 0, 0, 0},
1108  {0, 0, 0, 0, 0},
1109  {0, 0, 0, 0, 0},
1110  {0, 0, 0, 0, 0},
1111  {0, 0, 0, 0, 0},
1112  {0, 0, 0, 0, 0}
1113  };
1114 
1115  int num_packets = 7;
1117  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1118 
1119  int i = 0;
1120  for (; i < num_packets; i++) {
1121  p[i]->flow = f;
1122  p[i]->flow->protoctx = &ssn;
1123 
1124  SCLogDebug("packet %d", i);
1125  p[i]->ts = TimeGet();
1126  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1127 
1128  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
1129 
1131 
1132  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1133  /* see if the PKT_HAS_TAG is set on the packet if needed */
1134  bool expect = (i == 1 || i == 2 || i == 3 || i == 4);
1135  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1136  }
1137 
1138  UTHFreePackets(p, 7);
1139  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1141 
1142  /* clean up flow */
1143  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1144  FlowClearMemory(f, proto_map);
1145  FLOW_DESTROY(f);
1146  FlowFree(f);
1147 
1148  FlowShutdown();
1149  HostShutdown();
1150  TagDestroyCtx();
1151  StorageCleanup();
1152  StatsThreadCleanup(&th_v.stats);
1153  PASS;
1154 }
1155 
1156 /**
1157  * \test session tagging: bytes
1158  */
1159 static int DetectTagTestPacket06 (void)
1160 {
1161  uint8_t *buf = (uint8_t *)"Hi all!";
1162  uint8_t *buf2 = (uint8_t *)"lalala!";
1163  uint16_t buf_len = strlen((char *)buf);
1164  uint16_t buf_len2 = strlen((char *)buf2);
1165 
1166  TcpSession ssn;
1167  memset(&ssn, 0, sizeof(ssn));
1168 
1169  StorageCleanup();
1170  StorageInit();
1171  TagInitCtx();
1172  StorageFinalize();
1173  HostInitConfig(1);
1174  FlowInitConfig(1);
1175 
1176  Flow *f = FlowAlloc();
1177  FAIL_IF_NULL(f);
1178  FLOW_INITIALIZE(f);
1179  f->protoctx = (void *)&ssn;
1180  f->flags |= FLOW_IPV4;
1181  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
1182  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
1183 
1185  ThreadVars th_v;
1186  DetectEngineThreadCtx *det_ctx = NULL;
1187  memset(&dtv, 0, sizeof(DecodeThreadVars));
1188  memset(&th_v, 0, sizeof(th_v));
1189  StatsThreadInit(&th_v.stats);
1190 
1193  de_ctx->flags |= DE_QUIET;
1194 
1195  Packet *p[7];
1196  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1197  "192.168.1.5", "192.168.1.1",
1198  41424, 80);
1199  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1200  "192.168.1.5", "192.168.1.1",
1201  41424, 80);
1202  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1203  "192.168.1.5", "192.168.1.1",
1204  41424, 80);
1205  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1206  "192.168.1.5", "192.168.1.1",
1207  41424, 80);
1208  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1209  "192.168.1.1", "192.168.1.5",
1210  80, 41424);
1211  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1212  "192.168.1.1", "192.168.1.5",
1213  80, 41424);
1214  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1215  "192.168.1.5", "192.168.1.1",
1216  80, 41424);
1217 
1218  const char *sigs[5];
1219  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,150,bytes; sid:1;)";
1220  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
1221  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
1222  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
1223  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
1224 
1225  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
1226  uint32_t sid[5] = {1,2,3,4,5};
1227  int numsigs = 5;
1228 
1229  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
1230 
1231  int32_t results[7][5] = {
1232  {1, 0, 0, 0, 0},
1233  {0, 0, 0, 0, 0},
1234  {0, 0, 0, 0, 0},
1235  {0, 0, 0, 0, 0},
1236  {0, 0, 0, 0, 0},
1237  {0, 0, 0, 0, 0},
1238  {0, 0, 0, 0, 0}
1239  };
1240 
1241  int num_packets = 7;
1243  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1244 
1245  int i = 0;
1246  for (; i < num_packets; i++) {
1247  p[i]->flow = f;
1248  p[i]->flow->protoctx = &ssn;
1249  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1250 
1251  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
1252 
1253  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1254 
1255  /* see if the PKT_HAS_TAG is set on the packet if needed */
1256  bool expect = (i == 1 || i == 2);
1257  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1258  }
1259 
1260  UTHFreePackets(p, 7);
1261  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1263 
1264  /* clean up flow */
1265  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1266  FlowClearMemory(f, proto_map);
1267  FLOW_DESTROY(f);
1268  FlowFree(f);
1269 
1270  FlowShutdown();
1271  HostShutdown();
1272  TagDestroyCtx();
1273  StorageCleanup();
1274  StatsThreadCleanup(&th_v.stats);
1275  PASS;
1276 }
1277 
1278 /**
1279  * \test session tagging: bytes, where a 2nd match makes us tag more
1280  */
1281 static int DetectTagTestPacket07 (void)
1282 {
1283  uint8_t *buf = (uint8_t *)"Hi all!";
1284  uint8_t *buf2 = (uint8_t *)"lalala!";
1285  uint16_t buf_len = strlen((char *)buf);
1286  uint16_t buf_len2 = strlen((char *)buf2);
1287 
1288  TcpSession ssn;
1289  memset(&ssn, 0, sizeof(ssn));
1290 
1291  StorageCleanup();
1292  StorageInit();
1293  TagInitCtx();
1294  StorageFinalize();
1295  HostInitConfig(1);
1296  FlowInitConfig(1);
1297 
1298  Flow *f = FlowAlloc();
1299  FAIL_IF_NULL(f);
1300  FLOW_INITIALIZE(f);
1301  f->protoctx = (void *)&ssn;
1302  f->flags |= FLOW_IPV4;
1303  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
1304  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
1305 
1307  ThreadVars th_v;
1308  DetectEngineThreadCtx *det_ctx = NULL;
1309  memset(&dtv, 0, sizeof(DecodeThreadVars));
1310  memset(&th_v, 0, sizeof(th_v));
1311  StatsThreadInit(&th_v.stats);
1312 
1315  de_ctx->flags |= DE_QUIET;
1316 
1317  Packet *p[7];
1318  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1319  "192.168.1.5", "192.168.1.1",
1320  41424, 80);
1321  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1322  "192.168.1.5", "192.168.1.1",
1323  41424, 80);
1324  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1325  "192.168.1.5", "192.168.1.1",
1326  41424, 80);
1327  p[3] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1328  "192.168.1.5", "192.168.1.1",
1329  41424, 80);
1330  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1331  "192.168.1.1", "192.168.1.5",
1332  80, 41424);
1333  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1334  "192.168.1.1", "192.168.1.5",
1335  80, 41424);
1336  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1337  "192.168.1.5", "192.168.1.1",
1338  80, 41424);
1339 
1340  const char *sigs[5];
1341  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,150,bytes; sid:1;)";
1342  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
1343  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
1344  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
1345  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
1346 
1347  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
1348  uint32_t sid[5] = {1,2,3,4,5};
1349  int numsigs = 5;
1350 
1351  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
1352  int32_t results[7][5] = {
1353  {1, 0, 0, 0, 0},
1354  {0, 0, 0, 0, 0},
1355  {0, 0, 0, 0, 0},
1356  {1, 0, 0, 0, 0},
1357  {0, 0, 0, 0, 0},
1358  {0, 0, 0, 0, 0},
1359  {0, 0, 0, 0, 0}
1360  };
1361 
1362  int num_packets = 7;
1364  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1365 
1366  int i = 0;
1367  for (; i < num_packets; i++) {
1368  p[i]->flow = f;
1369  p[i]->flow->protoctx = &ssn;
1370  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1371 
1372  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
1373 
1374  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1375 
1376  /* see if the PKT_HAS_TAG is set on the packet if needed */
1377  bool expect = (i == 1 || i == 2 || i == 3 || i == 4 || i == 5);
1378  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1379  }
1380 
1381  UTHFreePackets(p, 7);
1382  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1384 
1385  /* clean up flow */
1386  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1387  FlowClearMemory(f, proto_map);
1388  FLOW_DESTROY(f);
1389  FlowFree(f);
1390 
1391  FlowShutdown();
1392  HostShutdown();
1393  TagDestroyCtx();
1394  StorageCleanup();
1395  StatsThreadCleanup(&th_v.stats);
1396  PASS;
1397 }
1398 
1399 #endif /* UNITTESTS */
1400 
1401 /**
1402  * \brief this function registers unit tests for DetectTag
1403  */
1405 {
1406 #ifdef UNITTESTS
1407  UtRegisterTest("DetectTagTestPacket01", DetectTagTestPacket01);
1408  UtRegisterTest("DetectTagTestPacket02", DetectTagTestPacket02);
1409  UtRegisterTest("DetectTagTestPacket03", DetectTagTestPacket03);
1410  UtRegisterTest("DetectTagTestPacket04", DetectTagTestPacket04);
1411  UtRegisterTest("DetectTagTestPacket05", DetectTagTestPacket05);
1412  UtRegisterTest("DetectTagTestPacket06", DetectTagTestPacket06);
1413  UtRegisterTest("DetectTagTestPacket07", DetectTagTestPacket07);
1414 #endif /* UNITTESTS */
1415 }
1416 
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:282
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
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
DETECT_TAG_METRIC_BYTES
@ DETECT_TAG_METRIC_BYTES
Definition: detect-tag.h:57
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:2418
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: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
DETECT_TAG_METRIC_SECONDS
@ DETECT_TAG_METRIC_SECONDS
Definition: detect-tag.h:56
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:19
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:284
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:286
TimeSetIncrementTime
void TimeSetIncrementTime(uint32_t tv_sec)
increment the time in the engine
Definition: util-time.c:180
DETECT_TAG_METRIC_PACKET
@ DETECT_TAG_METRIC_PACKET
Definition: detect-tag.h:55
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:34
StatsThreadInit
void StatsThreadInit(StatsThreadContext *stats)
Definition: counters.c:1258
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:3601
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:517
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:1404
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
ThreadVars_::stats
StatsThreadContext stats
Definition: threadvars.h:121
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:288
StatsThreadCleanup
void StatsThreadCleanup(StatsThreadContext *stats)
Definition: counters.c:1354
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