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  DetectEngineThreadCtx *det_ctx, Packet *p)
525 {
526  SCEnter();
527 
528  /* If there's no tag, get out of here */
529  unsigned int current_tags = SC_ATOMIC_GET(num_tags);
530  if (current_tags == 0)
531  SCReturn;
532 
533  /* First update and get session tags */
534  if (p->flow != NULL) {
535  TagHandlePacketFlow(p->flow, p);
536  }
537 
538  Host *src = GetLockedSrcHost(p);
539  if (src != NULL) {
540  if (TagHostHasTag(src)) {
541  TagHandlePacketHost(src, p);
542  }
543  HostUnlock(src);
544  }
545 
546  Host *dst = GetLockedDstHost(p);
547  if (dst != NULL) {
548  if (TagHostHasTag(dst)) {
549  TagHandlePacketHost(dst, p);
550  }
551  HostUnlock(dst);
552  }
553 
554  SCReturn;
555 }
556 
557 /**
558  * \brief Removes the entries exceeding the max timeout value
559  *
560  * \param tag_ctx Tag context
561  * \param ts the current time
562  *
563  * \retval 1 no tags or tags removed -- host is free to go (from tag perspective)
564  * \retval 0 still active tags
565  */
567 {
568  DetectTagDataEntry *tde = NULL;
569  DetectTagDataEntry *tmp = NULL;
570  DetectTagDataEntry *prev = NULL;
571  int retval = 1;
572 
573  tmp = HostGetStorageById(host, host_tag_id);
574  if (tmp == NULL)
575  return 1;
576 
577  prev = NULL;
578  while (tmp != NULL) {
580  if (SCTIME_CMP_GTE(timeout_at, ts)) {
581  prev = tmp;
582  tmp = tmp->next;
583  retval = 0;
584  continue;
585  }
586 
587  /* timed out */
588 
589  if (prev != NULL) {
590  prev->next = tmp->next;
591 
592  tde = tmp;
593  tmp = tde->next;
594 
595  SCFree(tde);
596  (void) SC_ATOMIC_SUB(num_tags, 1);
597  } else {
598  HostSetStorageById(host, host_tag_id, tmp->next);
599 
600  tde = tmp;
601  tmp = tde->next;
602 
603  SCFree(tde);
604  (void) SC_ATOMIC_SUB(num_tags, 1);
605  }
606  }
607  return retval;
608 }
609 
610 #ifdef UNITTESTS
611 
612 /**
613  * \test host tagging: packets
614  */
615 static int DetectTagTestPacket01 (void)
616 {
617  uint8_t *buf = (uint8_t *)"Hi all!";
618  uint8_t *buf2 = (uint8_t *)"lalala!";
619  uint16_t buf_len = strlen((char *)buf);
620  uint16_t buf_len2 = strlen((char *)buf2);
621 
622  Packet *p[7];
623  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
624  "192.168.1.5", "192.168.1.1",
625  41424, 80);
626  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
627  "192.168.1.5", "192.168.1.1",
628  41424, 80);
629  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
630  "192.168.1.5", "192.168.1.9",
631  41424, 80);
632  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
633  "192.168.1.5", "192.168.1.9",
634  41424, 80);
635  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
636  "192.168.1.1", "192.168.1.9",
637  41424, 80);
638  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
639  "192.168.1.1", "192.168.1.11",
640  41424, 80);
641  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
642  "192.168.1.5", "192.168.1.11",
643  41424, 80);
644 
645  const char *sigs[5];
646  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host,3,packets,src; sid:1;)";
647  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host,4,packets,dst; sid:2;)";
648  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
649  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
650  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
651 
652  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
653  uint32_t sid[5] = {1,2,3,4,5};
654 
655  int32_t results[7][5] = {
656  {1, 1, 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  {0, 0, 0, 0, 0}
663  };
664  StorageInit();
665  TagInitCtx();
666  StorageFinalize();
667  HostInitConfig(1);
668 
669  SCLogDebug("running tests");
670  FAIL_IF_NOT(UTHGenericTest(p, 7, sigs, sid, (uint32_t *)results, 5));
671  SCLogDebug("running tests done");
672 
673  Host *src = HostLookupHostFromHash(&p[1]->src);
674  FAIL_IF_NULL(src);
675  FAIL_IF_NOT_NULL(HostGetStorageById(src, host_tag_id));
676 
677  Host *dst = HostLookupHostFromHash(&p[1]->dst);
678  FAIL_IF_NULL(dst);
679 
680  void *tag = HostGetStorageById(dst, host_tag_id);
681  FAIL_IF_NULL(tag);
682 
683  DetectTagDataEntry *iter = tag;
684 
685  /* check internal state */
686  FAIL_IF_NOT(iter->gid == 1);
687  FAIL_IF_NOT(iter->sid == 2);
688  FAIL_IF_NOT(iter->packets == 4);
689  FAIL_IF_NOT(iter->count == 4);
690 
691  HostRelease(src);
692  HostRelease(dst);
693 
694  UTHFreePackets(p, 7);
695 
696  HostShutdown();
697  TagDestroyCtx();
698  StorageCleanup();
699  PASS;
700 }
701 
702 /**
703  * \test host tagging: seconds
704  */
705 static int DetectTagTestPacket02 (void)
706 {
707  uint8_t *buf = (uint8_t *)"Hi all!";
708  uint8_t *buf2 = (uint8_t *)"lalala!";
709  uint16_t buf_len = strlen((char *)buf);
710  uint16_t buf_len2 = strlen((char *)buf2);
711 
713  ThreadVars th_v;
714  DetectEngineThreadCtx *det_ctx = NULL;
715  memset(&dtv, 0, sizeof(DecodeThreadVars));
716  memset(&th_v, 0, sizeof(th_v));
717 
718  StorageInit();
719  TagInitCtx();
720  StorageFinalize();
721  HostInitConfig(1);
722 
725  de_ctx->flags |= DE_QUIET;
726 
727  Packet *p[7];
728  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
729  "192.168.1.5", "192.168.1.1",
730  41424, 80);
731  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
732  "192.168.1.5", "192.168.1.1",
733  41424, 80);
734  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
735  "192.168.1.5", "192.168.1.9",
736  41424, 80);
737  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
738  "192.168.1.5", "192.168.1.9",
739  41424, 80);
740  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
741  "192.168.1.1", "192.168.1.9",
742  41424, 80);
743  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
744  "192.168.1.1", "192.168.1.11",
745  41424, 80);
746  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
747  "192.168.1.5", "192.168.1.11",
748  41424, 80);
749 
750  const char *sigs[5];
751  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host,3,seconds,src; sid:1;)";
752  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host,8,seconds,dst; sid:2;)";
753  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
754  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
755  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
756 
757  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
758  uint32_t sid[5] = {1,2,3,4,5};
759  int numsigs = 5;
760 
761  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
762 
763  //de_ctx->flags |= DE_QUIET;
764 
765  int32_t results[7][5] = {
766  {1, 1, 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  {0, 0, 0, 0, 0}
773  };
774 
775  int num_packets = 7;
777  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
778 
779  int i = 0;
780  for (; i < num_packets; i++) {
781  SCLogDebug("packet %d", i);
782  p[i]->ts = TimeGet();
783  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
784  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
785 
787  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
788 
789  /* see if the PKT_HAS_TAG is set on the packet if needed */
790  bool expect = (i == 1 || i == 4);
791  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
792  }
793 
794  UTHFreePackets(p, 7);
795  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
797 
798  HostShutdown();
799  TagDestroyCtx();
800  StorageCleanup();
801  PASS;
802 }
803 
804 /**
805  * \test host tagging: bytes
806  */
807 static int DetectTagTestPacket03 (void)
808 {
809  uint8_t *buf = (uint8_t *)"Hi all!";
810  uint8_t *buf2 = (uint8_t *)"lalala!";
811  uint16_t buf_len = strlen((char *)buf);
812  uint16_t buf_len2 = strlen((char *)buf2);
813 
815  ThreadVars th_v;
816  DetectEngineThreadCtx *det_ctx = NULL;
817  memset(&dtv, 0, sizeof(DecodeThreadVars));
818  memset(&th_v, 0, sizeof(th_v));
819 
820  StorageInit();
821  TagInitCtx();
822  StorageFinalize();
823  HostInitConfig(1);
824 
827 
828  de_ctx->flags |= DE_QUIET;
829 
830  Packet *p[7];
831  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
832  "192.168.1.5", "192.168.1.1",
833  41424, 80);
834  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
835  "192.168.1.5", "192.168.1.1",
836  41424, 80);
837  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
838  "192.168.1.5", "192.168.1.9",
839  41424, 80);
840  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
841  "192.168.1.5", "192.168.1.9",
842  41424, 80);
843  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
844  "192.168.1.1", "192.168.1.9",
845  41424, 80);
846  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
847  "192.168.1.1", "192.168.1.11",
848  41424, 80);
849  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
850  "192.168.1.5", "192.168.1.11",
851  41424, 80);
852 
853  const char *sigs[5];
854  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host, 150, bytes, src; sid:1;)";
855  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host, 150, bytes, dst; sid:2;)";
856  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
857  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
858  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
859 
860  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
861  uint32_t sid[5] = {1,2,3,4,5};
862  int numsigs = 5;
863 
864  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
865 
866  int32_t results[7][5] = {
867  {1, 1, 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  {0, 0, 0, 0, 0}
874  };
875 
876  int num_packets = 7;
878  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
879 
880  int i = 0;
881  for (; i < num_packets; i++) {
882  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
883 
884  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
885 
886  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
887 
888  /* see if the PKT_HAS_TAG is set on the packet if needed */
889  bool expect = (i == 1 || i == 2 || i == 4);
890  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
891  }
892 
893  UTHFreePackets(p, 7);
894  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
896 
897  HostShutdown();
898  TagDestroyCtx();
899  StorageCleanup();
900  PASS;
901 }
902 
903 /**
904  * \test session tagging: packets
905  */
906 static int DetectTagTestPacket04 (void)
907 {
908  uint8_t *buf = (uint8_t *)"Hi all!";
909  uint8_t *buf2 = (uint8_t *)"lalala!";
910  uint16_t buf_len = strlen((char *)buf);
911  uint16_t buf_len2 = strlen((char *)buf2);
912 
913  Flow *f = NULL;
914  TcpSession ssn;
915 
916  memset(&f, 0, sizeof(f));
917  memset(&ssn, 0, sizeof(ssn));
918 
919  StorageInit();
920  TagInitCtx();
921  StorageFinalize();
922  HostInitConfig(1);
923  FlowInitConfig(1);
924 
925  f = FlowAlloc();
926  FAIL_IF_NULL(f);
927  FLOW_INITIALIZE(f);
928  f->protoctx = (void *)&ssn;
929  f->flags |= FLOW_IPV4;
930  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
931  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
932 
934  ThreadVars th_v;
935  DetectEngineThreadCtx *det_ctx = NULL;
936  memset(&dtv, 0, sizeof(DecodeThreadVars));
937  memset(&th_v, 0, sizeof(th_v));
938 
941  de_ctx->flags |= DE_QUIET;
942 
943  Packet *p[7];
944  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
945  "192.168.1.5", "192.168.1.1",
946  41424, 80);
947  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
948  "192.168.1.5", "192.168.1.1",
949  41424, 80);
950  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
951  "192.168.1.5", "192.168.1.1",
952  41424, 80);
953  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
954  "192.168.1.5", "192.168.1.1",
955  41424, 80);
956  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
957  "192.168.1.1", "192.168.1.5",
958  80, 41424);
959  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
960  "192.168.1.1", "192.168.1.5",
961  80, 41424);
962  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
963  "192.168.1.5", "192.168.1.1",
964  80, 41424);
965 
966  const char *sigs[5];
967  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,4,packets; sid:1;)";
968  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
969  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
970  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
971  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
972 
973  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
974  uint32_t sid[5] = {1,2,3,4,5};
975  int numsigs = 5;
976 
977  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
978 
979  int32_t results[7][5] = {
980  {1, 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  {0, 0, 0, 0, 0}
987  };
988 
989  int num_packets = 7;
991  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
992 
993  int i = 0;
994  for (; i < num_packets; i++) {
995  p[i]->flow = f;
996  p[i]->flow->protoctx = &ssn;
997  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
998 
999  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
1000 
1001  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1002  /* see if the PKT_HAS_TAG is set on the packet if needed */
1003  bool expect = (i == 1 || i == 2 || i == 3);
1004  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1005  }
1006 
1007  UTHFreePackets(p, 7);
1008  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1010 
1011  /* clean up flow */
1012  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1013  FlowClearMemory(f, proto_map);
1014  FLOW_DESTROY(f);
1015  FlowFree(f);
1016 
1017  FlowShutdown();
1018  HostShutdown();
1019  TagDestroyCtx();
1020  StorageCleanup();
1021  PASS;
1022 }
1023 
1024 /**
1025  * \test session tagging: seconds
1026  */
1027 static int DetectTagTestPacket05 (void)
1028 {
1029  uint8_t *buf = (uint8_t *)"Hi all!";
1030  uint8_t *buf2 = (uint8_t *)"lalala!";
1031  uint16_t buf_len = strlen((char *)buf);
1032  uint16_t buf_len2 = strlen((char *)buf2);
1033 
1034  Flow *f = NULL;
1035  TcpSession ssn;
1036 
1037  memset(&f, 0, sizeof(f));
1038  memset(&ssn, 0, sizeof(ssn));
1039 
1040  StorageInit();
1041  TagInitCtx();
1042  StorageFinalize();
1043  HostInitConfig(1);
1044  FlowInitConfig(1);
1045 
1046  f = FlowAlloc();
1047  FAIL_IF_NULL(f);
1048  FLOW_INITIALIZE(f);
1049  f->protoctx = (void *)&ssn;
1050  f->flags |= FLOW_IPV4;
1051  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
1052  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
1053 
1055  ThreadVars th_v;
1056  DetectEngineThreadCtx *det_ctx = NULL;
1057  memset(&dtv, 0, sizeof(DecodeThreadVars));
1058  memset(&th_v, 0, sizeof(th_v));
1059 
1062  de_ctx->flags |= DE_QUIET;
1063 
1064  Packet *p[7];
1065  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1066  "192.168.1.5", "192.168.1.1",
1067  41424, 80);
1068  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1069  "192.168.1.5", "192.168.1.1",
1070  41424, 80);
1071  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1072  "192.168.1.5", "192.168.1.1",
1073  41424, 80);
1074  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1075  "192.168.1.5", "192.168.1.1",
1076  41424, 80);
1077  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1078  "192.168.1.1", "192.168.1.5",
1079  80, 41424);
1080  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1081  "192.168.1.1", "192.168.1.5",
1082  80, 41424);
1083  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1084  "192.168.1.5", "192.168.1.1",
1085  80, 41424);
1086 
1087  const char *sigs[5];
1088  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,8,seconds; sid:1;)";
1089  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
1090  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
1091  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
1092  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
1093 
1094  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
1095  uint32_t sid[5] = {1,2,3,4,5};
1096  int numsigs = 5;
1097 
1098  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
1099 
1100  int32_t results[7][5] = {
1101  {1, 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  {0, 0, 0, 0, 0}
1108  };
1109 
1110  int num_packets = 7;
1112  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1113 
1114  int i = 0;
1115  for (; i < num_packets; i++) {
1116  p[i]->flow = f;
1117  p[i]->flow->protoctx = &ssn;
1118 
1119  SCLogDebug("packet %d", i);
1120  p[i]->ts = TimeGet();
1121  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1122 
1123  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
1124 
1126 
1127  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1128  /* see if the PKT_HAS_TAG is set on the packet if needed */
1129  bool expect = (i == 1 || i == 2 || i == 3 || i == 4);
1130  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1131  }
1132 
1133  UTHFreePackets(p, 7);
1134  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1136 
1137  /* clean up flow */
1138  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1139  FlowClearMemory(f, proto_map);
1140  FLOW_DESTROY(f);
1141  FlowFree(f);
1142 
1143  FlowShutdown();
1144  HostShutdown();
1145  TagDestroyCtx();
1146  StorageCleanup();
1147  PASS;
1148 }
1149 
1150 /**
1151  * \test session tagging: bytes
1152  */
1153 static int DetectTagTestPacket06 (void)
1154 {
1155  uint8_t *buf = (uint8_t *)"Hi all!";
1156  uint8_t *buf2 = (uint8_t *)"lalala!";
1157  uint16_t buf_len = strlen((char *)buf);
1158  uint16_t buf_len2 = strlen((char *)buf2);
1159 
1160  Flow *f = NULL;
1161  TcpSession ssn;
1162 
1163  memset(&f, 0, sizeof(f));
1164  memset(&ssn, 0, sizeof(ssn));
1165 
1166  StorageInit();
1167  TagInitCtx();
1168  StorageFinalize();
1169  HostInitConfig(1);
1170  FlowInitConfig(1);
1171 
1172  f = FlowAlloc();
1173  FAIL_IF_NULL(f);
1174  FLOW_INITIALIZE(f);
1175  f->protoctx = (void *)&ssn;
1176  f->flags |= FLOW_IPV4;
1177  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
1178  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
1179 
1181  ThreadVars th_v;
1182  DetectEngineThreadCtx *det_ctx = NULL;
1183  memset(&dtv, 0, sizeof(DecodeThreadVars));
1184  memset(&th_v, 0, sizeof(th_v));
1185 
1188  de_ctx->flags |= DE_QUIET;
1189 
1190  Packet *p[7];
1191  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1192  "192.168.1.5", "192.168.1.1",
1193  41424, 80);
1194  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1195  "192.168.1.5", "192.168.1.1",
1196  41424, 80);
1197  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1198  "192.168.1.5", "192.168.1.1",
1199  41424, 80);
1200  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1201  "192.168.1.5", "192.168.1.1",
1202  41424, 80);
1203  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1204  "192.168.1.1", "192.168.1.5",
1205  80, 41424);
1206  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1207  "192.168.1.1", "192.168.1.5",
1208  80, 41424);
1209  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1210  "192.168.1.5", "192.168.1.1",
1211  80, 41424);
1212 
1213  const char *sigs[5];
1214  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,150,bytes; sid:1;)";
1215  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
1216  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
1217  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
1218  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
1219 
1220  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
1221  uint32_t sid[5] = {1,2,3,4,5};
1222  int numsigs = 5;
1223 
1224  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
1225 
1226  int32_t results[7][5] = {
1227  {1, 0, 0, 0, 0},
1228  {0, 0, 0, 0, 0},
1229  {0, 0, 0, 0, 0},
1230  {0, 0, 0, 0, 0},
1231  {0, 0, 0, 0, 0},
1232  {0, 0, 0, 0, 0},
1233  {0, 0, 0, 0, 0}
1234  };
1235 
1236  int num_packets = 7;
1238  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1239 
1240  int i = 0;
1241  for (; i < num_packets; i++) {
1242  p[i]->flow = f;
1243  p[i]->flow->protoctx = &ssn;
1244  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1245 
1246  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
1247 
1248  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1249 
1250  /* see if the PKT_HAS_TAG is set on the packet if needed */
1251  bool expect = (i == 1 || i == 2);
1252  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1253  }
1254 
1255  UTHFreePackets(p, 7);
1256  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1258 
1259  /* clean up flow */
1260  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1261  FlowClearMemory(f, proto_map);
1262  FLOW_DESTROY(f);
1263  FlowFree(f);
1264 
1265  FlowShutdown();
1266  HostShutdown();
1267  TagDestroyCtx();
1268  StorageCleanup();
1269  PASS;
1270 }
1271 
1272 /**
1273  * \test session tagging: bytes, where a 2nd match makes us tag more
1274  */
1275 static int DetectTagTestPacket07 (void)
1276 {
1277  uint8_t *buf = (uint8_t *)"Hi all!";
1278  uint8_t *buf2 = (uint8_t *)"lalala!";
1279  uint16_t buf_len = strlen((char *)buf);
1280  uint16_t buf_len2 = strlen((char *)buf2);
1281 
1282  Flow *f = NULL;
1283  TcpSession ssn;
1284 
1285  memset(&f, 0, sizeof(f));
1286  memset(&ssn, 0, sizeof(ssn));
1287 
1288  StorageInit();
1289  TagInitCtx();
1290  StorageFinalize();
1291  HostInitConfig(1);
1292  FlowInitConfig(1);
1293 
1294  f = FlowAlloc();
1295  FAIL_IF_NULL(f);
1296  FLOW_INITIALIZE(f);
1297  f->protoctx = (void *)&ssn;
1298  f->flags |= FLOW_IPV4;
1299  FAIL_IF(inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1);
1300  FAIL_IF(inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1);
1301 
1303  ThreadVars th_v;
1304  DetectEngineThreadCtx *det_ctx = NULL;
1305  memset(&dtv, 0, sizeof(DecodeThreadVars));
1306  memset(&th_v, 0, sizeof(th_v));
1307 
1310  de_ctx->flags |= DE_QUIET;
1311 
1312  Packet *p[7];
1313  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1314  "192.168.1.5", "192.168.1.1",
1315  41424, 80);
1316  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1317  "192.168.1.5", "192.168.1.1",
1318  41424, 80);
1319  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1320  "192.168.1.5", "192.168.1.1",
1321  41424, 80);
1322  p[3] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1323  "192.168.1.5", "192.168.1.1",
1324  41424, 80);
1325  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1326  "192.168.1.1", "192.168.1.5",
1327  80, 41424);
1328  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1329  "192.168.1.1", "192.168.1.5",
1330  80, 41424);
1331  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1332  "192.168.1.5", "192.168.1.1",
1333  80, 41424);
1334 
1335  const char *sigs[5];
1336  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,150,bytes; sid:1;)";
1337  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
1338  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
1339  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
1340  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
1341 
1342  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
1343  uint32_t sid[5] = {1,2,3,4,5};
1344  int numsigs = 5;
1345 
1346  FAIL_IF(UTHAppendSigs(de_ctx, sigs, numsigs) == 0);
1347  int32_t results[7][5] = {
1348  {1, 0, 0, 0, 0},
1349  {0, 0, 0, 0, 0},
1350  {0, 0, 0, 0, 0},
1351  {1, 0, 0, 0, 0},
1352  {0, 0, 0, 0, 0},
1353  {0, 0, 0, 0, 0},
1354  {0, 0, 0, 0, 0}
1355  };
1356 
1357  int num_packets = 7;
1359  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1360 
1361  int i = 0;
1362  for (; i < num_packets; i++) {
1363  p[i]->flow = f;
1364  p[i]->flow->protoctx = &ssn;
1365  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1366 
1367  FAIL_IF(UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0);
1368 
1369  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1370 
1371  /* see if the PKT_HAS_TAG is set on the packet if needed */
1372  bool expect = (i == 1 || i == 2 || i == 3 || i == 4 || i == 5);
1373  FAIL_IF(((p[i]->flags & PKT_HAS_TAG) ? true : false) != expect);
1374  }
1375 
1376  UTHFreePackets(p, 7);
1377  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1379 
1380  /* clean up flow */
1381  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1382  FlowClearMemory(f, proto_map);
1383  FLOW_DESTROY(f);
1384  FlowFree(f);
1385 
1386  FlowShutdown();
1387  HostShutdown();
1388  TagDestroyCtx();
1389  StorageCleanup();
1390  PASS;
1391 }
1392 
1393 #endif /* UNITTESTS */
1394 
1395 /**
1396  * \brief this function registers unit tests for DetectTag
1397  */
1399 {
1400 #ifdef UNITTESTS
1401  UtRegisterTest("DetectTagTestPacket01", DetectTagTestPacket01);
1402  UtRegisterTest("DetectTagTestPacket02", DetectTagTestPacket02);
1403  UtRegisterTest("DetectTagTestPacket03", DetectTagTestPacket03);
1404  UtRegisterTest("DetectTagTestPacket04", DetectTagTestPacket04);
1405  UtRegisterTest("DetectTagTestPacket05", DetectTagTestPacket05);
1406  UtRegisterTest("DetectTagTestPacket06", DetectTagTestPacket06);
1407  UtRegisterTest("DetectTagTestPacket07", DetectTagTestPacket07);
1408 #endif /* UNITTESTS */
1409 }
1410 
FlowStorageId
Definition: flow-storage.h:31
DETECT_TAG_MATCH_LIMIT
#define DETECT_TAG_MATCH_LIMIT
Definition: detect-tag.h:32
DetectTagDataEntry_::bytes
uint32_t bytes
Definition: detect-tag.h:80
host.h
HostUnlock
void HostUnlock(Host *h)
Definition: host.c:472
TagInitCtx
void TagInitCtx(void)
Definition: detect-engine-tag.c:52
ts
uint64_t ts
Definition: source-erf-file.c:55
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
host-storage.h
SC_ATOMIC_DECLARE
SC_ATOMIC_DECLARE(unsigned int, num_tags)
StorageInit
void StorageInit(void)
Definition: util-storage.c:70
util-hashlist.h
flow-util.h
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
Definition: util-atomic.h:314
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
Packet_::host_src
struct Host_ * host_src
Definition: decode.h:613
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:270
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:535
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:919
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:2624
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:2349
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:614
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:546
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:38
DetectTagDataEntry_::count
uint32_t count
Definition: detect-tag.h:75
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
TagHostHasTag
int TagHostHasTag(Host *host)
Definition: detect-engine-tag.c:79
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
TAG_ENTRY_FLAG_DIR_DST
#define TAG_ENTRY_FLAG_DIR_DST
Definition: detect-tag.h:89
DetectEngineThreadCtx_
Definition: detect.h:1211
Packet_::ts
SCTime_t ts
Definition: decode.h:546
SCEnter
#define SCEnter(...)
Definition: util-debug.h:272
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
DETECT_TAG_METRIC_PACKET
@ DETECT_TAG_METRIC_PACKET
Definition: detect-tag.h:55
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
Definition: detect-engine.c:3350
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:274
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:492
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:1096
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:1303
Flow_::src
FlowAddress src
Definition: flow.h:359
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2130
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:566
DetectTagDataEntry_::packets
uint32_t packets
Definition: detect-tag.h:79
flow-storage.h
Packet_::flow
struct Flow_ * flow
Definition: decode.h:537
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:690
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3576
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:503
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
TagHandlePacket
void TagHandlePacket(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
HostStorageId_
Definition: host-storage.h:31
DetectEngineTagRegisterTests
void DetectEngineTagRegisterTests(void)
this function registers unit tests for DetectTag
Definition: detect-engine-tag.c:1398
HostStorageId_::id
int id
Definition: host-storage.h:32
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SCTIME_CMP_GTE
#define SCTIME_CMP_GTE(a, b)
Definition: util-time.h:103
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:954
DETECT_TAG_METRIC_SECONDS
@ DETECT_TAG_METRIC_SECONDS
Definition: detect-tag.h:56
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:2585
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:497
HostInitConfig
void HostInitConfig(bool quiet)
initialize the configuration
Definition: host.c:168
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:921
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:1245
DETECT_TAG_METRIC_BYTES
@ DETECT_TAG_METRIC_BYTES
Definition: detect-tag.h:57
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:276
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:496
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