suricata
detect-engine-tag.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2013 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-tag.h"
36 #include "host.h"
37 #include "host-storage.h"
38 #include "flow-storage.h"
39 
40 #include "util-unittest.h"
41 #include "util-unittest-helper.h"
42 #include "flow-util.h"
43 #include "stream-tcp-private.h"
44 
45 SC_ATOMIC_DECLARE(unsigned int, num_tags); /**< Atomic counter, to know if we
46  have tagged hosts/sessions,
47  to avoid locking */
48 static int host_tag_id = -1; /**< Host storage id for tags */
49 static int flow_tag_id = -1; /**< Flow storage id for tags */
50 
51 void TagInitCtx(void)
52 {
53  SC_ATOMIC_INIT(num_tags);
54 
55  host_tag_id = HostStorageRegister("tag", sizeof(void *), NULL, DetectTagDataListFree);
56  if (host_tag_id == -1) {
57  FatalError(SC_ERR_FATAL, "Can't initiate host storage for tag");
58  }
59  flow_tag_id = FlowStorageRegister("tag", sizeof(void *), NULL, DetectTagDataListFree);
60  if (flow_tag_id == -1) {
61  FatalError(SC_ERR_FATAL, "Can't initiate flow storage for tag");
62  }
63 }
64 
65 /**
66  * \brief Destroy tag context hash tables
67  *
68  * \param tag_ctx Tag Context
69  *
70  */
71 void TagDestroyCtx(void)
72 {
73 #ifdef DEBUG
74  BUG_ON(SC_ATOMIC_GET(num_tags) != 0);
75 #endif
76 }
77 
78 /** \brief Reset the tagging engine context
79  */
81 {
82  TagDestroyCtx();
83  TagInitCtx();
84 }
85 
86 int TagHostHasTag(Host *host)
87 {
88  return HostGetStorageById(host, host_tag_id) ? 1 : 0;
89 }
90 
91 static DetectTagDataEntry *DetectTagDataCopy(DetectTagDataEntry *dtd)
92 {
94  if (unlikely(tde == NULL)) {
95  return NULL;
96  }
97  memset(tde, 0, sizeof(DetectTagDataEntry));
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 succesfuly
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 = p->ts.tv_sec;
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  } else {
280  /* Update metrics; remove if tag expired; and set alerts */
281  switch (iter->metric) {
283  if (iter->packets > iter->count) {
284  SCLogDebug("flow tag expired: packets %u > %u",
285  iter->packets, iter->count);
286  /* tag expired */
287  if (prev != NULL) {
288  tde = iter;
289  prev->next = iter->next;
290  iter = iter->next;
291  SCFree(tde);
292  (void) SC_ATOMIC_SUB(num_tags, 1);
293  continue;
294  } else {
295  FlowSetStorageById(p->flow, flow_tag_id, iter->next);
296  tde = iter;
297  iter = iter->next;
298  SCFree(tde);
299  (void) SC_ATOMIC_SUB(num_tags, 1);
300  continue;
301  }
302  } else if (flag_added == 0) {
303  /* It's matching the tag. Add it to be logged and
304  * update "flag_added" to add the packet once. */
305  p->flags |= PKT_HAS_TAG;
306  flag_added++;
307  }
308  break;
310  if (iter->bytes > iter->count) {
311  /* tag expired */
312  SCLogDebug("flow tag expired: bytes %u > %u",
313  iter->bytes, iter->count);
314  if (prev != NULL) {
315  tde = iter;
316  prev->next = iter->next;
317  iter = iter->next;
318  SCFree(tde);
319  (void) SC_ATOMIC_SUB(num_tags, 1);
320  continue;
321  } else {
322  FlowSetStorageById(p->flow, flow_tag_id, iter->next);
323  tde = iter;
324  iter = iter->next;
325  SCFree(tde);
326  (void) SC_ATOMIC_SUB(num_tags, 1);
327  continue;
328  }
329  } else if (flag_added == 0) {
330  /* It's matching the tag. Add it to be logged and
331  * update "flag_added" to add the packet once. */
332  p->flags |= PKT_HAS_TAG;
333  flag_added++;
334  }
335  break;
337  /* last_ts handles this metric, but also a generic time based
338  * expiration to prevent dead sessions/hosts */
339  if (iter->last_ts - iter->first_ts > iter->count) {
340  SCLogDebug("flow tag expired: %u - %u = %u > %u",
341  iter->last_ts, iter->first_ts,
342  (iter->last_ts - iter->first_ts), iter->count);
343  /* tag expired */
344  if (prev != NULL) {
345  tde = iter;
346  prev->next = iter->next;
347  iter = iter->next;
348  SCFree(tde);
349  (void) SC_ATOMIC_SUB(num_tags, 1);
350  continue;
351  } else {
352  FlowSetStorageById(p->flow, flow_tag_id, iter->next);
353  tde = iter;
354  iter = iter->next;
355  SCFree(tde);
356  (void) SC_ATOMIC_SUB(num_tags, 1);
357  continue;
358  }
359  } else if (flag_added == 0) {
360  /* It's matching the tag. Add it to be logged and
361  * update "flag_added" to add the packet once. */
362  p->flags |= PKT_HAS_TAG;
363  flag_added++;
364  }
365  break;
366  }
367 
368  }
369 
370  prev = iter;
371  iter = iter->next;
372  }
373 }
374 
375 static void TagHandlePacketHost(Host *host, Packet *p)
376 {
377  DetectTagDataEntry *tde = NULL;
378  DetectTagDataEntry *prev = NULL;
379  DetectTagDataEntry *iter;
380  uint8_t flag_added = 0;
381 
382  iter = HostGetStorageById(host, host_tag_id);
383  prev = NULL;
384  while (iter != NULL) {
385  /* update counters */
386  iter->last_ts = p->ts.tv_sec;
387  switch (iter->metric) {
389  iter->packets++;
390  break;
392  iter->bytes += GET_PKT_LEN(p);
393  break;
394  }
395 
396  /* If this packet triggered the rule with tag, we dont need
397  * to log it (the alert will log it) */
398  if (!(iter->flags & TAG_ENTRY_FLAG_SKIPPED_FIRST)) {
400  } else {
401  /* Update metrics; remove if tag expired; and set alerts */
402  switch (iter->metric) {
404  if (iter->packets > iter->count) {
405  SCLogDebug("host tag expired: packets %u > %u", iter->packets, iter->count);
406  /* tag expired */
407  if (prev != NULL) {
408  tde = iter;
409  prev->next = iter->next;
410  iter = iter->next;
411  SCFree(tde);
412  (void) SC_ATOMIC_SUB(num_tags, 1);
413  continue;
414  } else {
415  tde = iter;
416  iter = iter->next;
417  SCFree(tde);
418  (void) SC_ATOMIC_SUB(num_tags, 1);
419  HostSetStorageById(host, host_tag_id, iter);
420  continue;
421  }
422  } else if (flag_added == 0) {
423  /* It's matching the tag. Add it to be logged and
424  * update "flag_added" to add the packet once. */
425  p->flags |= PKT_HAS_TAG;
426  flag_added++;
427  }
428  break;
430  if (iter->bytes > iter->count) {
431  SCLogDebug("host tag expired: bytes %u > %u", iter->bytes, iter->count);
432  /* tag expired */
433  if (prev != NULL) {
434  tde = iter;
435  prev->next = iter->next;
436  iter = iter->next;
437  SCFree(tde);
438  (void) SC_ATOMIC_SUB(num_tags, 1);
439  continue;
440  } else {
441  tde = iter;
442  iter = iter->next;
443  SCFree(tde);
444  (void) SC_ATOMIC_SUB(num_tags, 1);
445  HostSetStorageById(host, host_tag_id, iter);
446  continue;
447  }
448  } else if (flag_added == 0) {
449  /* It's matching the tag. Add it to be logged and
450  * update "flag_added" to add the packet once. */
451  p->flags |= PKT_HAS_TAG;
452  flag_added++;
453  }
454  break;
456  /* last_ts handles this metric, but also a generic time based
457  * expiration to prevent dead sessions/hosts */
458  if (iter->last_ts - iter->first_ts > iter->count) {
459  SCLogDebug("host tag expired: %u - %u = %u > %u",
460  iter->last_ts, iter->first_ts,
461  (iter->last_ts - iter->first_ts), iter->count);
462  /* tag expired */
463  if (prev != NULL) {
464  tde = iter;
465  prev->next = iter->next;
466  iter = iter->next;
467  SCFree(tde);
468  (void) SC_ATOMIC_SUB(num_tags, 1);
469  continue;
470  } else {
471  tde = iter;
472  iter = iter->next;
473  SCFree(tde);
474  (void) SC_ATOMIC_SUB(num_tags, 1);
475  HostSetStorageById(host, host_tag_id, iter);
476  continue;
477  }
478  } else if (flag_added == 0) {
479  /* It's matching the tag. Add it to be logged and
480  * update "flag_added" to add the packet once. */
481  p->flags |= PKT_HAS_TAG;
482  flag_added++;
483  }
484  break;
485  }
486 
487  }
488 
489  prev = iter;
490  iter = iter->next;
491  }
492 }
493 
494 /**
495  * \brief Search tags for src and dst. Update entries of the tag, remove if necessary
496  *
497  * \param de_ctx Detect context
498  * \param det_ctx Detect thread context
499  * \param p packet
500  *
501  */
503  DetectEngineThreadCtx *det_ctx, Packet *p)
504 {
505  SCEnter();
506 
507  /* If there's no tag, get out of here */
508  unsigned int current_tags = SC_ATOMIC_GET(num_tags);
509  if (current_tags == 0)
510  SCReturn;
511 
512  /* First update and get session tags */
513  if (p->flow != NULL) {
514  TagHandlePacketFlow(p->flow, p);
515  }
516 
518  if (src) {
519  if (TagHostHasTag(src)) {
520  TagHandlePacketHost(src,p);
521  }
522  HostRelease(src);
523  }
525  if (dst) {
526  if (TagHostHasTag(dst)) {
527  TagHandlePacketHost(dst,p);
528  }
529  HostRelease(dst);
530  }
531  SCReturn;
532 }
533 
534 /**
535  * \brief Removes the entries exceding the max timeout value
536  *
537  * \param tag_ctx Tag context
538  * \param ts the current time
539  *
540  * \retval 1 no tags or tags removed -- host is free to go (from tag perspective)
541  * \retval 0 still active tags
542  */
543 int TagTimeoutCheck(Host *host, struct timeval *tv)
544 {
545  DetectTagDataEntry *tde = NULL;
546  DetectTagDataEntry *tmp = NULL;
547  DetectTagDataEntry *prev = NULL;
548  int retval = 1;
549 
550  tmp = HostGetStorageById(host, host_tag_id);
551  if (tmp == NULL)
552  return 1;
553 
554  prev = NULL;
555  while (tmp != NULL) {
556  if ((tv->tv_sec - tmp->last_ts) <= TAG_MAX_LAST_TIME_SEEN) {
557  prev = tmp;
558  tmp = tmp->next;
559  retval = 0;
560  continue;
561  }
562 
563  /* timed out */
564 
565  if (prev != NULL) {
566  prev->next = tmp->next;
567 
568  tde = tmp;
569  tmp = tde->next;
570 
571  SCFree(tde);
572  (void) SC_ATOMIC_SUB(num_tags, 1);
573  } else {
574  HostSetStorageById(host, host_tag_id, tmp->next);
575 
576  tde = tmp;
577  tmp = tde->next;
578 
579  SCFree(tde);
580  (void) SC_ATOMIC_SUB(num_tags, 1);
581  }
582  }
583  return retval;
584 }
585 
586 #ifdef UNITTESTS
587 
588 /**
589  * \test host tagging: packets
590  */
591 static int DetectTagTestPacket01 (void)
592 {
593  int result = 0;
594  uint8_t *buf = (uint8_t *)"Hi all!";
595  uint8_t *buf2 = (uint8_t *)"lalala!";
596  uint16_t buf_len = strlen((char *)buf);
597  uint16_t buf_len2 = strlen((char *)buf2);
598 
599  Packet *p[7];
600  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
601  "192.168.1.5", "192.168.1.1",
602  41424, 80);
603  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
604  "192.168.1.5", "192.168.1.1",
605  41424, 80);
606  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
607  "192.168.1.5", "192.168.1.9",
608  41424, 80);
609  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
610  "192.168.1.5", "192.168.1.9",
611  41424, 80);
612  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
613  "192.168.1.1", "192.168.1.9",
614  41424, 80);
615  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
616  "192.168.1.1", "192.168.1.11",
617  41424, 80);
618  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
619  "192.168.1.5", "192.168.1.11",
620  41424, 80);
621 
622  const char *sigs[5];
623  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host,3,packets,src; sid:1;)";
624  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host,4,packets,dst; sid:2;)";
625  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
626  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
627  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
628 
629  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
630  uint32_t sid[5] = {1,2,3,4,5};
631 
632  int32_t results[7][5] = {
633  {1, 1, 0, 0, 0},
634  {0, 0, 0, 0, 0},
635  {0, 0, 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  };
641  StorageInit();
642  TagInitCtx();
643  StorageFinalize();
644  HostInitConfig(1);
645 
646  SCLogDebug("running tests");
647  result = UTHGenericTest(p, 7, sigs, sid, (uint32_t *) results, 5);
648  SCLogDebug("running tests done");
649 
650  Host *src = HostLookupHostFromHash(&p[1]->src);
651  if (src) {
652  void *tag = HostGetStorageById(src, host_tag_id);
653  if (tag != NULL) {
654  printf("tag should have been expired: ");
655  result = 0;
656  }
657 
658  HostRelease(src);
659  }
660  Host *dst = HostLookupHostFromHash(&p[1]->dst);
661  if (dst) {
662  void *tag = HostGetStorageById(dst, host_tag_id);
663  BUG_ON(tag == NULL);
664 
665  DetectTagDataEntry *iter = tag;
666 
667  /* check internal state */
668  if (!(iter->gid == 1 && iter->sid == 2 && iter->packets == 4 && iter->count == 4)) {
669  printf("gid %u sid %u packets %u count %u: ", iter->gid, iter->sid, iter->packets, iter->count);
670  result = 0;
671  }
672 
673  HostRelease(dst);
674  }
675  BUG_ON(src == NULL || dst == NULL);
676 
677  UTHFreePackets(p, 7);
678 
679  HostShutdown();
680  TagDestroyCtx();
681  StorageCleanup();
682  return result;
683 }
684 
685 /**
686  * \test host tagging: seconds
687  */
688 static int DetectTagTestPacket02 (void)
689 {
690  int result = 0;
691  uint8_t *buf = (uint8_t *)"Hi all!";
692  uint8_t *buf2 = (uint8_t *)"lalala!";
693  uint16_t buf_len = strlen((char *)buf);
694  uint16_t buf_len2 = strlen((char *)buf2);
695 
697  ThreadVars th_v;
698  DetectEngineThreadCtx *det_ctx = NULL;
699  memset(&dtv, 0, sizeof(DecodeThreadVars));
700  memset(&th_v, 0, sizeof(th_v));
701 
702  StorageInit();
703  TagInitCtx();
704  StorageFinalize();
705  HostInitConfig(1);
706 
708  if (de_ctx == NULL) {
709  goto end;
710  }
711  de_ctx->flags |= DE_QUIET;
712 
713  Packet *p[7];
714  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
715  "192.168.1.5", "192.168.1.1",
716  41424, 80);
717  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
718  "192.168.1.5", "192.168.1.1",
719  41424, 80);
720  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
721  "192.168.1.5", "192.168.1.9",
722  41424, 80);
723  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
724  "192.168.1.5", "192.168.1.9",
725  41424, 80);
726  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
727  "192.168.1.1", "192.168.1.9",
728  41424, 80);
729  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
730  "192.168.1.1", "192.168.1.11",
731  41424, 80);
732  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
733  "192.168.1.5", "192.168.1.11",
734  41424, 80);
735 
736  const char *sigs[5];
737  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host,3,seconds,src; sid:1;)";
738  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host,8,seconds,dst; sid:2;)";
739  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
740  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
741  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
742 
743  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
744  uint32_t sid[5] = {1,2,3,4,5};
745  int numsigs = 5;
746 
747  if (UTHAppendSigs(de_ctx, sigs, numsigs) == 0)
748  goto cleanup;
749 
750  //de_ctx->flags |= DE_QUIET;
751 
752  int32_t results[7][5] = {
753  {1, 1, 0, 0, 0},
754  {0, 0, 0, 0, 0},
755  {0, 0, 0, 0, 0},
756  {0, 0, 0, 0, 0},
757  {0, 0, 0, 0, 0},
758  {0, 0, 0, 0, 0},
759  {0, 0, 0, 0, 0}
760  };
761 
762  int num_packets = 7;
764  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
765 
766  int i = 0;
767  for (; i < num_packets; i++) {
768  SCLogDebug("packet %d", i);
769  TimeGet(&p[i]->ts);
770  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
771  if (UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0)
772  goto cleanup;
773 
775  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
776 
777  /* see if the PKT_HAS_TAG is set on the packet if needed */
778  int expect;
779  if (i == 0 || i == 2 || i == 3 || i == 5 || i == 6)
780  expect = FALSE;
781  else
782  expect = TRUE;
783  if (((p[i]->flags & PKT_HAS_TAG) ? TRUE : FALSE) != expect)
784  goto cleanup;
785  }
786 
787  result = 1;
788 
789 cleanup:
790  UTHFreePackets(p, 7);
791  if (det_ctx != NULL)
792  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
793 
794  if (de_ctx != NULL) {
798  }
799 end:
800  HostShutdown();
801  TagDestroyCtx();
802  StorageCleanup();
803  return result;
804 }
805 
806 /**
807  * \test host tagging: bytes
808  */
809 static int DetectTagTestPacket03 (void)
810 {
811  int result = 0;
812  uint8_t *buf = (uint8_t *)"Hi all!";
813  uint8_t *buf2 = (uint8_t *)"lalala!";
814  uint16_t buf_len = strlen((char *)buf);
815  uint16_t buf_len2 = strlen((char *)buf2);
816 
818  ThreadVars th_v;
819  DetectEngineThreadCtx *det_ctx = NULL;
820  memset(&dtv, 0, sizeof(DecodeThreadVars));
821  memset(&th_v, 0, sizeof(th_v));
822 
823  StorageInit();
824  TagInitCtx();
825  StorageFinalize();
826  HostInitConfig(1);
827 
829  if (de_ctx == NULL) {
830  goto end;
831  }
832  de_ctx->flags |= DE_QUIET;
833 
834  Packet *p[7];
835  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
836  "192.168.1.5", "192.168.1.1",
837  41424, 80);
838  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
839  "192.168.1.5", "192.168.1.1",
840  41424, 80);
841  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
842  "192.168.1.5", "192.168.1.9",
843  41424, 80);
844  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
845  "192.168.1.5", "192.168.1.9",
846  41424, 80);
847  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
848  "192.168.1.1", "192.168.1.9",
849  41424, 80);
850  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
851  "192.168.1.1", "192.168.1.11",
852  41424, 80);
853  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
854  "192.168.1.5", "192.168.1.11",
855  41424, 80);
856 
857  const char *sigs[5];
858  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host, 150, bytes, src; sid:1;)";
859  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host, 150, bytes, dst; sid:2;)";
860  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
861  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
862  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
863 
864  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
865  uint32_t sid[5] = {1,2,3,4,5};
866  int numsigs = 5;
867 
868  if (UTHAppendSigs(de_ctx, sigs, numsigs) == 0)
869  goto cleanup;
870 
871  int32_t results[7][5] = {
872  {1, 1, 0, 0, 0},
873  {0, 0, 0, 0, 0},
874  {0, 0, 0, 0, 0},
875  {0, 0, 0, 0, 0},
876  {0, 0, 0, 0, 0},
877  {0, 0, 0, 0, 0},
878  {0, 0, 0, 0, 0}
879  };
880 
881  int num_packets = 7;
883  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
884 
885  int i = 0;
886  for (; i < num_packets; i++) {
887  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
888 
889  if (UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0)
890  goto cleanup;
891 
892  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
893 
894  /* see if the PKT_HAS_TAG is set on the packet if needed */
895  int expect;
896  if (i == 0 || i == 3 || i == 5 || i == 6)
897  expect = FALSE;
898  else
899  expect = TRUE;
900  if (((p[i]->flags & PKT_HAS_TAG) ? TRUE : FALSE) != expect)
901  goto cleanup;
902  }
903 
904  result = 1;
905 
906 cleanup:
907  UTHFreePackets(p, 7);
908  if (det_ctx != NULL)
909  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
910 
911  if (de_ctx != NULL) {
915  }
916 end:
917  HostShutdown();
918  TagDestroyCtx();
919  StorageCleanup();
920  return result;
921 }
922 
923 /**
924  * \test session tagging: packets
925  */
926 static int DetectTagTestPacket04 (void)
927 {
928  int result = 0;
929  uint8_t *buf = (uint8_t *)"Hi all!";
930  uint8_t *buf2 = (uint8_t *)"lalala!";
931  uint16_t buf_len = strlen((char *)buf);
932  uint16_t buf_len2 = strlen((char *)buf2);
933 
934  Flow *f = NULL;
935  TcpSession ssn;
936 
937  memset(&f, 0, sizeof(f));
938  memset(&ssn, 0, sizeof(ssn));
939 
940  StorageInit();
941  TagInitCtx();
942  StorageFinalize();
943  HostInitConfig(1);
944  FlowInitConfig(1);
945 
946  f = FlowAlloc();
947  BUG_ON(f == NULL);
948  FLOW_INITIALIZE(f);
949  f->protoctx = (void *)&ssn;
950  f->flags |= FLOW_IPV4;
951  if (inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1)
952  goto end;
953  if (inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1)
954  goto end;
955 
957  ThreadVars th_v;
958  DetectEngineThreadCtx *det_ctx = NULL;
959  memset(&dtv, 0, sizeof(DecodeThreadVars));
960  memset(&th_v, 0, sizeof(th_v));
961 
963  if (de_ctx == NULL) {
964  goto end;
965  }
966  de_ctx->flags |= DE_QUIET;
967 
968  Packet *p[7];
969  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
970  "192.168.1.5", "192.168.1.1",
971  41424, 80);
972  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
973  "192.168.1.5", "192.168.1.1",
974  41424, 80);
975  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
976  "192.168.1.5", "192.168.1.1",
977  41424, 80);
978  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
979  "192.168.1.5", "192.168.1.1",
980  41424, 80);
981  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
982  "192.168.1.1", "192.168.1.5",
983  80, 41424);
984  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
985  "192.168.1.1", "192.168.1.5",
986  80, 41424);
987  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
988  "192.168.1.5", "192.168.1.1",
989  80, 41424);
990 
991  const char *sigs[5];
992  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,4,packets; sid:1;)";
993  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
994  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
995  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
996  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
997 
998  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
999  uint32_t sid[5] = {1,2,3,4,5};
1000  int numsigs = 5;
1001 
1002  if (UTHAppendSigs(de_ctx, sigs, numsigs) == 0)
1003  goto cleanup;
1004 
1005  int32_t results[7][5] = {
1006  {1, 0, 0, 0, 0},
1007  {0, 0, 0, 0, 0},
1008  {0, 0, 0, 0, 0},
1009  {0, 0, 0, 0, 0},
1010  {0, 0, 0, 0, 0},
1011  {0, 0, 0, 0, 0},
1012  {0, 0, 0, 0, 0}
1013  };
1014 
1015  int num_packets = 7;
1017  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1018 
1019  int i = 0;
1020  for (; i < num_packets; i++) {
1021  p[i]->flow = f;
1022  p[i]->flow->protoctx = &ssn;
1023  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1024 
1025  if (UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0)
1026  goto cleanup;
1027 
1028  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1029  /* see if the PKT_HAS_TAG is set on the packet if needed */
1030  int expect;
1031  if (i == 0 || i == 4 || i == 5 || i == 6)
1032  expect = FALSE;
1033  else
1034  expect = TRUE;
1035  if (((p[i]->flags & PKT_HAS_TAG) ? TRUE : FALSE) != expect)
1036  goto cleanup;
1037  }
1038 
1039  result = 1;
1040 
1041 cleanup:
1042  UTHFreePackets(p, 7);
1043  if (det_ctx != NULL)
1044  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1045 
1046  if (de_ctx != NULL) {
1050  }
1051 
1052  /* clean up flow */
1053  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1054  FlowClearMemory(f, proto_map);
1055  FLOW_DESTROY(f);
1056 end:
1057  FlowShutdown();
1058  HostShutdown();
1059  TagDestroyCtx();
1060  StorageCleanup();
1061  return result;
1062 }
1063 
1064 /**
1065  * \test session tagging: seconds
1066  */
1067 static int DetectTagTestPacket05 (void)
1068 {
1069  int result = 0;
1070  uint8_t *buf = (uint8_t *)"Hi all!";
1071  uint8_t *buf2 = (uint8_t *)"lalala!";
1072  uint16_t buf_len = strlen((char *)buf);
1073  uint16_t buf_len2 = strlen((char *)buf2);
1074 
1075  Flow *f = NULL;
1076  TcpSession ssn;
1077 
1078  memset(&f, 0, sizeof(f));
1079  memset(&ssn, 0, sizeof(ssn));
1080 
1081  StorageInit();
1082  TagInitCtx();
1083  StorageFinalize();
1084  HostInitConfig(1);
1085  FlowInitConfig(1);
1086 
1087  f = FlowAlloc();
1088  BUG_ON(f == NULL);
1089  FLOW_INITIALIZE(f);
1090  f->protoctx = (void *)&ssn;
1091  f->flags |= FLOW_IPV4;
1092  if (inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1)
1093  goto end;
1094  if (inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1)
1095  goto end;
1096 
1098  ThreadVars th_v;
1099  DetectEngineThreadCtx *det_ctx = NULL;
1100  memset(&dtv, 0, sizeof(DecodeThreadVars));
1101  memset(&th_v, 0, sizeof(th_v));
1102 
1104  if (de_ctx == NULL) {
1105  goto end;
1106  }
1107  de_ctx->flags |= DE_QUIET;
1108 
1109  Packet *p[7];
1110  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1111  "192.168.1.5", "192.168.1.1",
1112  41424, 80);
1113  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1114  "192.168.1.5", "192.168.1.1",
1115  41424, 80);
1116  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1117  "192.168.1.5", "192.168.1.1",
1118  41424, 80);
1119  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1120  "192.168.1.5", "192.168.1.1",
1121  41424, 80);
1122  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1123  "192.168.1.1", "192.168.1.5",
1124  80, 41424);
1125  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1126  "192.168.1.1", "192.168.1.5",
1127  80, 41424);
1128  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1129  "192.168.1.5", "192.168.1.1",
1130  80, 41424);
1131 
1132  const char *sigs[5];
1133  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,8,seconds; sid:1;)";
1134  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
1135  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
1136  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
1137  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
1138 
1139  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
1140  uint32_t sid[5] = {1,2,3,4,5};
1141  int numsigs = 5;
1142 
1143  if (UTHAppendSigs(de_ctx, sigs, numsigs) == 0)
1144  goto cleanup;
1145 
1146  int32_t results[7][5] = {
1147  {1, 0, 0, 0, 0},
1148  {0, 0, 0, 0, 0},
1149  {0, 0, 0, 0, 0},
1150  {0, 0, 0, 0, 0},
1151  {0, 0, 0, 0, 0},
1152  {0, 0, 0, 0, 0},
1153  {0, 0, 0, 0, 0}
1154  };
1155 
1156  int num_packets = 7;
1158  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1159 
1160  int i = 0;
1161  for (; i < num_packets; i++) {
1162  p[i]->flow = f;
1163  p[i]->flow->protoctx = &ssn;
1164 
1165  SCLogDebug("packet %d", i);
1166  TimeGet(&p[i]->ts);
1167  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1168 
1169  if (UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0)
1170  goto cleanup;
1171 
1173 
1174  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1175  /* see if the PKT_HAS_TAG is set on the packet if needed */
1176  int expect;
1177  if (i == 0 || i == 5 || i == 6)
1178  expect = FALSE;
1179  else
1180  expect = TRUE;
1181  if (((p[i]->flags & PKT_HAS_TAG) ? TRUE : FALSE) != expect)
1182  goto cleanup;
1183  }
1184 
1185  result = 1;
1186 
1187 cleanup:
1188  UTHFreePackets(p, 7);
1189  if (det_ctx != NULL)
1190  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1191 
1192  if (de_ctx != NULL) {
1196  }
1197 
1198  /* clean up flow */
1199  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1200  FlowClearMemory(f, proto_map);
1201  FLOW_DESTROY(f);
1202 end:
1203  FlowShutdown();
1204  HostShutdown();
1205  TagDestroyCtx();
1206  StorageCleanup();
1207  return result;
1208 }
1209 
1210 /**
1211  * \test session tagging: bytes
1212  */
1213 static int DetectTagTestPacket06 (void)
1214 {
1215  int result = 0;
1216  uint8_t *buf = (uint8_t *)"Hi all!";
1217  uint8_t *buf2 = (uint8_t *)"lalala!";
1218  uint16_t buf_len = strlen((char *)buf);
1219  uint16_t buf_len2 = strlen((char *)buf2);
1220 
1221  Flow *f = NULL;
1222  TcpSession ssn;
1223 
1224  memset(&f, 0, sizeof(f));
1225  memset(&ssn, 0, sizeof(ssn));
1226 
1227  StorageInit();
1228  TagInitCtx();
1229  StorageFinalize();
1230  HostInitConfig(1);
1231  FlowInitConfig(1);
1232 
1233  f = FlowAlloc();
1234  BUG_ON(f == NULL);
1235  FLOW_INITIALIZE(f);
1236  f->protoctx = (void *)&ssn;
1237  f->flags |= FLOW_IPV4;
1238  if (inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1)
1239  goto end;
1240  if (inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1)
1241  goto end;
1242 
1244  ThreadVars th_v;
1245  DetectEngineThreadCtx *det_ctx = NULL;
1246  memset(&dtv, 0, sizeof(DecodeThreadVars));
1247  memset(&th_v, 0, sizeof(th_v));
1248 
1250  if (de_ctx == NULL) {
1251  goto end;
1252  }
1253  de_ctx->flags |= DE_QUIET;
1254 
1255  Packet *p[7];
1256  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1257  "192.168.1.5", "192.168.1.1",
1258  41424, 80);
1259  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1260  "192.168.1.5", "192.168.1.1",
1261  41424, 80);
1262  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1263  "192.168.1.5", "192.168.1.1",
1264  41424, 80);
1265  p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1266  "192.168.1.5", "192.168.1.1",
1267  41424, 80);
1268  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1269  "192.168.1.1", "192.168.1.5",
1270  80, 41424);
1271  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1272  "192.168.1.1", "192.168.1.5",
1273  80, 41424);
1274  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1275  "192.168.1.5", "192.168.1.1",
1276  80, 41424);
1277 
1278  const char *sigs[5];
1279  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,150,bytes; sid:1;)";
1280  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
1281  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
1282  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
1283  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
1284 
1285  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
1286  uint32_t sid[5] = {1,2,3,4,5};
1287  int numsigs = 5;
1288 
1289  if (UTHAppendSigs(de_ctx, sigs, numsigs) == 0)
1290  goto cleanup;
1291 
1292  int32_t results[7][5] = {
1293  {1, 0, 0, 0, 0},
1294  {0, 0, 0, 0, 0},
1295  {0, 0, 0, 0, 0},
1296  {0, 0, 0, 0, 0},
1297  {0, 0, 0, 0, 0},
1298  {0, 0, 0, 0, 0},
1299  {0, 0, 0, 0, 0}
1300  };
1301 
1302  int num_packets = 7;
1304  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1305 
1306  int i = 0;
1307  for (; i < num_packets; i++) {
1308  p[i]->flow = f;
1309  p[i]->flow->protoctx = &ssn;
1310  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1311 
1312  if (UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0)
1313  goto cleanup;
1314 
1315  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1316 
1317  /* see if the PKT_HAS_TAG is set on the packet if needed */
1318  int expect;
1319  if (i == 0 || i == 3 || i == 4 || i == 5 || i == 6)
1320  expect = FALSE;
1321  else
1322  expect = TRUE;
1323  if (((p[i]->flags & PKT_HAS_TAG) ? TRUE : FALSE) != expect)
1324  goto cleanup;
1325  }
1326 
1327  result = 1;
1328 
1329 cleanup:
1330  UTHFreePackets(p, 7);
1331  if (det_ctx != NULL)
1332  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1333 
1334  if (de_ctx != NULL) {
1338  }
1339 
1340  /* clean up flow */
1341  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1342  FlowClearMemory(f, proto_map);
1343  FLOW_DESTROY(f);
1344 end:
1345  FlowShutdown();
1346  HostShutdown();
1347  TagDestroyCtx();
1348  StorageCleanup();
1349  return result;
1350 }
1351 
1352 /**
1353  * \test session tagging: bytes, where a 2nd match makes us tag more
1354  */
1355 static int DetectTagTestPacket07 (void)
1356 {
1357  int result = 0;
1358  uint8_t *buf = (uint8_t *)"Hi all!";
1359  uint8_t *buf2 = (uint8_t *)"lalala!";
1360  uint16_t buf_len = strlen((char *)buf);
1361  uint16_t buf_len2 = strlen((char *)buf2);
1362 
1363  Flow *f = NULL;
1364  TcpSession ssn;
1365 
1366  memset(&f, 0, sizeof(f));
1367  memset(&ssn, 0, sizeof(ssn));
1368 
1369  StorageInit();
1370  TagInitCtx();
1371  StorageFinalize();
1372  HostInitConfig(1);
1373  FlowInitConfig(1);
1374 
1375  f = FlowAlloc();
1376  BUG_ON(f == NULL);
1377  FLOW_INITIALIZE(f);
1378  f->protoctx = (void *)&ssn;
1379  f->flags |= FLOW_IPV4;
1380  if (inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1)
1381  goto end;
1382  if (inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1)
1383  goto end;
1384 
1386  ThreadVars th_v;
1387  DetectEngineThreadCtx *det_ctx = NULL;
1388  memset(&dtv, 0, sizeof(DecodeThreadVars));
1389  memset(&th_v, 0, sizeof(th_v));
1390 
1392  if (de_ctx == NULL) {
1393  goto end;
1394  }
1395  de_ctx->flags |= DE_QUIET;
1396 
1397  Packet *p[7];
1398  p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1399  "192.168.1.5", "192.168.1.1",
1400  41424, 80);
1401  p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1402  "192.168.1.5", "192.168.1.1",
1403  41424, 80);
1404  p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1405  "192.168.1.5", "192.168.1.1",
1406  41424, 80);
1407  p[3] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
1408  "192.168.1.5", "192.168.1.1",
1409  41424, 80);
1410  p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1411  "192.168.1.1", "192.168.1.5",
1412  80, 41424);
1413  p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1414  "192.168.1.1", "192.168.1.5",
1415  80, 41424);
1416  p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
1417  "192.168.1.5", "192.168.1.1",
1418  80, 41424);
1419 
1420  const char *sigs[5];
1421  sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,150,bytes; sid:1;)";
1422  sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
1423  sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
1424  sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
1425  sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
1426 
1427  /* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
1428  uint32_t sid[5] = {1,2,3,4,5};
1429  int numsigs = 5;
1430 
1431  if (UTHAppendSigs(de_ctx, sigs, numsigs) == 0)
1432  goto cleanup;
1433 
1434  int32_t results[7][5] = {
1435  {1, 0, 0, 0, 0},
1436  {0, 0, 0, 0, 0},
1437  {0, 0, 0, 0, 0},
1438  {1, 0, 0, 0, 0},
1439  {0, 0, 0, 0, 0},
1440  {0, 0, 0, 0, 0},
1441  {0, 0, 0, 0, 0}
1442  };
1443 
1444  int num_packets = 7;
1446  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1447 
1448  int i = 0;
1449  for (; i < num_packets; i++) {
1450  p[i]->flow = f;
1451  p[i]->flow->protoctx = &ssn;
1452  SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
1453 
1454  if (UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0)
1455  goto cleanup;
1456 
1457  SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
1458 #if 1
1459  /* see if the PKT_HAS_TAG is set on the packet if needed */
1460  int expect;
1461  if (i == 0 || i == 6)
1462  expect = FALSE;
1463  else
1464  expect = TRUE;
1465  if (((p[i]->flags & PKT_HAS_TAG) ? TRUE : FALSE) != expect)
1466  goto cleanup;
1467 #endif
1468  }
1469 
1470  result = 1;
1471 
1472 cleanup:
1473  UTHFreePackets(p, 7);
1474  if (det_ctx != NULL)
1475  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1476 
1477  if (de_ctx != NULL) {
1481  }
1482 
1483  /* clean up flow */
1484  uint8_t proto_map = FlowGetProtoMapping(f->proto);
1485  FlowClearMemory(f, proto_map);
1486  FLOW_DESTROY(f);
1487 end:
1488  FlowShutdown();
1489  HostShutdown();
1490  TagDestroyCtx();
1491  StorageCleanup();
1492  return result;
1493 }
1494 
1495 #endif /* UNITTESTS */
1496 
1497 /**
1498  * \brief this function registers unit tests for DetectTag
1499  */
1501 {
1502 #ifdef UNITTESTS
1503  UtRegisterTest("DetectTagTestPacket01", DetectTagTestPacket01);
1504  UtRegisterTest("DetectTagTestPacket02", DetectTagTestPacket02);
1505  UtRegisterTest("DetectTagTestPacket03", DetectTagTestPacket03);
1506  UtRegisterTest("DetectTagTestPacket04", DetectTagTestPacket04);
1507  UtRegisterTest("DetectTagTestPacket05", DetectTagTestPacket05);
1508  UtRegisterTest("DetectTagTestPacket06", DetectTagTestPacket06);
1509  UtRegisterTest("DetectTagTestPacket07", DetectTagTestPacket07);
1510 #endif /* UNITTESTS */
1511 }
1512 
DETECT_TAG_MATCH_LIMIT
#define DETECT_TAG_MATCH_LIMIT
Definition: detect-tag.h:34
DetectTagDataEntry_::bytes
uint32_t bytes
Definition: detect-tag.h:84
host.h
TagInitCtx
void TagInitCtx(void)
Definition: detect-engine-tag.c:51
ts
uint64_t ts
Definition: source-erf-file.c:54
detect-engine.h
host-storage.h
SC_ATOMIC_DECLARE
SC_ATOMIC_DECLARE(unsigned int, num_tags)
StorageInit
void StorageInit(void)
Definition: util-storage.c:67
util-hashlist.h
flow-util.h
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
Definition: util-atomic.h:286
DetectTagDataEntry_::last_ts
uint32_t last_ts
Definition: detect-tag.h:87
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
DETECT_TAG_METRIC_SECONDS
@ DETECT_TAG_METRIC_SECONDS
Definition: detect-tag.h:59
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
DetectTagDataEntry_
Definition: detect-tag.h:73
TagRestartCtx
void TagRestartCtx()
Reset the tagging engine context.
Definition: detect-engine-tag.c:80
Flow_::proto
uint8_t proto
Definition: flow.h:361
HostSetStorageById
int HostSetStorageById(Host *h, int id, void *ptr)
Store a pointer in a given Host storage.
Definition: host-storage.c:71
DetectTagDataEntry_::cnt_match
uint16_t cnt_match
Definition: detect-tag.h:77
Packet_::flags
uint32_t flags
Definition: decode.h:446
Flow_
Flow data structure.
Definition: flow.h:343
results
struct DetectRfbSecresult_ results[]
HostInitConfig
void HostInitConfig(char quiet)
initialize the configuration
Definition: host.c:173
HostRelease
void HostRelease(Host *h)
Definition: host.c:474
util-hash.h
DetectTagDataEntry_::sid
uint32_t sid
Definition: detect-tag.h:80
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:304
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:766
FlowInitConfig
void FlowInitConfig(char quiet)
initialize the configuration
Definition: flow.c:531
HostGetHostFromHash
Host * HostGetHostFromHash(Address *a)
Definition: host.c:499
TAG_ENTRY_FLAG_SKIPPED_FIRST
#define TAG_ENTRY_FLAG_SKIPPED_FIRST
Definition: detect-tag.h:97
DetectTagDataListFree
void DetectTagDataListFree(void *ptr)
this function will free all the entries of a list DetectTagDataEntry
Definition: detect-tag.c:323
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2092
StorageCleanup
void StorageCleanup(void)
Definition: util-storage.c:75
TAG_ENTRY_FLAG_DIR_SRC
#define TAG_ENTRY_FLAG_DIR_SRC
Definition: detect-tag.h:95
DE_QUIET
#define DE_QUIET
Definition: detect.h:293
TAG_MAX_LAST_TIME_SEEN
#define TAG_MAX_LAST_TIME_SEEN
Definition: detect-engine-tag.h:36
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:39
DetectTagDataEntry_::metric
uint8_t metric
Definition: detect-tag.h:75
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:241
Flow_::protoctx
void * protoctx
Definition: flow.h:416
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:94
util-unittest.h
DetectTagDataEntry_::flags
uint8_t flags
Definition: detect-tag.h:74
util-unittest-helper.h
DetectTagDataEntry_::gid
uint32_t gid
Definition: detect-tag.h:81
HostGetStorageById
void * HostGetStorageById(Host *h, int id)
Get a value from a given Host storage.
Definition: host-storage.c:84
Flow_::dst
FlowAddress dst
Definition: flow.h:346
DETECT_TAG_MAX_TAGS
#define DETECT_TAG_MAX_TAGS
Definition: detect-tag.h:37
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
DetectTagDataEntry_::count
uint32_t count
Definition: detect-tag.h:79
TagHostHasTag
int TagHostHasTag(Host *host)
Definition: detect-engine-tag.c:86
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:96
DetectEngineThreadCtx_
Definition: detect.h:1009
DetectTagDataEntry_::first_ts
uint32_t first_ts
Definition: detect-tag.h:86
FlowStorageRegister
int FlowStorageRegister(const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void(*Free)(void *))
Definition: flow-storage.c:65
SCEnter
#define SCEnter(...)
Definition: util-debug.h:300
DETECT_TAG_METRIC_BYTES
@ DETECT_TAG_METRIC_BYTES
Definition: detect-tag.h:60
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
UTHCheckPacketMatchResults
int UTHCheckPacketMatchResults(Packet *p, uint32_t sids[], uint32_t results[], int numsids)
UTHCheckPacketMatches: function to check if a packet match some sids.
Definition: util-unittest-helper.c:646
util-atomic.h
util-time.h
TRUE
#define TRUE
Definition: suricata-common.h:33
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:282
SigMatchSignatures
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1688
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:1943
detect-engine-tag.h
SC_ATOMIC_SUB
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:313
FALSE
#define FALSE
Definition: suricata-common.h:34
SCReturn
#define SCReturn
Definition: util-debug.h:302
TimeSetIncrementTime
void TimeSetIncrementTime(uint32_t tv_sec)
increment the time in the engine
Definition: util-time.c:182
FlowGetProtoMapping
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition: flow-util.c:95
Packet_
Definition: decode.h:411
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:227
stream-tcp-private.h
StorageFinalize
int StorageFinalize(void)
Definition: util-storage.c:139
FlowClearMemory
int FlowClearMemory(Flow *f, uint8_t proto_map)
Function clear the flow memory before queueing it to spare flow queue.
Definition: flow.c:1035
FlowSetStorageById
int FlowSetStorageById(Flow *f, int id, void *ptr)
Definition: flow-storage.c:44
HostStorageRegister
int HostStorageRegister(const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void(*Free)(void *))
Register a Host storage.
Definition: host-storage.c:59
Flow_::src
FlowAddress src
Definition: flow.h:346
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1878
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:30
DetectTagDataEntry_::packets
uint32_t packets
Definition: detect-tag.h:83
flow-storage.h
Packet_::flow
struct Flow_ * flow
Definition: decode.h:448
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:2796
TagTimeoutCheck
int TagTimeoutCheck(Host *host, struct timeval *tv)
Removes the entries exceding the max timeout value.
Definition: detect-engine-tag.c:543
flags
uint8_t flags
Definition: decode-gre.h:0
Packet_::ts
struct timeval ts
Definition: decode.h:454
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3004
FlowShutdown
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:683
HostShutdown
void HostShutdown(void)
shutdown the flow engine
Definition: host.c:305
FatalError
#define FatalError(x,...)
Definition: util-debug.h:532
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
UTHGenericTest
int UTHGenericTest(Packet **pkt, int numpkts, const char *sigs[], uint32_t sids[], uint32_t *results, int numsigs)
UTHGenericTest: function that perfom a generic check taking care of as maximum common unittest elemen...
Definition: util-unittest-helper.c:603
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:502
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
DetectEngineTagRegisterTests
void DetectEngineTagRegisterTests(void)
this function registers unit tests for DetectTag
Definition: detect-engine-tag.c:1500
DETECT_TAG_METRIC_PACKET
@ DETECT_TAG_METRIC_PACKET
Definition: detect-tag.h:58
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:625
SC_ERR_FATAL
@ SC_ERR_FATAL
Definition: util-error.h:203
Flow_::flags
uint32_t flags
Definition: flow.h:396
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
TimeGet
void TimeGet(struct timeval *tv)
Definition: util-time.c:153
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2047
FlowGetStorageById
void * FlowGetStorageById(Flow *f, int id)
Definition: flow-storage.c:39
DetectTagDataEntry_::next
struct DetectTagDataEntry_ * next
Definition: detect-tag.h:91
HostLookupHostFromHash
Host * HostLookupHostFromHash(Address *a)
look up a host in the hash
Definition: host.c:598
Packet_::dst
Address dst
Definition: decode.h:416
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:767
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:680
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:347
TcpSession_
Definition: stream-tcp-private.h:260
PKT_HAS_TAG
#define PKT_HAS_TAG
Definition: decode.h:1083
FlowAlloc
Flow * FlowAlloc(void)
allocate a flow
Definition: flow-util.c:51
Host_
Definition: host.h:58
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:121
Packet_::src
Address src
Definition: decode.h:415
TagDestroyCtx
void TagDestroyCtx(void)
Destroy tag context hash tables.
Definition: detect-engine-tag.c:71
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:467