1 /* Copyright (C) 2007-2020 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
20 *
21 * \author Victor Julien <victor@inliniac.net>
22 * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
23 *
24 * Signatures that only inspect IP addresses are processed here
25 * We use radix trees for src dst ipv4 and ipv6 addresses
26 * This radix trees hold information for subnets and hosts in a
27 * hierarchical distribution
28 */
29
30 #include "suricata-common.h"
31 #include "debug.h"
32 #include "detect.h"
33 #include "decode.h"
34 #include "flow.h"
35
36 #include "detect-parse.h"
37 #include "detect-engine.h"
38
39 #include "detect-engine-siggroup.h"
40 #include "detect-engine-address.h"
41 #include "detect-engine-proto.h"
42 #include "detect-engine-port.h"
43 #include "detect-engine-mpm.h"
44
45 #include "detect-engine-threshold.h"
46 #include "detect-engine-iponly.h"
47 #include "detect-threshold.h"
48 #include "util-classification-config.h"
49 #include "util-rule-vars.h"
50
51 #include "flow-util.h"
52 #include "util-debug.h"
53 #include "util-unittest.h"
54 #include "util-unittest-helper.h"
55 #include "util-print.h"
56 #include "util-byte.h"
57 #include "util-profiling.h"
58 #include "util-validate.h"
59
60 #ifdef OS_WIN32
61 #include <winsock.h>
62 #else
63 #include <netinet/in.h>
64 #endif /* OS_WIN32 */
65
66 /**
67 * \brief This function creates a new IPOnlyCIDRItem
68 *
69 * \retval IPOnlyCIDRItem address of the new instance
70 */
IPOnlyCIDRItemNew(void)71 static IPOnlyCIDRItem *IPOnlyCIDRItemNew(void)
72 {
73 SCEnter();
74 IPOnlyCIDRItem *item = NULL;
75
76 item = SCMalloc(sizeof(IPOnlyCIDRItem));
77 if (unlikely(item == NULL))
78 SCReturnPtr(NULL, "IPOnlyCIDRItem");
79 memset(item, 0, sizeof(IPOnlyCIDRItem));
80
81 SCReturnPtr(item, "IPOnlyCIDRItem");
82 }
83
IPOnlyCIDRItemCompare(IPOnlyCIDRItem * head,IPOnlyCIDRItem * item)84 static uint8_t IPOnlyCIDRItemCompare(IPOnlyCIDRItem *head,
85 IPOnlyCIDRItem *item)
86 {
87 uint8_t i = 0;
88 for (; i < head->netmask / 32 || i < 1; i++) {
89 if (item->ip[i] < head->ip[i])
90 //if (*(uint8_t *)(item->ip + i) < *(uint8_t *)(head->ip + i))
91 return 1;
92 }
93 return 0;
94 }
95
96 //declaration for using it already
97 static IPOnlyCIDRItem *IPOnlyCIDRItemInsert(IPOnlyCIDRItem *head,
98 IPOnlyCIDRItem *item);
99
100 /**
101 * \internal
102 * \brief Parses an ipv4/ipv6 address string and updates the result into the
103 * IPOnlyCIDRItem instance sent as the argument.
104 *
105 * \param pdd Double pointer to the IPOnlyCIDRItem instance which should be updated
106 * with the address (in cidr) details from the parsed ip string.
107 * \param str Pointer to address string that has to be parsed.
108 *
109 * \retval 0 On successfully parsing the address string.
110 * \retval -1 On failure.
111 */
IPOnlyCIDRItemParseSingle(IPOnlyCIDRItem ** pdd,const char * str)112 static int IPOnlyCIDRItemParseSingle(IPOnlyCIDRItem **pdd, const char *str)
113 {
114 char buf[256] = "";
115 char *ip = NULL, *ip2 = NULL;
116 char *mask = NULL;
117 int r = 0;
118 IPOnlyCIDRItem *dd = *pdd;
119
120 while (*str != '\0' && *str == ' ')
121 str++;
122
123 SCLogDebug("str %s", str);
124 strlcpy(buf, str, sizeof(buf));
125 ip = buf;
126
127 /* first handle 'any' */
128 if (strcasecmp(str, "any") == 0) {
129 /* if any, insert 0.0.0.0/0 and ::/0 as well */
130 SCLogDebug("adding 0.0.0.0/0 and ::/0 as we\'re handling \'any\'");
131
132 IPOnlyCIDRItemParseSingle(&dd, "0.0.0.0/0");
133 BUG_ON(dd->family == 0);
134
135 dd->next = IPOnlyCIDRItemNew();
136 if (dd->next == NULL)
137 goto error;
138
139 IPOnlyCIDRItemParseSingle(&dd->next, "::/0");
140 BUG_ON(dd->family == 0);
141
142 SCLogDebug("address is \'any\'");
143 return 0;
144 }
145
146 /* handle the negation case */
147 if (ip[0] == '!') {
148 dd->negated = (dd->negated)? 0 : 1;
149 ip++;
150 }
151
152 /* see if the address is an ipv4 or ipv6 address */
153 if ((strchr(str, ':')) == NULL) {
154 /* IPv4 Address */
155 struct in_addr in;
156
157 dd->family = AF_INET;
158
159 if ((mask = strchr(ip, '/')) != NULL) {
160 /* 1.2.3.4/xxx format (either dotted or cidr notation */
161 ip[mask - ip] = '\0';
162 mask++;
163 uint32_t netmask = 0;
164 size_t u = 0;
165
166 if ((strchr (mask, '.')) == NULL) {
167 /* 1.2.3.4/24 format */
168
169 for (u = 0; u < strlen(mask); u++) {
170 if(!isdigit((unsigned char)mask[u]))
171 goto error;
172 }
173
174 int cidr;
175 if (StringParseI32RangeCheck(&cidr, 10, 0, (const char *)mask, 0, 32) < 0)
176 goto error;
177
178 dd->netmask = cidr;
179 } else {
180 /* 1.2.3.4/255.255.255.0 format */
181 r = inet_pton(AF_INET, mask, &in);
182 if (r <= 0)
183 goto error;
184
185 netmask = in.s_addr;
186
187 if (netmask != 0) {
188 /* Extract cidr netmask */
189 while ((0x01 & netmask) == 0) {
190 dd->netmask++;
191 netmask = netmask >> 1;
192 }
193 dd->netmask = 32 - dd->netmask;
194 }
195 }
196
197 r = inet_pton(AF_INET, ip, &in);
198 if (r <= 0)
199 goto error;
200
201 dd->ip[0] = in.s_addr;
202
203 } else if ((ip2 = strchr(ip, '-')) != NULL) {
204 /* 1.2.3.4-1.2.3.6 range format */
205 ip[ip2 - ip] = '\0';
206 ip2++;
207
208 uint32_t first, last;
209
210 r = inet_pton(AF_INET, ip, &in);
211 if (r <= 0)
212 goto error;
213 first = SCNtohl(in.s_addr);
214
215 r = inet_pton(AF_INET, ip2, &in);
216 if (r <= 0)
217 goto error;
218 last = SCNtohl(in.s_addr);
219
220 /* a > b is illegal, a = b is ok */
221 if (first > last)
222 goto error;
223
224 SCLogDebug("Creating CIDR range for [%s - %s]", ip, ip2);
225 dd->netmask = 32;
226 /* Find the maximum netmask starting from current address first
227 * and not crossing last.
228 * To extend the mask, we need to start from a power of 2.
229 * And we need to pay attention to unsigned overflow back to 0.0.0.0
230 */
231 while (dd->netmask > 0 &&
232 (first & (1UL << (32-dd->netmask))) == 0 &&
233 first + (1UL << (32-(dd->netmask-1))) - 1 <= last) {
234 dd->netmask--;
235 }
236 dd->ip[0] = htonl(first);
237 first += 1UL << (32-dd->netmask);
238 //case whatever-255.255.255.255 looping to 0.0.0.0/0
239 while ( first <= last && first != 0 ) {
240 IPOnlyCIDRItem *new = IPOnlyCIDRItemNew();
241 if (new == NULL)
242 goto error;
243 new->negated = dd->negated;
244 new->family= dd->family;
245 new->netmask = 32;
246 while (new->netmask > 0 &&
247 (first & (1UL << (32-new->netmask))) == 0 &&
248 first + (1UL << (32-(new->netmask-1))) - 1 <= last) {
249 new->netmask--;
250 }
251 new->ip[0] = htonl(first);
252 first += 1UL << (32-new->netmask);
253 dd = IPOnlyCIDRItemInsert(dd, new);
254 }
255 //update head of list
256 *pdd = dd;
257
258 } else {
259 /* 1.2.3.4 format */
260 r = inet_pton(AF_INET, ip, &in);
261 if (r <= 0)
262 goto error;
263
264 /* single host */
265 dd->ip[0] = in.s_addr;
266 dd->netmask = 32;
267 }
268 } else {
269 /* IPv6 Address */
270 struct in6_addr in6;
271 uint32_t ip6addr[4];
272
273 dd->family = AF_INET6;
274
275 if ((mask = strchr(ip, '/')) != NULL) {
276 mask[0] = '\0';
277 mask++;
278
279 r = inet_pton(AF_INET6, ip, &in6);
280 if (r <= 0)
281 goto error;
282
283 /* Format is cidr val */
284 if (StringParseU8RangeCheck(&dd->netmask, 10, 0,
285 (const char *)mask, 0, 128) < 0) {
286 goto error;
287 }
288
289 memcpy(dd->ip, &in6.s6_addr, sizeof(ip6addr));
290 } else {
291 r = inet_pton(AF_INET6, ip, &in6);
292 if (r <= 0)
293 goto error;
294
295 memcpy(dd->ip, &in6.s6_addr, sizeof(dd->ip));
296 dd->netmask = 128;
297 }
298
299 }
300
301 BUG_ON(dd->family == 0);
302 return 0;
303
304 error:
305 return -1;
306 }
307
308 /**
309 * \brief Setup a single address string, parse it and add the resulting
310 * Address items in cidr format to the list of gh
311 *
312 * \param gh Pointer to the IPOnlyCIDRItem list Head to which the
313 * resulting Address-Range(s) from the parsed ip string has to
314 * be added.
315 * \param s Pointer to the ip address string to be parsed.
316 *
317 * \retval 0 On success.
318 * \retval -1 On failure.
319 */
IPOnlyCIDRItemSetup(IPOnlyCIDRItem ** gh,char * s)320 static int IPOnlyCIDRItemSetup(IPOnlyCIDRItem **gh, char *s)
321 {
322 SCLogDebug("gh %p, s %s", *gh, s);
323
324 /* parse the address */
325 if (IPOnlyCIDRItemParseSingle(gh, s) == -1) {
326 SCLogError(SC_ERR_ADDRESS_ENGINE_GENERIC,
327 "address parsing error \"%s\"", s);
328 goto error;
329 }
330
331 return 0;
332
333 error:
334 return -1;
335 }
336
337
338 /**
339 * \brief This function insert a IPOnlyCIDRItem
340 * to a list of IPOnlyCIDRItems sorted by netmask
341 * ascending
342 * \param head Pointer to the head of IPOnlyCIDRItems list
343 * \param item Pointer to the item to insert in the list
344 *
345 * \retval IPOnlyCIDRItem address of the new head if apply
346 */
IPOnlyCIDRItemInsertReal(IPOnlyCIDRItem * head,IPOnlyCIDRItem * item)347 static IPOnlyCIDRItem *IPOnlyCIDRItemInsertReal(IPOnlyCIDRItem *head,
348 IPOnlyCIDRItem *item)
349 {
350 IPOnlyCIDRItem *it, *prev = NULL;
351
352 if (item == NULL)
353 return head;
354
355 /* Compare with the head */
356 if (item->netmask < head->netmask || (item->netmask == head->netmask && IPOnlyCIDRItemCompare(head, item))) {
357 item->next = head;
358 return item;
359 }
360
361 if (item->netmask == head->netmask && !IPOnlyCIDRItemCompare(head, item)) {
362 item->next = head->next;
363 head->next = item;
364 return head;
365 }
366
367 for (prev = it = head;
368 it != NULL && it->netmask < item->netmask;
369 it = it->next)
370 prev = it;
371
372 if (it == NULL) {
373 prev->next = item;
374 item->next = NULL;
375 } else {
376 item->next = it;
377 prev->next = item;
378 }
379
380 return head;
381 }
382
383 /**
384 * \brief This function insert a IPOnlyCIDRItem list
385 * to a list of IPOnlyCIDRItems sorted by netmask
386 * ascending
387 * \param head Pointer to the head of IPOnlyCIDRItems list
388 * \param item Pointer to the list of items to insert in the list
389 *
390 * \retval IPOnlyCIDRItem address of the new head if apply
391 */
IPOnlyCIDRItemInsert(IPOnlyCIDRItem * head,IPOnlyCIDRItem * item)392 static IPOnlyCIDRItem *IPOnlyCIDRItemInsert(IPOnlyCIDRItem *head,
393 IPOnlyCIDRItem *item)
394 {
395 IPOnlyCIDRItem *it, *prev = NULL;
396
397 /* The first element */
398 if (head == NULL) {
399 SCLogDebug("Head is NULL to insert item (%p)",item);
400 return item;
401 }
402
403 if (item == NULL) {
404 SCLogDebug("Item is NULL");
405 return head;
406 }
407
408 SCLogDebug("Inserting item(%p)->netmask %u head %p", item, item->netmask, head);
409
410 prev = item;
411 while (prev != NULL) {
412 it = prev->next;
413
414 /* Separate from the item list */
415 prev->next = NULL;
416
417 //SCLogDebug("Before:");
418 //IPOnlyCIDRListPrint(head);
419 head = IPOnlyCIDRItemInsertReal(head, prev);
420 //SCLogDebug("After:");
421 //IPOnlyCIDRListPrint(head);
422 prev = it;
423 }
424
425 return head;
426 }
427
428 /**
429 * \brief This function free a IPOnlyCIDRItem list
430 * \param tmphead Pointer to the list
431 */
IPOnlyCIDRListFree(IPOnlyCIDRItem * tmphead)432 void IPOnlyCIDRListFree(IPOnlyCIDRItem *tmphead)
433 {
434 SCEnter();
435 uint32_t i = 0;
436
437 IPOnlyCIDRItem *it, *next = NULL;
438
439 if (tmphead == NULL) {
440 SCLogDebug("temphead is NULL");
441 return;
442 }
443
444 it = tmphead;
445 next = it->next;
446
447 while (it != NULL) {
448 i++;
449 SCFree(it);
450 SCLogDebug("Item(%p) %"PRIu32" removed", it, i);
451 it = next;
452
453 if (next != NULL)
454 next = next->next;
455 }
456 SCReturn;
457 }
458
459 /**
460 * \brief This function update a list of IPOnlyCIDRItems
461 * setting the signature internal id (signum) to "i"
462 *
463 * \param tmphead Pointer to the list
464 * \param i number of signature internal id
465 */
IPOnlyCIDRListSetSigNum(IPOnlyCIDRItem * tmphead,SigIntId i)466 static void IPOnlyCIDRListSetSigNum(IPOnlyCIDRItem *tmphead, SigIntId i)
467 {
468 while (tmphead != NULL) {
469 tmphead->signum = i;
470 tmphead = tmphead->next;
471 }
472 }
473
474 #ifdef UNITTESTS
475 /**
476 * \brief This function print a IPOnlyCIDRItem list
477 * \param tmphead Pointer to the head of IPOnlyCIDRItems list
478 */
IPOnlyCIDRListPrint(IPOnlyCIDRItem * tmphead)479 static void IPOnlyCIDRListPrint(IPOnlyCIDRItem *tmphead)
480 {
481 uint32_t i = 0;
482
483 while (tmphead != NULL) {
484 i++;
485 SCLogDebug("Item %"PRIu32" has netmask %"PRIu8" negated:"
486 " %s; IP: %s; signum: %"PRIu32, i, tmphead->netmask,
487 (tmphead->negated) ? "yes":"no",
488 inet_ntoa(*(struct in_addr*)&tmphead->ip[0]),
489 tmphead->signum);
490 tmphead = tmphead->next;
491 }
492 }
493 #endif
494
495 /**
496 * \brief This function print a SigNumArray, it's used with the
497 * radix tree print function to help debugging
498 * \param tmp Pointer to the head of SigNumArray
499 */
SigNumArrayPrint(void * tmp)500 static void SigNumArrayPrint(void *tmp)
501 {
502 SigNumArray *sna = (SigNumArray *)tmp;
503 uint32_t u;
504
505 for (u = 0; u < sna->size; u++) {
506 uint8_t bitarray = sna->array[u];
507 uint8_t i = 0;
508
509 for (; i < 8; i++) {
510 if (bitarray & 0x01)
511 printf(", %"PRIu32"", u * 8 + i);
512 else
513 printf(", ");
514
515 bitarray = bitarray >> 1;
516 }
517 }
518 }
519
520 /**
521 * \brief This function creates a new SigNumArray with the
522 * size fixed to the io_ctx->max_idx
523 * \param de_ctx Pointer to the current detection context
524 * \param io_ctx Pointer to the current ip only context
525 *
526 * \retval SigNumArray address of the new instance
527 */
SigNumArrayNew(DetectEngineCtx * de_ctx,DetectEngineIPOnlyCtx * io_ctx)528 static SigNumArray *SigNumArrayNew(DetectEngineCtx *de_ctx,
529 DetectEngineIPOnlyCtx *io_ctx)
530 {
531 SigNumArray *new = SCMalloc(sizeof(SigNumArray));
532
533 if (unlikely(new == NULL)) {
534 FatalError(SC_ERR_FATAL,
535 "Fatal error encountered in SigNumArrayNew. Exiting...");
536 }
537 memset(new, 0, sizeof(SigNumArray));
538
539 new->array = SCMalloc(io_ctx->max_idx / 8 + 1);
540 if (new->array == NULL) {
541 exit(EXIT_FAILURE);
542 }
543
544 memset(new->array, 0, io_ctx->max_idx / 8 + 1);
545 new->size = io_ctx->max_idx / 8 + 1;
546
547 SCLogDebug("max idx= %u", io_ctx->max_idx);
548
549 return new;
550 }
551
552 /**
553 * \brief This function creates a new SigNumArray with the
554 * same data as the argument
555 *
556 * \param orig Pointer to the original SigNumArray to copy
557 *
558 * \retval SigNumArray address of the new instance
559 */
SigNumArrayCopy(SigNumArray * orig)560 static SigNumArray *SigNumArrayCopy(SigNumArray *orig)
561 {
562 SigNumArray *new = SCMalloc(sizeof(SigNumArray));
563
564 if (unlikely(new == NULL)) {
565 FatalError(SC_ERR_FATAL,
566 "Fatal error encountered in SigNumArrayCopy. Exiting...");
567 }
568
569 memset(new, 0, sizeof(SigNumArray));
570 new->size = orig->size;
571
572 new->array = SCMalloc(orig->size);
573 if (new->array == NULL) {
574 exit(EXIT_FAILURE);
575 }
576
577 memcpy(new->array, orig->array, orig->size);
578 return new;
579 }
580
581 /**
582 * \brief This function free() a SigNumArray
583 * \param orig Pointer to the original SigNumArray to copy
584 */
SigNumArrayFree(void * tmp)585 static void SigNumArrayFree(void *tmp)
586 {
587 SigNumArray *sna = (SigNumArray *)tmp;
588
589 if (sna == NULL)
590 return;
591
592 if (sna->array != NULL)
593 SCFree(sna->array);
594
595 SCFree(sna);
596 }
597
598 /**
599 * \brief This function parses and return a list of IPOnlyCIDRItem
600 *
601 * \param s Pointer to the string of the addresses
602 * (in the format of signatures)
603 * \param negate flag to indicate if all this string is negated or not
604 *
605 * \retval 0 if success
606 * \retval -1 if fails
607 */
IPOnlyCIDRListParse2(const DetectEngineCtx * de_ctx,char * s,int negate)608 static IPOnlyCIDRItem *IPOnlyCIDRListParse2(const DetectEngineCtx *de_ctx,
609 char *s, int negate)
610 {
611 size_t x = 0;
612 size_t u = 0;
613 int o_set = 0, n_set = 0, d_set = 0;
614 int depth = 0;
615 size_t size = strlen(s);
616 char address[8196] = "";
617 const char *rule_var_address = NULL;
618 char *temp_rule_var_address = NULL;
619 IPOnlyCIDRItem *head;
620 IPOnlyCIDRItem *subhead;
621 head = subhead = NULL;
622
623 SCLogDebug("s %s negate %s", s, negate ? "true" : "false");
624
625 for (u = 0, x = 0; u < size && x < sizeof(address); u++) {
626 address[x] = s[u];
627 x++;
628
629 if (!o_set && s[u] == '!') {
630 n_set = 1;
631 x--;
632 } else if (s[u] == '[') {
633 if (!o_set) {
634 o_set = 1;
635 x = 0;
636 }
637 depth++;
638 } else if (s[u] == ']') {
639 if (depth == 1) {
640 address[x - 1] = '\0';
641 x = 0;
642
643 if ( (subhead = IPOnlyCIDRListParse2(de_ctx, address,
644 (negate + n_set) % 2)) == NULL)
645 goto error;
646
647 head = IPOnlyCIDRItemInsert(head, subhead);
648 n_set = 0;
649 }
650 depth--;
651 } else if (depth == 0 && s[u] == ',') {
652 if (o_set == 1) {
653 o_set = 0;
654 } else if (d_set == 1) {
655 address[x - 1] = '\0';
656
657 rule_var_address = SCRuleVarsGetConfVar(de_ctx, address,
658 SC_RULE_VARS_ADDRESS_GROUPS);
659 if (rule_var_address == NULL)
660 goto error;
661
662 if ((negate + n_set) % 2) {
663 temp_rule_var_address = SCMalloc(strlen(rule_var_address) + 3);
664 if (unlikely(temp_rule_var_address == NULL)) {
665 goto error;
666 }
667
668 snprintf(temp_rule_var_address, strlen(rule_var_address) + 3,
669 "[%s]", rule_var_address);
670 } else {
671 temp_rule_var_address = SCStrdup(rule_var_address);
672 if (unlikely(temp_rule_var_address == NULL)) {
673 goto error;
674 }
675 }
676
677 subhead = IPOnlyCIDRListParse2(de_ctx, temp_rule_var_address,
678 (negate + n_set) % 2);
679 head = IPOnlyCIDRItemInsert(head, subhead);
680
681 d_set = 0;
682 n_set = 0;
683
684 SCFree(temp_rule_var_address);
685
686 } else {
687 address[x - 1] = '\0';
688
689 subhead = IPOnlyCIDRItemNew();
690 if (subhead == NULL)
691 goto error;
692
693 if (!((negate + n_set) % 2))
694 subhead->negated = 0;
695 else
696 subhead->negated = 1;
697
698 if (IPOnlyCIDRItemSetup(&subhead, address) < 0) {
699 IPOnlyCIDRListFree(subhead);
700 subhead = NULL;
701 goto error;
702 }
703 head = IPOnlyCIDRItemInsert(head, subhead);
704
705 n_set = 0;
706 }
707 x = 0;
708 } else if (depth == 0 && s[u] == '$') {
709 d_set = 1;
710 } else if (depth == 0 && u == size - 1) {
711 if (x == sizeof(address)) {
712 address[x - 1] = '\0';
713 } else {
714 address[x] = '\0';
715 }
716 x = 0;
717
718 if (d_set == 1) {
719 rule_var_address = SCRuleVarsGetConfVar(de_ctx, address,
720 SC_RULE_VARS_ADDRESS_GROUPS);
721 if (rule_var_address == NULL)
722 goto error;
723
724 if ((negate + n_set) % 2) {
725 temp_rule_var_address = SCMalloc(strlen(rule_var_address) + 3);
726 if (unlikely(temp_rule_var_address == NULL)) {
727 goto error;
728 }
729 snprintf(temp_rule_var_address, strlen(rule_var_address) + 3,
730 "[%s]", rule_var_address);
731 } else {
732 temp_rule_var_address = SCStrdup(rule_var_address);
733 if (unlikely(temp_rule_var_address == NULL)) {
734 goto error;
735 }
736 }
737 subhead = IPOnlyCIDRListParse2(de_ctx, temp_rule_var_address,
738 (negate + n_set) % 2);
739 head = IPOnlyCIDRItemInsert(head, subhead);
740
741 d_set = 0;
742
743 SCFree(temp_rule_var_address);
744 } else {
745 subhead = IPOnlyCIDRItemNew();
746 if (subhead == NULL)
747 goto error;
748
749 if (!((negate + n_set) % 2))
750 subhead->negated = 0;
751 else
752 subhead->negated = 1;
753
754 if (IPOnlyCIDRItemSetup(&subhead, address) < 0) {
755 IPOnlyCIDRListFree(subhead);
756 subhead = NULL;
757 goto error;
758 }
759 head = IPOnlyCIDRItemInsert(head, subhead);
760 }
761 n_set = 0;
762 }
763 }
764
765 return head;
766
767 error:
768 SCLogError(SC_ERR_ADDRESS_ENGINE_GENERIC,"Error parsing addresses");
769 return head;
770 }
771
772
773 /**
774 * \brief Parses an address group sent as a character string and updates the
775 * IPOnlyCIDRItem list
776 *
777 * \param gh Pointer to the IPOnlyCIDRItem list
778 * \param str Pointer to the character string containing the address group
779 * that has to be parsed.
780 *
781 * \retval 0 On success.
782 * \retval -1 On failure.
783 */
IPOnlyCIDRListParse(const DetectEngineCtx * de_ctx,IPOnlyCIDRItem ** gh,char * str)784 static int IPOnlyCIDRListParse(const DetectEngineCtx *de_ctx,
785 IPOnlyCIDRItem **gh, char *str)
786 {
787 SCLogDebug("gh %p, str %s", gh, str);
788
789 if (gh == NULL)
790 goto error;
791
792 *gh = IPOnlyCIDRListParse2(de_ctx, str, 0);
793 if (*gh == NULL) {
794 SCLogDebug("IPOnlyCIDRListParse2 returned null");
795 goto error;
796 }
797
798 return 0;
799
800 error:
801 return -1;
802 }
803
804 /**
805 * \brief Parses an address group sent as a character string and updates the
806 * IPOnlyCIDRItem lists src and dst of the Signature *s
807 *
808 * \param s Pointer to the signature structure
809 * \param addrstr Pointer to the character string containing the address group
810 * that has to be parsed.
811 * \param flag to indicate if we are parsing the src string or the dst string
812 *
813 * \retval 0 On success.
814 * \retval -1 On failure.
815 */
IPOnlySigParseAddress(const DetectEngineCtx * de_ctx,Signature * s,const char * addrstr,char flag)816 int IPOnlySigParseAddress(const DetectEngineCtx *de_ctx,
817 Signature *s, const char *addrstr, char flag)
818 {
819 SCLogDebug("Address Group \"%s\" to be parsed now", addrstr);
820 IPOnlyCIDRItem *tmp = NULL;
821
822 /* pass on to the address(list) parser */
823 if (flag == 0) {
824 if (strcasecmp(addrstr, "any") == 0) {
825 s->flags |= SIG_FLAG_SRC_ANY;
826
827 if (IPOnlyCIDRListParse(de_ctx, &s->CidrSrc, (char *)"0.0.0.0/0") < 0)
828 goto error;
829
830 if (IPOnlyCIDRListParse(de_ctx, &tmp, (char *)"::/0") < 0)
831 goto error;
832
833 s->CidrSrc = IPOnlyCIDRItemInsert(s->CidrSrc, tmp);
834
835 } else if (IPOnlyCIDRListParse(de_ctx, &s->CidrSrc, (char *)addrstr) < 0) {
836 goto error;
837 }
838
839 /* IPOnlyCIDRListPrint(s->CidrSrc); */
840 } else {
841 if (strcasecmp(addrstr, "any") == 0) {
842 s->flags |= SIG_FLAG_DST_ANY;
843
844 if (IPOnlyCIDRListParse(de_ctx, &tmp, (char *)"0.0.0.0/0") < 0)
845 goto error;
846
847 if (IPOnlyCIDRListParse(de_ctx, &s->CidrDst, (char *)"::/0") < 0)
848 goto error;
849
850 s->CidrDst = IPOnlyCIDRItemInsert(s->CidrDst, tmp);
851
852 } else if (IPOnlyCIDRListParse(de_ctx, &s->CidrDst, (char *)addrstr) < 0) {
853 goto error;
854 }
855
856 /* IPOnlyCIDRListPrint(s->CidrDst); */
857 }
858
859 return 0;
860
861 error:
862 SCLogError(SC_ERR_ADDRESS_ENGINE_GENERIC, "failed to parse addresses");
863 return -1;
864 }
865
866 /**
867 * \brief Setup the IP Only detection engine context
868 *
869 * \param de_ctx Pointer to the current detection engine
870 * \param io_ctx Pointer to the current ip only detection engine
871 */
IPOnlyInit(DetectEngineCtx * de_ctx,DetectEngineIPOnlyCtx * io_ctx)872 void IPOnlyInit(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
873 {
874 io_ctx->sig_init_size = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
875
876 if ( (io_ctx->sig_init_array = SCMalloc(io_ctx->sig_init_size)) == NULL) {
877 FatalError(SC_ERR_FATAL,
878 "Fatal error encountered in IPOnlyInit. Exiting...");
879 }
880
881 memset(io_ctx->sig_init_array, 0, io_ctx->sig_init_size);
882
883 io_ctx->tree_ipv4src = SCRadixCreateRadixTree(SigNumArrayFree,
884 SigNumArrayPrint);
885 io_ctx->tree_ipv4dst = SCRadixCreateRadixTree(SigNumArrayFree,
886 SigNumArrayPrint);
887 io_ctx->tree_ipv6src = SCRadixCreateRadixTree(SigNumArrayFree,
888 SigNumArrayPrint);
889 io_ctx->tree_ipv6dst = SCRadixCreateRadixTree(SigNumArrayFree,
890 SigNumArrayPrint);
891 }
892
893 /**
894 * \brief Setup the IP Only thread detection engine context
895 *
896 * \param de_ctx Pointer to the current detection engine
897 * \param io_ctx Pointer to the current ip only thread detection engine
898 */
DetectEngineIPOnlyThreadInit(DetectEngineCtx * de_ctx,DetectEngineIPOnlyThreadCtx * io_tctx)899 void DetectEngineIPOnlyThreadInit(DetectEngineCtx *de_ctx,
900 DetectEngineIPOnlyThreadCtx *io_tctx)
901 {
902 /* initialize the signature bitarray */
903 io_tctx->sig_match_size = de_ctx->io_ctx.max_idx / 8 + 1;
904 io_tctx->sig_match_array = SCMalloc(io_tctx->sig_match_size);
905 if (io_tctx->sig_match_array == NULL) {
906 exit(EXIT_FAILURE);
907 }
908
909 memset(io_tctx->sig_match_array, 0, io_tctx->sig_match_size);
910 }
911
912 /**
913 * \brief Print stats of the IP Only engine
914 *
915 * \param de_ctx Pointer to the current detection engine
916 * \param io_ctx Pointer to the current ip only detection engine
917 */
IPOnlyPrint(DetectEngineCtx * de_ctx,DetectEngineIPOnlyCtx * io_ctx)918 void IPOnlyPrint(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
919 {
920 /* XXX: how are we going to print the stats now? */
921 }
922
923 /**
924 * \brief Deinitialize the IP Only detection engine context
925 *
926 * \param de_ctx Pointer to the current detection engine
927 * \param io_ctx Pointer to the current ip only detection engine
928 */
IPOnlyDeinit(DetectEngineCtx * de_ctx,DetectEngineIPOnlyCtx * io_ctx)929 void IPOnlyDeinit(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
930 {
931
932 if (io_ctx == NULL)
933 return;
934
935 if (io_ctx->tree_ipv4src != NULL)
936 SCRadixReleaseRadixTree(io_ctx->tree_ipv4src);
937 io_ctx->tree_ipv4src = NULL;
938
939 if (io_ctx->tree_ipv4dst != NULL)
940 SCRadixReleaseRadixTree(io_ctx->tree_ipv4dst);
941 io_ctx->tree_ipv4dst = NULL;
942
943 if (io_ctx->tree_ipv6src != NULL)
944 SCRadixReleaseRadixTree(io_ctx->tree_ipv6src);
945 io_ctx->tree_ipv6src = NULL;
946
947 if (io_ctx->tree_ipv6dst != NULL)
948 SCRadixReleaseRadixTree(io_ctx->tree_ipv6dst);
949 io_ctx->tree_ipv6dst = NULL;
950
951 if (io_ctx->sig_init_array)
952 SCFree(io_ctx->sig_init_array);
953 io_ctx->sig_init_array = NULL;
954 }
955
956 /**
957 * \brief Deinitialize the IP Only thread detection engine context
958 *
959 * \param de_ctx Pointer to the current detection engine
960 * \param io_ctx Pointer to the current ip only detection engine
961 */
DetectEngineIPOnlyThreadDeinit(DetectEngineIPOnlyThreadCtx * io_tctx)962 void DetectEngineIPOnlyThreadDeinit(DetectEngineIPOnlyThreadCtx *io_tctx)
963 {
964 SCFree(io_tctx->sig_match_array);
965 }
966
967 static inline
IPOnlyMatchCompatSMs(ThreadVars * tv,DetectEngineThreadCtx * det_ctx,Signature * s,Packet * p)968 int IPOnlyMatchCompatSMs(ThreadVars *tv,
969 DetectEngineThreadCtx *det_ctx,
970 Signature *s, Packet *p)
971 {
972 KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_MATCH);
973 SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_MATCH];
974 if (smd) {
975 while (1) {
976 DEBUG_VALIDATE_BUG_ON(!(sigmatch_table[smd->type].flags & SIGMATCH_IPONLY_COMPAT));
977 KEYWORD_PROFILING_START;
978 if (sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx) > 0) {
979 KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
980 if (smd->is_last)
981 break;
982 smd++;
983 continue;
984 }
985 KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
986 return 0;
987 }
988 }
989 return 1;
990 }
991
992 /**
993 * \brief Match a packet against the IP Only detection engine contexts
994 *
995 * \param de_ctx Pointer to the current detection engine
996 * \param io_ctx Pointer to the current ip only detection engine
997 * \param io_ctx Pointer to the current ip only thread detection engine
998 * \param p Pointer to the Packet to match against
999 */
IPOnlyMatchPacket(ThreadVars * tv,const DetectEngineCtx * de_ctx,DetectEngineThreadCtx * det_ctx,const DetectEngineIPOnlyCtx * io_ctx,DetectEngineIPOnlyThreadCtx * io_tctx,Packet * p)1000 void IPOnlyMatchPacket(ThreadVars *tv,
1001 const DetectEngineCtx *de_ctx,
1002 DetectEngineThreadCtx *det_ctx,
1003 const DetectEngineIPOnlyCtx *io_ctx,
1004 DetectEngineIPOnlyThreadCtx *io_tctx, Packet *p)
1005 {
1006 SigNumArray *src = NULL;
1007 SigNumArray *dst = NULL;
1008 void *user_data_src = NULL, *user_data_dst = NULL;
1009
1010 SCEnter();
1011
1012 if (p->src.family == AF_INET) {
1013 (void)SCRadixFindKeyIPV4BestMatch((uint8_t *)&GET_IPV4_SRC_ADDR_U32(p),
1014 io_ctx->tree_ipv4src, &user_data_src);
1015 } else if (p->src.family == AF_INET6) {
1016 (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&GET_IPV6_SRC_ADDR(p),
1017 io_ctx->tree_ipv6src, &user_data_src);
1018 }
1019
1020 if (p->dst.family == AF_INET) {
1021 (void)SCRadixFindKeyIPV4BestMatch((uint8_t *)&GET_IPV4_DST_ADDR_U32(p),
1022 io_ctx->tree_ipv4dst, &user_data_dst);
1023 } else if (p->dst.family == AF_INET6) {
1024 (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&GET_IPV6_DST_ADDR(p),
1025 io_ctx->tree_ipv6dst, &user_data_dst);
1026 }
1027
1028 src = user_data_src;
1029 dst = user_data_dst;
1030
1031 if (src == NULL || dst == NULL)
1032 SCReturn;
1033
1034 uint32_t u;
1035 for (u = 0; u < src->size; u++) {
1036 SCLogDebug("And %"PRIu8" & %"PRIu8, src->array[u], dst->array[u]);
1037
1038 /* The final results will be at io_tctx */
1039 io_tctx->sig_match_array[u] = dst->array[u] & src->array[u];
1040
1041 /* We have to move the logic of the signature checking
1042 * to the main detect loop, in order to apply the
1043 * priority of actions (pass, drop, reject, alert) */
1044 if (io_tctx->sig_match_array[u] != 0) {
1045 /* We have a match :) Let's see from which signum's */
1046 uint8_t bitarray = io_tctx->sig_match_array[u];
1047 uint8_t i = 0;
1048
1049 for (; i < 8; i++, bitarray = bitarray >> 1) {
1050 if (bitarray & 0x01) {
1051 Signature *s = de_ctx->sig_array[u * 8 + i];
1052
1053 if ((s->proto.flags & DETECT_PROTO_IPV4) && !PKT_IS_IPV4(p)) {
1054 SCLogDebug("ip version didn't match");
1055 continue;
1056 }
1057 if ((s->proto.flags & DETECT_PROTO_IPV6) && !PKT_IS_IPV6(p)) {
1058 SCLogDebug("ip version didn't match");
1059 continue;
1060 }
1061
1062 if (DetectProtoContainsProto(&s->proto, IP_GET_IPPROTO(p)) == 0) {
1063 SCLogDebug("proto didn't match");
1064 continue;
1065 }
1066
1067 /* check the source & dst port in the sig */
1068 if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP || p->proto == IPPROTO_SCTP) {
1069 if (!(s->flags & SIG_FLAG_DP_ANY)) {
1070 if (p->flags & PKT_IS_FRAGMENT)
1071 continue;
1072
1073 DetectPort *dport = DetectPortLookupGroup(s->dp,p->dp);
1074 if (dport == NULL) {
1075 SCLogDebug("dport didn't match.");
1076 continue;
1077 }
1078 }
1079 if (!(s->flags & SIG_FLAG_SP_ANY)) {
1080 if (p->flags & PKT_IS_FRAGMENT)
1081 continue;
1082
1083 DetectPort *sport = DetectPortLookupGroup(s->sp,p->sp);
1084 if (sport == NULL) {
1085 SCLogDebug("sport didn't match.");
1086 continue;
1087 }
1088 }
1089 } else if ((s->flags & (SIG_FLAG_DP_ANY|SIG_FLAG_SP_ANY)) != (SIG_FLAG_DP_ANY|SIG_FLAG_SP_ANY)) {
1090 SCLogDebug("port-less protocol and sig needs ports");
1091 continue;
1092 }
1093
1094 if (!IPOnlyMatchCompatSMs(tv, det_ctx, s, p)) {
1095 continue;
1096 }
1097
1098 SCLogDebug("Signum %"PRIu32" match (sid: %"PRIu32", msg: %s)",
1099 u * 8 + i, s->id, s->msg);
1100
1101 if (s->sm_arrays[DETECT_SM_LIST_POSTMATCH] != NULL) {
1102 KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_POSTMATCH);
1103 SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_POSTMATCH];
1104
1105 SCLogDebug("running match functions, sm %p", smd);
1106
1107 if (smd != NULL) {
1108 while (1) {
1109 KEYWORD_PROFILING_START;
1110 (void)sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx);
1111 KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
1112 if (smd->is_last)
1113 break;
1114 smd++;
1115 }
1116 }
1117 }
1118 PacketAlertAppend(det_ctx, s, p, 0, 0);
1119 }
1120 }
1121 }
1122 }
1123 SCReturn;
1124 }
1125
1126 /**
1127 * \brief Build the radix trees from the lists of parsed adresses in CIDR format
1128 * the result should be 4 radix trees: src/dst ipv4 and src/dst ipv6
1129 * holding SigNumArrays, each of them with a hierarchical relation
1130 * of subnets and hosts
1131 *
1132 * \param de_ctx Pointer to the current detection engine
1133 */
IPOnlyPrepare(DetectEngineCtx * de_ctx)1134 void IPOnlyPrepare(DetectEngineCtx *de_ctx)
1135 {
1136 SCLogDebug("Preparing Final Lists");
1137
1138 /*
1139 IPOnlyCIDRListPrint((de_ctx->io_ctx).ip_src);
1140 IPOnlyCIDRListPrint((de_ctx->io_ctx).ip_dst);
1141 */
1142
1143 IPOnlyCIDRItem *src, *dst;
1144 SCRadixNode *node = NULL;
1145
1146 /* Prepare Src radix trees */
1147 for (src = (de_ctx->io_ctx).ip_src; src != NULL; ) {
1148 if (src->family == AF_INET) {
1149 /*
1150 SCLogDebug("To IPv4");
1151 SCLogDebug("Item has netmask %"PRIu16" negated: %s; IP: %s; "
1152 "signum: %"PRIu16, src->netmask,
1153 (src->negated) ? "yes":"no",
1154 inet_ntoa( *(struct in_addr*)&src->ip[0]),
1155 src->signum);
1156 */
1157
1158 void *user_data = NULL;
1159 if (src->netmask == 32)
1160 (void)SCRadixFindKeyIPV4ExactMatch((uint8_t *)&src->ip[0],
1161 (de_ctx->io_ctx).tree_ipv4src,
1162 &user_data);
1163 else
1164 (void)SCRadixFindKeyIPV4Netblock((uint8_t *)&src->ip[0],
1165 (de_ctx->io_ctx).tree_ipv4src,
1166 src->netmask, &user_data);
1167 if (user_data == NULL) {
1168 SCLogDebug("Exact match not found");
1169
1170 /** Not found, look if there's a subnet of this range with
1171 * bigger netmask */
1172 (void)SCRadixFindKeyIPV4BestMatch((uint8_t *)&src->ip[0],
1173 (de_ctx->io_ctx).tree_ipv4src,
1174 &user_data);
1175 if (user_data == NULL) {
1176 SCLogDebug("best match not found");
1177
1178 /* Not found, insert a new one */
1179 SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1180
1181 /* Update the sig */
1182 uint8_t tmp = 1 << (src->signum % 8);
1183
1184 if (src->negated > 0)
1185 /* Unset it */
1186 sna->array[src->signum / 8] &= ~tmp;
1187 else
1188 /* Set it */
1189 sna->array[src->signum / 8] |= tmp;
1190
1191 if (src->netmask == 32)
1192 node = SCRadixAddKeyIPV4((uint8_t *)&src->ip[0],
1193 (de_ctx->io_ctx).tree_ipv4src, sna);
1194 else
1195 node = SCRadixAddKeyIPV4Netblock((uint8_t *)&src->ip[0],
1196 (de_ctx->io_ctx).tree_ipv4src,
1197 sna, src->netmask);
1198
1199 if (node == NULL)
1200 SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the "
1201 "src ipv4 radix tree");
1202 } else {
1203 SCLogDebug("Best match found");
1204
1205 /* Found, copy the sig num table, add this signum and insert */
1206 SigNumArray *sna = NULL;
1207 sna = SigNumArrayCopy((SigNumArray *) user_data);
1208
1209 /* Update the sig */
1210 uint8_t tmp = 1 << (src->signum % 8);
1211
1212 if (src->negated > 0)
1213 /* Unset it */
1214 sna->array[src->signum / 8] &= ~tmp;
1215 else
1216 /* Set it */
1217 sna->array[src->signum / 8] |= tmp;
1218
1219 if (src->netmask == 32)
1220 node = SCRadixAddKeyIPV4((uint8_t *)&src->ip[0],
1221 (de_ctx->io_ctx).tree_ipv4src, sna);
1222 else
1223 node = SCRadixAddKeyIPV4Netblock((uint8_t *)&src->ip[0],
1224 (de_ctx->io_ctx).tree_ipv4src, sna,
1225 src->netmask);
1226
1227 if (node == NULL) {
1228 char tmpstr[64];
1229 PrintInet(src->family, &src->ip[0], tmpstr, sizeof(tmpstr));
1230 SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the"
1231 " src ipv4 radix tree ip %s netmask %"PRIu8, tmpstr, src->netmask);
1232 //SCRadixPrintTree((de_ctx->io_ctx).tree_ipv4src);
1233 exit(-1);
1234 }
1235 }
1236 } else {
1237 SCLogDebug("Exact match found");
1238
1239 /* it's already inserted. Update it */
1240 SigNumArray *sna = (SigNumArray *)user_data;
1241
1242 /* Update the sig */
1243 uint8_t tmp = 1 << (src->signum % 8);
1244
1245 if (src->negated > 0)
1246 /* Unset it */
1247 sna->array[src->signum / 8] &= ~tmp;
1248 else
1249 /* Set it */
1250 sna->array[src->signum / 8] |= tmp;
1251 }
1252 } else if (src->family == AF_INET6) {
1253 SCLogDebug("To IPv6");
1254
1255 void *user_data = NULL;
1256 if (src->netmask == 128)
1257 (void)SCRadixFindKeyIPV6ExactMatch((uint8_t *)&src->ip[0],
1258 (de_ctx->io_ctx).tree_ipv6src,
1259 &user_data);
1260 else
1261 (void)SCRadixFindKeyIPV6Netblock((uint8_t *)&src->ip[0],
1262 (de_ctx->io_ctx).tree_ipv6src,
1263 src->netmask, &user_data);
1264
1265 if (user_data == NULL) {
1266 /* Not found, look if there's a subnet of this range with bigger netmask */
1267 (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&src->ip[0],
1268 (de_ctx->io_ctx).tree_ipv6src,
1269 &user_data);
1270
1271 if (user_data == NULL) {
1272 /* Not found, insert a new one */
1273 SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1274
1275 /* Update the sig */
1276 uint8_t tmp = 1 << (src->signum % 8);
1277
1278 if (src->negated > 0)
1279 /* Unset it */
1280 sna->array[src->signum / 8] &= ~tmp;
1281 else
1282 /* Set it */
1283 sna->array[src->signum / 8] |= tmp;
1284
1285 if (src->netmask == 128)
1286 node = SCRadixAddKeyIPV6((uint8_t *)&src->ip[0],
1287 (de_ctx->io_ctx).tree_ipv6src, sna);
1288 else
1289 node = SCRadixAddKeyIPV6Netblock((uint8_t *)&src->ip[0],
1290 (de_ctx->io_ctx).tree_ipv6src,
1291 sna, src->netmask);
1292 if (node == NULL)
1293 SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the src "
1294 "ipv6 radix tree");
1295 } else {
1296 /* Found, copy the sig num table, add this signum and insert */
1297 SigNumArray *sna = NULL;
1298 sna = SigNumArrayCopy((SigNumArray *)user_data);
1299
1300 /* Update the sig */
1301 uint8_t tmp = 1 << (src->signum % 8);
1302 if (src->negated > 0)
1303 /* Unset it */
1304 sna->array[src->signum / 8] &= ~tmp;
1305 else
1306 /* Set it */
1307 sna->array[src->signum / 8] |= tmp;
1308
1309 if (src->netmask == 128)
1310 node = SCRadixAddKeyIPV6((uint8_t *)&src->ip[0],
1311 (de_ctx->io_ctx).tree_ipv6src, sna);
1312 else
1313 node = SCRadixAddKeyIPV6Netblock((uint8_t *)&src->ip[0],
1314 (de_ctx->io_ctx).tree_ipv6src,
1315 sna, src->netmask);
1316 if (node == NULL)
1317 SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the src "
1318 "ipv6 radix tree");
1319 }
1320 } else {
1321 /* it's already inserted. Update it */
1322 SigNumArray *sna = (SigNumArray *)user_data;
1323
1324 /* Update the sig */
1325 uint8_t tmp = 1 << (src->signum % 8);
1326 if (src->negated > 0)
1327 /* Unset it */
1328 sna->array[src->signum / 8] &= ~tmp;
1329 else
1330 /* Set it */
1331 sna->array[src->signum / 8] |= tmp;
1332 }
1333 }
1334 IPOnlyCIDRItem *tmpaux = src;
1335 src = src->next;
1336 SCFree(tmpaux);
1337 }
1338
1339 SCLogDebug("dsts:");
1340
1341 /* Prepare Dst radix trees */
1342 for (dst = (de_ctx->io_ctx).ip_dst; dst != NULL; ) {
1343 if (dst->family == AF_INET) {
1344
1345 SCLogDebug("To IPv4");
1346 SCLogDebug("Item has netmask %"PRIu8" negated: %s; IP: %s; signum:"
1347 " %"PRIu32"", dst->netmask, (dst->negated)?"yes":"no",
1348 inet_ntoa(*(struct in_addr*)&dst->ip[0]), dst->signum);
1349
1350 void *user_data = NULL;
1351 if (dst->netmask == 32)
1352 (void) SCRadixFindKeyIPV4ExactMatch((uint8_t *) &dst->ip[0],
1353 (de_ctx->io_ctx).tree_ipv4dst,
1354 &user_data);
1355 else
1356 (void) SCRadixFindKeyIPV4Netblock((uint8_t *) &dst->ip[0],
1357 (de_ctx->io_ctx).tree_ipv4dst,
1358 dst->netmask,
1359 &user_data);
1360
1361 if (user_data == NULL) {
1362 SCLogDebug("Exact match not found");
1363
1364 /**
1365 * Not found, look if there's a subnet of this range
1366 * with bigger netmask
1367 */
1368 (void) SCRadixFindKeyIPV4BestMatch((uint8_t *)&dst->ip[0],
1369 (de_ctx->io_ctx).tree_ipv4dst,
1370 &user_data);
1371 if (user_data == NULL) {
1372 SCLogDebug("Best match not found");
1373
1374 /** Not found, insert a new one */
1375 SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1376
1377 /** Update the sig */
1378 uint8_t tmp = 1 << (dst->signum % 8);
1379 if (dst->negated > 0)
1380 /** Unset it */
1381 sna->array[dst->signum / 8] &= ~tmp;
1382 else
1383 /** Set it */
1384 sna->array[dst->signum / 8] |= tmp;
1385
1386 if (dst->netmask == 32)
1387 node = SCRadixAddKeyIPV4((uint8_t *)&dst->ip[0],
1388 (de_ctx->io_ctx).tree_ipv4dst, sna);
1389 else
1390 node = SCRadixAddKeyIPV4Netblock((uint8_t *)&dst->ip[0],
1391 (de_ctx->io_ctx).tree_ipv4dst,
1392 sna, dst->netmask);
1393
1394 if (node == NULL)
1395 SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the dst "
1396 "ipv4 radix tree");
1397 } else {
1398 SCLogDebug("Best match found");
1399
1400 /* Found, copy the sig num table, add this signum and insert */
1401 SigNumArray *sna = NULL;
1402 sna = SigNumArrayCopy((SigNumArray *) user_data);
1403
1404 /* Update the sig */
1405 uint8_t tmp = 1 << (dst->signum % 8);
1406 if (dst->negated > 0)
1407 /* Unset it */
1408 sna->array[dst->signum / 8] &= ~tmp;
1409 else
1410 /* Set it */
1411 sna->array[dst->signum / 8] |= tmp;
1412
1413 if (dst->netmask == 32)
1414 node = SCRadixAddKeyIPV4((uint8_t *)&dst->ip[0],
1415 (de_ctx->io_ctx).tree_ipv4dst, sna);
1416 else
1417 node = SCRadixAddKeyIPV4Netblock((uint8_t *)&dst->ip[0],
1418 (de_ctx->io_ctx).tree_ipv4dst,
1419 sna, dst->netmask);
1420
1421 if (node == NULL)
1422 SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the dst "
1423 "ipv4 radix tree");
1424 }
1425 } else {
1426 SCLogDebug("Exact match found");
1427
1428 /* it's already inserted. Update it */
1429 SigNumArray *sna = (SigNumArray *)user_data;
1430
1431 /* Update the sig */
1432 uint8_t tmp = 1 << (dst->signum % 8);
1433 if (dst->negated > 0)
1434 /* Unset it */
1435 sna->array[dst->signum / 8] &= ~tmp;
1436 else
1437 /* Set it */
1438 sna->array[dst->signum / 8] |= tmp;
1439 }
1440 } else if (dst->family == AF_INET6) {
1441 SCLogDebug("To IPv6");
1442
1443 void *user_data = NULL;
1444 if (dst->netmask == 128)
1445 (void) SCRadixFindKeyIPV6ExactMatch((uint8_t *)&dst->ip[0],
1446 (de_ctx->io_ctx).tree_ipv6dst,
1447 &user_data);
1448 else
1449 (void) SCRadixFindKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1450 (de_ctx->io_ctx).tree_ipv6dst,
1451 dst->netmask, &user_data);
1452
1453 if (user_data == NULL) {
1454 /** Not found, look if there's a subnet of this range with
1455 * bigger netmask
1456 */
1457 (void) SCRadixFindKeyIPV6BestMatch((uint8_t *)&dst->ip[0],
1458 (de_ctx->io_ctx).tree_ipv6dst,
1459 &user_data);
1460
1461 if (user_data == NULL) {
1462 /* Not found, insert a new one */
1463 SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1464
1465 /* Update the sig */
1466 uint8_t tmp = 1 << (dst->signum % 8);
1467 if (dst->negated > 0)
1468 /* Unset it */
1469 sna->array[dst->signum / 8] &= ~tmp;
1470 else
1471 /* Set it */
1472 sna->array[dst->signum / 8] |= tmp;
1473
1474 if (dst->netmask == 128)
1475 node = SCRadixAddKeyIPV6((uint8_t *)&dst->ip[0],
1476 (de_ctx->io_ctx).tree_ipv6dst, sna);
1477 else
1478 node = SCRadixAddKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1479 (de_ctx->io_ctx).tree_ipv6dst,
1480 sna, dst->netmask);
1481
1482 if (node == NULL)
1483 SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the dst "
1484 "ipv6 radix tree");
1485 } else {
1486 /* Found, copy the sig num table, add this signum and insert */
1487 SigNumArray *sna = NULL;
1488 sna = SigNumArrayCopy((SigNumArray *)user_data);
1489
1490 /* Update the sig */
1491 uint8_t tmp = 1 << (dst->signum % 8);
1492 if (dst->negated > 0)
1493 /* Unset it */
1494 sna->array[dst->signum / 8] &= ~tmp;
1495 else
1496 /* Set it */
1497 sna->array[dst->signum / 8] |= tmp;
1498
1499 if (dst->netmask == 128)
1500 node = SCRadixAddKeyIPV6((uint8_t *)&dst->ip[0],
1501 (de_ctx->io_ctx).tree_ipv6dst, sna);
1502 else
1503 node = SCRadixAddKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1504 (de_ctx->io_ctx).tree_ipv6dst,
1505 sna, dst->netmask);
1506
1507 if (node == NULL)
1508 SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the dst "
1509 "ipv6 radix tree");
1510 }
1511 } else {
1512 /* it's already inserted. Update it */
1513 SigNumArray *sna = (SigNumArray *)user_data;
1514
1515 /* Update the sig */
1516 uint8_t tmp = 1 << (dst->signum % 8);
1517 if (dst->negated > 0)
1518 /* Unset it */
1519 sna->array[dst->signum / 8] &= ~tmp;
1520 else
1521 /* Set it */
1522 sna->array[dst->signum / 8] |= tmp;
1523 }
1524 }
1525 IPOnlyCIDRItem *tmpaux = dst;
1526 dst = dst->next;
1527 SCFree(tmpaux);
1528 }
1529
1530 /* print all the trees: for debugging it might print too much info
1531 SCLogDebug("Radix tree src ipv4:");
1532 SCRadixPrintTree((de_ctx->io_ctx).tree_ipv4src);
1533 SCLogDebug("Radix tree src ipv6:");
1534 SCRadixPrintTree((de_ctx->io_ctx).tree_ipv6src);
1535 SCLogDebug("__________________");
1536
1537 SCLogDebug("Radix tree dst ipv4:");
1538 SCRadixPrintTree((de_ctx->io_ctx).tree_ipv4dst);
1539 SCLogDebug("Radix tree dst ipv6:");
1540 SCRadixPrintTree((de_ctx->io_ctx).tree_ipv6dst);
1541 SCLogDebug("__________________");
1542 */
1543 }
1544
1545 /**
1546 * \brief Add a signature to the lists of Addresses in CIDR format (sorted)
1547 * this step is necesary to build the radix tree with a hierarchical
1548 * relation between nodes
1549 * \param de_ctx Pointer to the current detection engine context
1550 * \param de_ctx Pointer to the current ip only detection engine contest
1551 * \param s Pointer to the current signature
1552 */
IPOnlyAddSignature(DetectEngineCtx * de_ctx,DetectEngineIPOnlyCtx * io_ctx,Signature * s)1553 void IPOnlyAddSignature(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx,
1554 Signature *s)
1555 {
1556 if (!(s->flags & SIG_FLAG_IPONLY))
1557 return;
1558
1559 /* Set the internal signum to the list before merging */
1560 IPOnlyCIDRListSetSigNum(s->CidrSrc, s->num);
1561
1562 IPOnlyCIDRListSetSigNum(s->CidrDst, s->num);
1563
1564 /**
1565 * ipv4 and ipv6 are mixed, but later we will separate them into
1566 * different trees
1567 */
1568 io_ctx->ip_src = IPOnlyCIDRItemInsert(io_ctx->ip_src, s->CidrSrc);
1569 io_ctx->ip_dst = IPOnlyCIDRItemInsert(io_ctx->ip_dst, s->CidrDst);
1570
1571 if (s->num > io_ctx->max_idx)
1572 io_ctx->max_idx = s->num;
1573
1574 /* enable the sig in the bitarray */
1575 io_ctx->sig_init_array[(s->num/8)] |= 1 << (s->num % 8);
1576
1577 /** no longer ref to this, it's in the table now */
1578 s->CidrSrc = NULL;
1579 s->CidrDst = NULL;
1580 }
1581
1582 #ifdef UNITTESTS
1583 /**
1584 * \test check that we set a Signature as IPOnly because it has no rule
1585 * option appending a SigMatch and no port is fixed
1586 */
1587
IPOnlyTestSig01(void)1588 static int IPOnlyTestSig01(void)
1589 {
1590 DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1591 FAIL_IF(de_ctx == NULL);
1592 de_ctx->flags |= DE_QUIET;
1593
1594 Signature *s = SigInit(de_ctx,"alert tcp any any -> any any (sid:400001; rev:1;)");
1595 FAIL_IF(s == NULL);
1596
1597 FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
1598 SigFree(de_ctx, s);
1599 DetectEngineCtxFree(de_ctx);
1600 PASS;
1601 }
1602
1603 /**
1604 * \test check that we dont set a Signature as IPOnly because it has no rule
1605 * option appending a SigMatch but a port is fixed
1606 */
1607
IPOnlyTestSig02(void)1608 static int IPOnlyTestSig02 (void)
1609 {
1610 DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1611 FAIL_IF(de_ctx == NULL);
1612 de_ctx->flags |= DE_QUIET;
1613
1614 Signature *s = SigInit(de_ctx,"alert tcp any any -> any 80 (sid:400001; rev:1;)");
1615 FAIL_IF(s == NULL);
1616
1617 FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
1618 SigFree(de_ctx, s);
1619 DetectEngineCtxFree(de_ctx);
1620 PASS;
1621 }
1622
1623 /**
1624 * \test check that we set dont set a Signature as IPOnly
1625 * because it has rule options appending a SigMatch like content, and pcre
1626 */
1627
IPOnlyTestSig03(void)1628 static int IPOnlyTestSig03 (void)
1629 {
1630 int result = 1;
1631 DetectEngineCtx *de_ctx;
1632 Signature *s=NULL;
1633
1634 de_ctx = DetectEngineCtxInit();
1635 if (de_ctx == NULL)
1636 goto end;
1637 de_ctx->flags |= DE_QUIET;
1638
1639 /* combination of pcre and content */
1640 s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (pcre and content) \"; content:\"php\"; pcre:\"/require(_once)?/i\"; classtype:misc-activity; sid:400001; rev:1;)");
1641 if (s == NULL) {
1642 goto end;
1643 }
1644 if(SignatureIsIPOnly(de_ctx, s))
1645 {
1646 printf("got a IPOnly signature (content): ");
1647 result=0;
1648 }
1649 SigFree(de_ctx, s);
1650
1651 /* content */
1652 s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (content) \"; content:\"match something\"; classtype:misc-activity; sid:400001; rev:1;)");
1653 if (s == NULL) {
1654 goto end;
1655 }
1656 if(SignatureIsIPOnly(de_ctx, s))
1657 {
1658 printf("got a IPOnly signature (content): ");
1659 result=0;
1660 }
1661 SigFree(de_ctx, s);
1662
1663 /* uricontent */
1664 s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (uricontent) \"; uricontent:\"match something\"; classtype:misc-activity; sid:400001; rev:1;)");
1665 if (s == NULL) {
1666 goto end;
1667 }
1668 if(SignatureIsIPOnly(de_ctx, s))
1669 {
1670 printf("got a IPOnly signature (uricontent): ");
1671 result=0;
1672 }
1673 SigFree(de_ctx, s);
1674
1675 /* pcre */
1676 s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (pcre) \"; pcre:\"/e?idps rule[sz]/i\"; classtype:misc-activity; sid:400001; rev:1;)");
1677 if (s == NULL) {
1678 goto end;
1679 }
1680 if(SignatureIsIPOnly(de_ctx, s))
1681 {
1682 printf("got a IPOnly signature (pcre): ");
1683 result=0;
1684 }
1685 SigFree(de_ctx, s);
1686
1687 /* flow */
1688 s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (flow) \"; flow:to_server; classtype:misc-activity; sid:400001; rev:1;)");
1689 if (s == NULL) {
1690 goto end;
1691 }
1692 if(SignatureIsIPOnly(de_ctx, s))
1693 {
1694 printf("got a IPOnly signature (flow): ");
1695 result=0;
1696 }
1697 SigFree(de_ctx, s);
1698
1699 /* dsize */
1700 s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (dsize) \"; dsize:100; classtype:misc-activity; sid:400001; rev:1;)");
1701 if (s == NULL) {
1702 goto end;
1703 }
1704 if(SignatureIsIPOnly(de_ctx, s))
1705 {
1706 printf("got a IPOnly signature (dsize): ");
1707 result=0;
1708 }
1709 SigFree(de_ctx, s);
1710
1711 /* flowbits */
1712 s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (flowbits) \"; flowbits:unset; classtype:misc-activity; sid:400001; rev:1;)");
1713 if (s == NULL) {
1714 goto end;
1715 }
1716 if(SignatureIsIPOnly(de_ctx, s))
1717 {
1718 printf("got a IPOnly signature (flowbits): ");
1719 result=0;
1720 }
1721 SigFree(de_ctx, s);
1722
1723 /* flowvar */
1724 s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (flowvar) \"; pcre:\"/(?<flow_var>.*)/i\"; flowvar:var,\"str\"; classtype:misc-activity; sid:400001; rev:1;)");
1725 if (s == NULL) {
1726 goto end;
1727 }
1728 if(SignatureIsIPOnly(de_ctx, s))
1729 {
1730 printf("got a IPOnly signature (flowvar): ");
1731 result=0;
1732 }
1733 SigFree(de_ctx, s);
1734
1735 /* pktvar */
1736 s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (pktvar) \"; pcre:\"/(?<pkt_var>.*)/i\"; pktvar:var,\"str\"; classtype:misc-activity; sid:400001; rev:1;)");
1737 if (s == NULL) {
1738 goto end;
1739 }
1740 if(SignatureIsIPOnly(de_ctx, s))
1741 {
1742 printf("got a IPOnly signature (pktvar): ");
1743 result=0;
1744 }
1745 SigFree(de_ctx, s);
1746
1747 end:
1748 if (de_ctx != NULL)
1749 DetectEngineCtxFree(de_ctx);
1750 return result;
1751 }
1752
1753 /**
1754 * \test
1755 */
IPOnlyTestSig04(void)1756 static int IPOnlyTestSig04 (void)
1757 {
1758 int result = 1;
1759
1760 IPOnlyCIDRItem *head = NULL;
1761 IPOnlyCIDRItem *new;
1762
1763 new = IPOnlyCIDRItemNew();
1764 new->netmask= 10;
1765
1766 head = IPOnlyCIDRItemInsert(head, new);
1767
1768 new = IPOnlyCIDRItemNew();
1769 new->netmask= 11;
1770
1771 head = IPOnlyCIDRItemInsert(head, new);
1772
1773 new = IPOnlyCIDRItemNew();
1774 new->netmask= 9;
1775
1776 head = IPOnlyCIDRItemInsert(head, new);
1777
1778 new = IPOnlyCIDRItemNew();
1779 new->netmask= 10;
1780
1781 head = IPOnlyCIDRItemInsert(head, new);
1782
1783 new = IPOnlyCIDRItemNew();
1784 new->netmask= 10;
1785
1786 head = IPOnlyCIDRItemInsert(head, new);
1787
1788 IPOnlyCIDRListPrint(head);
1789 new = head;
1790 if (new->netmask != 9) {
1791 result = 0;
1792 goto end;
1793 }
1794 new = new->next;
1795 if (new->netmask != 10) {
1796 result = 0;
1797 goto end;
1798 }
1799 new = new->next;
1800 if (new->netmask != 10) {
1801 result = 0;
1802 goto end;
1803 }
1804 new = new->next;
1805 if (new->netmask != 10) {
1806 result = 0;
1807 goto end;
1808 }
1809 new = new->next;
1810 if (new->netmask != 11) {
1811 result = 0;
1812 goto end;
1813 }
1814
1815 end:
1816 IPOnlyCIDRListFree(head);
1817 return result;
1818 }
1819
1820 /**
1821 * \test Test a set of ip only signatures making use a lot of
1822 * addresses for src and dst (all should match)
1823 */
IPOnlyTestSig05(void)1824 static int IPOnlyTestSig05(void)
1825 {
1826 int result = 0;
1827 uint8_t *buf = (uint8_t *)"Hi all!";
1828 uint16_t buflen = strlen((char *)buf);
1829
1830 uint8_t numpkts = 1;
1831 uint8_t numsigs = 7;
1832
1833 Packet *p[1];
1834
1835 p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1836
1837 const char *sigs[numsigs];
1838 sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
1839 sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
1840 sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1841 sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1842 sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1843 sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1844 sigs[6]= "alert tcp 192.168.1.0/24 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 7)\"; content:\"Hi all\";sid:7;)";
1845
1846 /* Sid numbers (we could extract them from the sig) */
1847 uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1848 uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
1849
1850 result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1851
1852 UTHFreePackets(p, numpkts);
1853
1854 return result;
1855 }
1856
1857 /**
1858 * \test Test a set of ip only signatures making use a lot of
1859 * addresses for src and dst (none should match)
1860 */
IPOnlyTestSig06(void)1861 static int IPOnlyTestSig06(void)
1862 {
1863 int result = 0;
1864 uint8_t *buf = (uint8_t *)"Hi all!";
1865 uint16_t buflen = strlen((char *)buf);
1866
1867 uint8_t numpkts = 1;
1868 uint8_t numsigs = 7;
1869
1870 Packet *p[1];
1871
1872 p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "80.58.0.33", "195.235.113.3");
1873
1874 const char *sigs[numsigs];
1875 sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
1876 sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
1877 sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1878 sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1879 sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1880 sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1881 sigs[6]= "alert tcp 192.168.1.0/24 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 7)\"; content:\"Hi all\";sid:7;)";
1882
1883 /* Sid numbers (we could extract them from the sig) */
1884 uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1885 uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
1886
1887 result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1888
1889 UTHFreePackets(p, numpkts);
1890
1891 return result;
1892 }
1893
1894 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
1895 * which is why these unittests fail. When we fix 608, we need to renable
1896 * these sigs */
1897 #if 0
1898 /**
1899 * \test Test a set of ip only signatures making use a lot of
1900 * addresses for src and dst (all should match)
1901 */
1902 static int IPOnlyTestSig07(void)
1903 {
1904 int result = 0;
1905 uint8_t *buf = (uint8_t *)"Hi all!";
1906 uint16_t buflen = strlen((char *)buf);
1907
1908 uint8_t numpkts = 1;
1909 uint8_t numsigs = 7;
1910
1911 Packet *p[1];
1912
1913 p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1914
1915 char *sigs[numsigs];
1916 sigs[0]= "alert tcp 192.168.1.5 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 1)\"; sid:1;)";
1917 sigs[1]= "alert tcp [192.168.1.2,192.168.1.5,192.168.1.4] any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 2)\"; sid:2;)";
1918 sigs[2]= "alert tcp [192.168.1.0/24,!192.168.1.1] any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1919 sigs[3]= "alert tcp [192.0.0.0/8,!192.168.0.0/16,192.168.1.0/24,!192.168.1.1] any -> [192.168.1.0/24,!192.168.1.5] any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1920 sigs[4]= "alert tcp any any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1921 sigs[5]= "alert tcp any any -> [192.168.0.0/16,!192.168.1.0/24,192.168.1.1] any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1922 sigs[6]= "alert tcp [78.129.202.0/24,192.168.1.5,78.129.205.64,78.129.214.103,78.129.223.19,78.129.233.17,78.137.168.33,78.140.132.11,78.140.133.15,78.140.138.105,78.140.139.105,78.140.141.107,78.140.141.114,78.140.143.103,78.140.143.13,78.140.145.144,78.140.170.164,78.140.23.18,78.143.16.7,78.143.46.124,78.157.129.71] any -> 192.168.1.1 any (msg:\"ET RBN Known Russian Business Network IP TCP - BLOCKING (246)\"; sid:7;)"; /* real sid:"2407490" */
1923
1924 /* Sid numbers (we could extract them from the sig) */
1925 uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1926 uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
1927
1928 result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1929
1930 UTHFreePackets(p, numpkts);
1931
1932 return result;
1933 }
1934 #endif
1935
1936 /**
1937 * \test Test a set of ip only signatures making use a lot of
1938 * addresses for src and dst (none should match)
1939 */
IPOnlyTestSig08(void)1940 static int IPOnlyTestSig08(void)
1941 {
1942 int result = 0;
1943 uint8_t *buf = (uint8_t *)"Hi all!";
1944 uint16_t buflen = strlen((char *)buf);
1945
1946 uint8_t numpkts = 1;
1947 uint8_t numsigs = 7;
1948
1949 Packet *p[1];
1950
1951 p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"192.168.1.1","192.168.1.5");
1952
1953 const char *sigs[numsigs];
1954 sigs[0]= "alert tcp 192.168.1.5 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 1)\"; sid:1;)";
1955 sigs[1]= "alert tcp [192.168.1.2,192.168.1.5,192.168.1.4] any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 2)\"; sid:2;)";
1956 sigs[2]= "alert tcp [192.168.1.0/24,!192.168.1.1] any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1957 sigs[3]= "alert tcp [192.0.0.0/8,!192.168.0.0/16,192.168.1.0/24,!192.168.1.1] any -> [192.168.1.0/24,!192.168.1.5] any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1958 sigs[4]= "alert tcp any any -> !192.168.1.5 any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1959 sigs[5]= "alert tcp any any -> [192.168.0.0/16,!192.168.1.0/24,192.168.1.1] any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1960 sigs[6]= "alert tcp [78.129.202.0/24,192.168.1.5,78.129.205.64,78.129.214.103,78.129.223.19,78.129.233.17,78.137.168.33,78.140.132.11,78.140.133.15,78.140.138.105,78.140.139.105,78.140.141.107,78.140.141.114,78.140.143.103,78.140.143.13,78.140.145.144,78.140.170.164,78.140.23.18,78.143.16.7,78.143.46.124,78.157.129.71] any -> 192.168.1.1 any (msg:\"ET RBN Known Russian Business Network IP TCP - BLOCKING (246)\"; sid:7;)"; /* real sid:"2407490" */
1961
1962 /* Sid numbers (we could extract them from the sig) */
1963 uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1964 uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
1965
1966 result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1967
1968 UTHFreePackets(p, numpkts);
1969
1970 return result;
1971 }
1972
1973 /**
1974 * \test Test a set of ip only signatures making use a lot of
1975 * addresses for src and dst (all should match)
1976 */
IPOnlyTestSig09(void)1977 static int IPOnlyTestSig09(void)
1978 {
1979 int result = 0;
1980 uint8_t *buf = (uint8_t *)"Hi all!";
1981 uint16_t buflen = strlen((char *)buf);
1982
1983 uint8_t numpkts = 1;
1984 uint8_t numsigs = 7;
1985
1986 Packet *p[1];
1987
1988 p[0] = UTHBuildPacketIPV6SrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565", "3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562");
1989
1990 const char *sigs[numsigs];
1991 sigs[0]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
1992 sigs[1]= "alert tcp any any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
1993 sigs[2]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1994 sigs[3]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:0/96 any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1995 sigs[4]= "alert tcp 3FFE:FFFF:7654:FEDA:0:0:0:0/64 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1996 sigs[5]= "alert tcp any any -> 3FFE:FFFF:7654:FEDA:0:0:0:0/64 any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1997 sigs[6]= "alert tcp 3FFE:FFFF:7654:FEDA:0:0:0:0/64 any -> 3FFE:FFFF:7654:FEDA:0:0:0:0/64 any (msg:\"Testing src/dst ip (sid 7)\"; content:\"Hi all\";sid:7;)";
1998
1999 /* Sid numbers (we could extract them from the sig) */
2000 uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2001 uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
2002
2003 result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2004
2005 UTHFreePackets(p, numpkts);
2006
2007 return result;
2008 }
2009
2010 /**
2011 * \test Test a set of ip only signatures making use a lot of
2012 * addresses for src and dst (none should match)
2013 */
IPOnlyTestSig10(void)2014 static int IPOnlyTestSig10(void)
2015 {
2016 int result = 0;
2017 uint8_t *buf = (uint8_t *)"Hi all!";
2018 uint16_t buflen = strlen((char *)buf);
2019
2020 uint8_t numpkts = 1;
2021 uint8_t numsigs = 7;
2022
2023 Packet *p[1];
2024
2025 p[0] = UTHBuildPacketIPV6SrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562", "3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565");
2026
2027 const char *sigs[numsigs];
2028 sigs[0]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2029 sigs[1]= "alert tcp any any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2030 sigs[2]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
2031 sigs[3]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> !3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562/96 any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
2032 sigs[4]= "alert tcp !3FFE:FFFF:7654:FEDA:0:0:0:0/64 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
2033 sigs[5]= "alert tcp any any -> !3FFE:FFFF:7654:FEDA:0:0:0:0/64 any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
2034 sigs[6]= "alert tcp 3FFE:FFFF:7654:FEDA:0:0:0:0/64 any -> 3FFE:FFFF:7654:FEDB:0:0:0:0/64 any (msg:\"Testing src/dst ip (sid 7)\"; content:\"Hi all\";sid:7;)";
2035
2036 /* Sid numbers (we could extract them from the sig) */
2037 uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2038 uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
2039
2040 result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2041
2042 UTHFreePackets(p, numpkts);
2043
2044 return result;
2045 }
2046
2047 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
2048 * which is why these unittests fail. When we fix 608, we need to renable
2049 * these sigs */
2050 #if 0
2051 /**
2052 * \test Test a set of ip only signatures making use a lot of
2053 * addresses for src and dst (all should match) with ipv4 and ipv6 mixed
2054 */
2055 static int IPOnlyTestSig11(void)
2056 {
2057 int result = 0;
2058 uint8_t *buf = (uint8_t *)"Hi all!";
2059 uint16_t buflen = strlen((char *)buf);
2060
2061 uint8_t numpkts = 2;
2062 uint8_t numsigs = 7;
2063
2064 Packet *p[2];
2065
2066 p[0] = UTHBuildPacketIPV6SrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565", "3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562");
2067 p[1] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"192.168.1.1","192.168.1.5");
2068
2069 char *sigs[numsigs];
2070 sigs[0]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565,192.168.1.1 any -> 3FFE:FFFF:7654:FEDA:0:0:0:0/64,192.168.1.5 any (msg:\"Testing src/dst ip (sid 1)\"; sid:1;)";
2071 sigs[1]= "alert tcp [192.168.1.1,3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565,192.168.1.4,192.168.1.5,!192.168.1.0/24] any -> [3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.0/24] any (msg:\"Testing src/dst ip (sid 2)\"; sid:2;)";
2072 sigs[2]= "alert tcp [3FFE:FFFF:7654:FEDA:0:0:0:0/64,!3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.1] any -> [3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.5] any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
2073 sigs[3]= "alert tcp [3FFE:FFFF:0:0:0:0:0:0/32,!3FFE:FFFF:7654:FEDA:0:0:0:0/64,3FFE:FFFF:7654:FEDA:0:0:0:0/64,!3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.1] any -> [3FFE:FFFF:7654:FEDA:0:0:0:0/64,192.168.1.0/24,!3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565] any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
2074 sigs[4]= "alert tcp any any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
2075 sigs[5]= "alert tcp any any -> [3FFE:FFFF:7654:FEDA:0:0:0:0/64,!3FFE:FFFF:7654:FEDA:0:0:0:0/64,3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.5] any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
2076 sigs[6]= "alert tcp [78.129.202.0/24,3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565,192.168.1.1,78.129.205.64,78.129.214.103,78.129.223.19,78.129.233.17,78.137.168.33,78.140.132.11,78.140.133.15,78.140.138.105,78.140.139.105,78.140.141.107,78.140.141.114,78.140.143.103,78.140.143.13,78.140.145.144,78.140.170.164,78.140.23.18,78.143.16.7,78.143.46.124,78.157.129.71] any -> [3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.0.0.0/8] any (msg:\"ET RBN Known Russian Business Network IP TCP - BLOCKING (246)\"; sid:7;)"; /* real sid:"2407490" */
2077
2078 /* Sid numbers (we could extract them from the sig) */
2079 uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2080 uint32_t results[2][7] = {{ 1, 1, 1, 1, 1, 1, 1}, { 1, 1, 1, 1, 1, 1, 1}};
2081
2082 result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2083
2084 UTHFreePackets(p, numpkts);
2085
2086 return result;
2087 }
2088 #endif
2089
2090 /**
2091 * \test Test a set of ip only signatures making use a lot of
2092 * addresses for src and dst (none should match) with ipv4 and ipv6 mixed
2093 */
IPOnlyTestSig12(void)2094 static int IPOnlyTestSig12(void)
2095 {
2096 int result = 0;
2097 uint8_t *buf = (uint8_t *)"Hi all!";
2098 uint16_t buflen = strlen((char *)buf);
2099
2100 uint8_t numpkts = 2;
2101 uint8_t numsigs = 7;
2102
2103 Packet *p[2];
2104
2105 p[0] = UTHBuildPacketIPV6SrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"3FBE:FFFF:7654:FEDA:1245:BA98:3210:4562","3FBE:FFFF:7654:FEDA:1245:BA98:3210:4565");
2106 p[1] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"195.85.1.1","80.198.1.5");
2107
2108 const char *sigs[numsigs];
2109 sigs[0]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565,192.168.1.1 any -> 3FFE:FFFF:7654:FEDA:0:0:0:0/64,192.168.1.5 any (msg:\"Testing src/dst ip (sid 1)\"; sid:1;)";
2110 sigs[1]= "alert tcp [192.168.1.1,3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565,192.168.1.4,192.168.1.5,!192.168.1.0/24] any -> [3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.0/24] any (msg:\"Testing src/dst ip (sid 2)\"; sid:2;)";
2111 sigs[2]= "alert tcp [3FFE:FFFF:7654:FEDA:0:0:0:0/64,!3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.1] any -> [3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.5] any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
2112 sigs[3]= "alert tcp [3FFE:FFFF:0:0:0:0:0:0/32,!3FFE:FFFF:7654:FEDA:0:0:0:0/64,3FFE:FFFF:7654:FEDA:0:0:0:0/64,!3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.1] any -> [3FFE:FFFF:7654:FEDA:0:0:0:0/64,192.168.1.0/24,!3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565] any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
2113 sigs[4]= "alert tcp any any -> [!3FBE:FFFF:7654:FEDA:1245:BA98:3210:4565,!80.198.1.5] any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
2114 sigs[5]= "alert tcp any any -> [3FFE:FFFF:7654:FEDA:0:0:0:0/64,!3FFE:FFFF:7654:FEDA:0:0:0:0/64,3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.5] any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
2115 sigs[6]= "alert tcp [78.129.202.0/24,3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565,192.168.1.1,78.129.205.64,78.129.214.103,78.129.223.19,78.129.233.17,78.137.168.33,78.140.132.11,78.140.133.15,78.140.138.105,78.140.139.105,78.140.141.107,78.140.141.114,78.140.143.103,78.140.143.13,78.140.145.144,78.140.170.164,78.140.23.18,78.143.16.7,78.143.46.124,78.157.129.71] any -> [3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.0.0.0/8] any (msg:\"ET RBN Known Russian Business Network IP TCP - BLOCKING (246)\"; sid:7;)"; /* real sid:"2407490" */
2116
2117 /* Sid numbers (we could extract them from the sig) */
2118 uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2119 uint32_t results[2][7] = {{ 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0}};
2120
2121 result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2122
2123 UTHFreePackets(p, numpkts);
2124
2125 return result;
2126 }
2127
IPOnlyTestSig13(void)2128 static int IPOnlyTestSig13(void)
2129 {
2130 DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2131 FAIL_IF(de_ctx == NULL);
2132 de_ctx->flags |= DE_QUIET;
2133
2134 Signature *s = SigInit(de_ctx,
2135 "alert tcp any any -> any any (msg:\"Test flowbits ip only\"; "
2136 "flowbits:set,myflow1; sid:1; rev:1;)");
2137 FAIL_IF(s == NULL);
2138
2139 FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
2140 SigFree(de_ctx, s);
2141 DetectEngineCtxFree(de_ctx);
2142 PASS;
2143 }
2144
IPOnlyTestSig14(void)2145 static int IPOnlyTestSig14(void)
2146 {
2147 DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2148 FAIL_IF(de_ctx == NULL);
2149 de_ctx->flags |= DE_QUIET;
2150
2151 Signature *s = SigInit(de_ctx,
2152 "alert tcp any any -> any any (msg:\"Test flowbits ip only\"; "
2153 "flowbits:set,myflow1; flowbits:isset,myflow2; sid:1; rev:1;)");
2154 FAIL_IF(s == NULL);
2155
2156 FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 1);
2157 SigFree(de_ctx, s);
2158 DetectEngineCtxFree(de_ctx);
2159 PASS;
2160 }
2161
IPOnlyTestSig15(void)2162 static int IPOnlyTestSig15(void)
2163 {
2164 int result = 0;
2165 uint8_t *buf = (uint8_t *)"Hi all!";
2166 uint16_t buflen = strlen((char *)buf);
2167
2168 uint8_t numpkts = 1;
2169 uint8_t numsigs = 7;
2170
2171 Packet *p[1];
2172 Flow f;
2173 GenericVar flowvar;
2174 memset(&f, 0, sizeof(Flow));
2175 memset(&flowvar, 0, sizeof(GenericVar));
2176 FLOW_INITIALIZE(&f);
2177
2178 p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
2179
2180 p[0]->flow = &f;
2181 p[0]->flow->flowvar = &flowvar;
2182 p[0]->flags |= PKT_HAS_FLOW;
2183 p[0]->flowflags |= FLOW_PKT_TOSERVER;
2184
2185 const char *sigs[numsigs];
2186 sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; "
2187 "flowbits:set,one; sid:1;)";
2188 sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; "
2189 "flowbits:set,two; sid:2;)";
2190 sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; "
2191 "flowbits:set,three; sid:3;)";
2192 sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; "
2193 "flowbits:set,four; sid:4;)";
2194 sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; "
2195 "flowbits:set,five; sid:5;)";
2196 sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; "
2197 "flowbits:set,six; sid:6;)";
2198 sigs[6]= "alert tcp 192.168.1.0/24 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 7)\"; "
2199 "flowbits:set,seven; content:\"Hi all\"; sid:7;)";
2200
2201 /* Sid numbers (we could extract them from the sig) */
2202 uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2203 uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
2204
2205 result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2206
2207 UTHFreePackets(p, numpkts);
2208
2209 FLOW_DESTROY(&f);
2210 return result;
2211 }
2212
2213 /**
2214 * \brief Unittest to show #599. We fail to match if we have negated addresses.
2215 */
IPOnlyTestSig16(void)2216 static int IPOnlyTestSig16(void)
2217 {
2218 int result = 0;
2219 uint8_t *buf = (uint8_t *)"Hi all!";
2220 uint16_t buflen = strlen((char *)buf);
2221
2222 uint8_t numpkts = 1;
2223 uint8_t numsigs = 2;
2224
2225 Packet *p[1];
2226
2227 p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "100.100.0.0", "50.0.0.0");
2228
2229 const char *sigs[numsigs];
2230 sigs[0]= "alert tcp !100.100.0.1 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2231 sigs[1]= "alert tcp any any -> !50.0.0.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2232
2233 /* Sid numbers (we could extract them from the sig) */
2234 uint32_t sid[2] = { 1, 2};
2235 uint32_t results[2] = { 1, 1};
2236
2237 result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2238
2239 UTHFreePackets(p, numpkts);
2240
2241 return result;
2242 }
2243
2244 /**
2245 * \brief Unittest to show #611. Ports on portless protocols.
2246 */
IPOnlyTestSig17(void)2247 static int IPOnlyTestSig17(void)
2248 {
2249 int result = 0;
2250 uint8_t *buf = (uint8_t *)"Hi all!";
2251 uint16_t buflen = strlen((char *)buf);
2252
2253 uint8_t numpkts = 1;
2254 uint8_t numsigs = 2;
2255
2256 Packet *p[1];
2257
2258 p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_ICMP, "100.100.0.0", "50.0.0.0");
2259
2260 const char *sigs[numsigs];
2261 sigs[0]= "alert ip 100.100.0.0 80 -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2262 sigs[1]= "alert ip any any -> 50.0.0.0 123 (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2263
2264 uint32_t sid[2] = { 1, 2};
2265 uint32_t results[2] = { 0, 0}; /* neither should match */
2266
2267 result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2268
2269 UTHFreePackets(p, numpkts);
2270
2271 return result;
2272 }
2273
2274 /**
2275 * \brief Unittest to show #3568 -- IP address range handling
2276 */
IPOnlyTestSig18(void)2277 static int IPOnlyTestSig18(void)
2278 {
2279 int result = 0;
2280 uint8_t *buf = (uint8_t *)"Hi all!";
2281 uint16_t buflen = strlen((char *)buf);
2282
2283 uint8_t numpkts = 4;
2284 uint8_t numsigs = 4;
2285
2286 Packet *p[4];
2287
2288 p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "10.10.10.1", "50.0.0.1");
2289 p[1] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "220.10.10.1", "5.0.0.1");
2290 p[2] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "0.0.0.1", "50.0.0.1");
2291 p[3] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "255.255.255.254", "5.0.0.1");
2292
2293 const char *sigs[numsigs];
2294 // really many IP addresses
2295 sigs[0]= "alert ip 1.2.3.4-219.6.7.8 any -> any any (sid:1;)";
2296 sigs[1]= "alert ip 51.2.3.4-253.1.2.3 any -> any any (sid:2;)";
2297 sigs[2]= "alert ip 0.0.0.0-50.0.0.2 any -> any any (sid:3;)";
2298 sigs[3]= "alert ip 50.0.0.0-255.255.255.255 any -> any any (sid:4;)";
2299
2300 uint32_t sid[4] = { 1, 2, 3, 4, };
2301 uint32_t results[4][4] = {
2302 { 1, 0, 1, 0, }, { 0, 1, 0, 1}, { 0, 0, 1, 0 }, { 0, 0, 0, 1}};
2303
2304 result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2305
2306 UTHFreePackets(p, numpkts);
2307
2308 FAIL_IF(result != 1);
2309
2310 PASS;
2311 }
2312
2313 #endif /* UNITTESTS */
2314
IPOnlyRegisterTests(void)2315 void IPOnlyRegisterTests(void)
2316 {
2317 #ifdef UNITTESTS
2318 UtRegisterTest("IPOnlyTestSig01", IPOnlyTestSig01);
2319 UtRegisterTest("IPOnlyTestSig02", IPOnlyTestSig02);
2320 UtRegisterTest("IPOnlyTestSig03", IPOnlyTestSig03);
2321 UtRegisterTest("IPOnlyTestSig04", IPOnlyTestSig04);
2322
2323 UtRegisterTest("IPOnlyTestSig05", IPOnlyTestSig05);
2324 UtRegisterTest("IPOnlyTestSig06", IPOnlyTestSig06);
2325 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
2326 * which is why these unittests fail. When we fix 608, we need to renable
2327 * these sigs */
2328 #if 0
2329 UtRegisterTest("IPOnlyTestSig07", IPOnlyTestSig07, 1);
2330 #endif
2331 UtRegisterTest("IPOnlyTestSig08", IPOnlyTestSig08);
2332
2333 UtRegisterTest("IPOnlyTestSig09", IPOnlyTestSig09);
2334 UtRegisterTest("IPOnlyTestSig10", IPOnlyTestSig10);
2335 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
2336 * which is why these unittests fail. When we fix 608, we need to renable
2337 * these sigs */
2338 #if 0
2339 UtRegisterTest("IPOnlyTestSig11", IPOnlyTestSig11, 1);
2340 #endif
2341 UtRegisterTest("IPOnlyTestSig12", IPOnlyTestSig12);
2342 UtRegisterTest("IPOnlyTestSig13", IPOnlyTestSig13);
2343 UtRegisterTest("IPOnlyTestSig14", IPOnlyTestSig14);
2344 UtRegisterTest("IPOnlyTestSig15", IPOnlyTestSig15);
2345 UtRegisterTest("IPOnlyTestSig16", IPOnlyTestSig16);
2346
2347 UtRegisterTest("IPOnlyTestSig17", IPOnlyTestSig17);
2348 UtRegisterTest("IPOnlyTestSig18", IPOnlyTestSig18);
2349 #endif
2350
2351 return;
2352 }
2353
2354