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