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