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