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