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