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