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