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