Coverage Report

Created: 2021-11-03 07:11

/src/suricata/src/detect-engine-iponly.c
Line
Count
Source (jump to first uncovered line)
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
 */
71
static IPOnlyCIDRItem *IPOnlyCIDRItemNew(void)
72
73.4k
{
73
73.4k
    SCEnter();
74
73.4k
    IPOnlyCIDRItem *item = NULL;
75
76
73.4k
    item = SCMalloc(sizeof(IPOnlyCIDRItem));
77
73.4k
    if (unlikely(item == NULL))
78
0
        SCReturnPtr(NULL, "IPOnlyCIDRItem");
79
73.4k
    memset(item, 0, sizeof(IPOnlyCIDRItem));
80
81
73.4k
    SCReturnPtr(item, "IPOnlyCIDRItem");
82
73.4k
}
83
84
static uint8_t IPOnlyCIDRItemCompare(IPOnlyCIDRItem *head,
85
                                         IPOnlyCIDRItem *item)
86
53.8k
{
87
53.8k
    uint8_t i = 0;
88
129k
    for (; i < head->netmask / 32 || i < 1; i++) {
89
89.6k
        if (item->ip[i] < head->ip[i])
90
        //if (*(uint8_t *)(item->ip + i) < *(uint8_t *)(head->ip + i))
91
13.9k
            return 1;
92
89.6k
    }
93
39.9k
    return 0;
94
53.8k
}
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
 */
112
static int IPOnlyCIDRItemParseSingle(IPOnlyCIDRItem **pdd, const char *str)
113
67.7k
{
114
67.7k
    char buf[256] = "";
115
67.7k
    char *ip = NULL, *ip2 = NULL;
116
67.7k
    char *mask = NULL;
117
67.7k
    int r = 0;
118
67.7k
    IPOnlyCIDRItem *dd = *pdd;
119
120
68.4k
    while (*str != '\0' && *str == ' ')
121
730
        str++;
122
123
67.7k
    SCLogDebug("str %s", str);
124
67.7k
    strlcpy(buf, str, sizeof(buf));
125
67.7k
    ip = buf;
126
127
    /* first handle 'any' */
128
67.7k
    if (strcasecmp(str, "any") == 0) {
129
        /* if any, insert 0.0.0.0/0 and ::/0 as well */
130
6.26k
        SCLogDebug("adding 0.0.0.0/0 and ::/0 as we\'re handling \'any\'");
131
132
6.26k
        IPOnlyCIDRItemParseSingle(&dd, "0.0.0.0/0");
133
6.26k
        BUG_ON(dd->family == 0);
134
135
0
        dd->next = IPOnlyCIDRItemNew();
136
6.26k
        if (dd->next == NULL)
137
0
            goto error;
138
139
6.26k
        IPOnlyCIDRItemParseSingle(&dd->next, "::/0");
140
6.26k
        BUG_ON(dd->family == 0);
141
142
6.26k
        SCLogDebug("address is \'any\'");
143
6.26k
        return 0;
144
6.26k
    }
145
146
    /* handle the negation case */
147
61.4k
    if (ip[0] == '!') {
148
201
        dd->negated = (dd->negated)? 0 : 1;
149
201
        ip++;
150
201
    }
151
152
    /* see if the address is an ipv4 or ipv6 address */
153
61.4k
    if ((strchr(str, ':')) == NULL) {
154
        /* IPv4 Address */
155
14.9k
        struct in_addr in;
156
157
14.9k
        dd->family = AF_INET;
158
159
14.9k
        if ((mask = strchr(ip, '/')) != NULL) {
160
            /* 1.2.3.4/xxx format (either dotted or cidr notation */
161
13.6k
            ip[mask - ip] = '\0';
162
13.6k
            mask++;
163
13.6k
            uint32_t netmask = 0;
164
13.6k
            size_t u = 0;
165
166
13.6k
            if ((strchr (mask, '.')) == NULL) {
167
                /* 1.2.3.4/24 format */
168
169
27.2k
                for (u = 0; u < strlen(mask); u++) {
170
13.7k
                    if(!isdigit((unsigned char)mask[u]))
171
0
                        goto error;
172
13.7k
                }
173
174
13.5k
                int cidr;
175
13.5k
                if (StringParseI32RangeCheck(&cidr, 10, 0, (const char *)mask, 0, 32) < 0)
176
3
                    goto error;
177
178
13.5k
                dd->netmask = cidr;
179
13.5k
            } else {
180
                /* 1.2.3.4/255.255.255.0 format */
181
103
                r = inet_pton(AF_INET, mask, &in);
182
103
                if (r <= 0)
183
2
                    goto error;
184
185
101
                netmask = in.s_addr;
186
187
101
                if (netmask != 0) {
188
                    /* Extract cidr netmask */
189
361
                    while ((0x01 & netmask) == 0) {
190
261
                        dd->netmask++;
191
261
                        netmask = netmask >> 1;
192
261
                    }
193
100
                    dd->netmask = 32 - dd->netmask;
194
100
                }
195
101
            }
196
197
13.6k
            r = inet_pton(AF_INET, ip, &in);
198
13.6k
            if (r <= 0)
199
8
                goto error;
200
201
13.6k
            dd->ip[0] = in.s_addr;
202
203
13.6k
        } else if ((ip2 = strchr(ip, '-')) != NULL)  {
204
            /* 1.2.3.4-1.2.3.6 range format */
205
638
            ip[ip2 - ip] = '\0';
206
638
            ip2++;
207
208
638
            uint32_t first, last;
209
210
638
            r = inet_pton(AF_INET, ip, &in);
211
638
            if (r <= 0)
212
10
                goto error;
213
628
            first = SCNtohl(in.s_addr);
214
215
628
            r = inet_pton(AF_INET, ip2, &in);
216
628
            if (r <= 0)
217
0
                goto error;
218
628
            last = SCNtohl(in.s_addr);
219
220
            /* a > b is illegal, a = b is ok */
221
628
            if (first > last)
222
0
                goto error;
223
224
628
            SCLogDebug("Creating CIDR range for [%s - %s]", ip, ip2);
225
628
            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
3.90k
            while (dd->netmask > 0 &&
232
3.90k
                   (first & (1UL << (32-dd->netmask))) == 0 &&
233
3.90k
                   first + (1UL << (32-(dd->netmask-1))) - 1 <= last) {
234
3.28k
                dd->netmask--;
235
3.28k
            }
236
628
            dd->ip[0] = htonl(first);
237
628
            first += 1UL << (32-dd->netmask);
238
            //case whatever-255.255.255.255 looping to 0.0.0.0/0
239
12.6k
            while ( first <= last && first != 0 ) {
240
12.0k
                IPOnlyCIDRItem *new = IPOnlyCIDRItemNew();
241
12.0k
                if (new == NULL)
242
0
                    goto error;
243
12.0k
                new->negated = dd->negated;
244
12.0k
                new->family= dd->family;
245
12.0k
                new->netmask = 32;
246
183k
                while (new->netmask > 0 &&
247
183k
                       (first & (1UL << (32-new->netmask))) == 0 &&
248
183k
                       first + (1UL << (32-(new->netmask-1))) - 1 <= last) {
249
171k
                    new->netmask--;
250
171k
                }
251
12.0k
                new->ip[0] = htonl(first);
252
12.0k
                first += 1UL << (32-new->netmask);
253
12.0k
                dd = IPOnlyCIDRItemInsert(dd, new);
254
12.0k
            }
255
            //update head of list
256
628
            *pdd = dd;
257
258
637
        } else {
259
            /* 1.2.3.4 format */
260
637
            r = inet_pton(AF_INET, ip, &in);
261
637
            if (r <= 0)
262
318
                goto error;
263
264
            /* single host */
265
319
            dd->ip[0] = in.s_addr;
266
319
            dd->netmask = 32;
267
319
        }
268
46.4k
    } else {
269
        /* IPv6 Address */
270
46.4k
        struct in6_addr in6;
271
46.4k
        uint32_t ip6addr[4];
272
273
46.4k
        dd->family = AF_INET6;
274
275
46.4k
        if ((mask = strchr(ip, '/')) != NULL)  {
276
17.5k
            mask[0] = '\0';
277
17.5k
            mask++;
278
279
17.5k
            r = inet_pton(AF_INET6, ip, &in6);
280
17.5k
            if (r <= 0)
281
224
                goto error;
282
283
            /* Format is cidr val */
284
17.3k
            if (StringParseU8RangeCheck(&dd->netmask, 10, 0,
285
17.3k
                                        (const char *)mask, 0, 128) < 0) {
286
1.18k
                goto error;
287
1.18k
            }
288
289
16.1k
            memcpy(dd->ip, &in6.s6_addr, sizeof(ip6addr));
290
28.9k
        } else {
291
28.9k
            r = inet_pton(AF_INET6, ip, &in6);
292
28.9k
            if (r <= 0)
293
42
                goto error;
294
295
28.8k
            memcpy(dd->ip, &in6.s6_addr, sizeof(dd->ip));
296
28.8k
            dd->netmask = 128;
297
28.8k
        }
298
299
46.4k
    }
300
301
59.6k
    BUG_ON(dd->family == 0);
302
0
    return 0;
303
304
1.79k
error:
305
1.79k
    return -1;
306
61.4k
}
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
 */
320
static int IPOnlyCIDRItemSetup(IPOnlyCIDRItem **gh, char *s)
321
55.1k
{
322
55.1k
    SCLogDebug("gh %p, s %s", *gh, s);
323
324
    /* parse the address */
325
55.1k
    if (IPOnlyCIDRItemParseSingle(gh, s) == -1) {
326
1.79k
        SCLogError(SC_ERR_ADDRESS_ENGINE_GENERIC,
327
1.79k
                   "address parsing error \"%s\"", s);
328
1.79k
        goto error;
329
1.79k
    }
330
331
53.3k
    return 0;
332
333
1.79k
error:
334
1.79k
    return -1;
335
55.1k
}
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
 */
347
static IPOnlyCIDRItem *IPOnlyCIDRItemInsertReal(IPOnlyCIDRItem *head,
348
                                         IPOnlyCIDRItem *item)
349
74.0k
{
350
74.0k
    IPOnlyCIDRItem *it, *prev = NULL;
351
352
74.0k
    if (item == NULL)
353
0
        return head;
354
355
    /* Compare with the head */
356
74.0k
    if (item->netmask < head->netmask || (item->netmask == head->netmask && IPOnlyCIDRItemCompare(head, item))) {
357
27.3k
        item->next = head;
358
27.3k
        return item;
359
27.3k
    }
360
361
46.7k
    if (item->netmask == head->netmask && !IPOnlyCIDRItemCompare(head, item)) {
362
19.9k
        item->next = head->next;
363
19.9k
        head->next = item;
364
19.9k
        return head;
365
19.9k
    }
366
367
26.8k
    for (prev = it = head;
368
3.68M
         it != NULL && it->netmask < item->netmask;
369
3.65M
         it = it->next)
370
3.65M
        prev = it;
371
372
26.8k
    if (it == NULL) {
373
2.43k
        prev->next = item;
374
2.43k
        item->next = NULL;
375
24.3k
    } else {
376
24.3k
        item->next = it;
377
24.3k
        prev->next = item;
378
24.3k
    }
379
380
26.8k
    return head;
381
46.7k
}
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
 */
392
static IPOnlyCIDRItem *IPOnlyCIDRItemInsert(IPOnlyCIDRItem *head,
393
                                     IPOnlyCIDRItem *item)
394
76.9k
{
395
76.9k
    IPOnlyCIDRItem *it, *prev = NULL;
396
397
    /* The first element */
398
76.9k
    if (head == NULL) {
399
24.7k
        SCLogDebug("Head is NULL to insert item (%p)",item);
400
24.7k
        return item;
401
24.7k
    }
402
403
52.1k
    if (item == NULL) {
404
0
        SCLogDebug("Item is NULL");
405
0
        return head;
406
0
    }
407
408
52.1k
    SCLogDebug("Inserting item(%p)->netmask %u head %p", item, item->netmask, head);
409
410
52.1k
    prev = item;
411
126k
    while (prev != NULL) {
412
74.0k
        it = prev->next;
413
414
        /* Separate from the item list */
415
74.0k
        prev->next = NULL;
416
417
        //SCLogDebug("Before:");
418
        //IPOnlyCIDRListPrint(head);
419
74.0k
        head = IPOnlyCIDRItemInsertReal(head, prev);
420
        //SCLogDebug("After:");
421
        //IPOnlyCIDRListPrint(head);
422
74.0k
        prev = it;
423
74.0k
    }
424
425
52.1k
    return head;
426
52.1k
}
427
428
/**
429
 * \brief This function free a IPOnlyCIDRItem list
430
 * \param tmphead Pointer to the list
431
 */
432
void IPOnlyCIDRListFree(IPOnlyCIDRItem *tmphead)
433
14.7k
{
434
14.7k
    SCEnter();
435
14.7k
    uint32_t i = 0;
436
437
14.7k
    IPOnlyCIDRItem *it, *next = NULL;
438
439
14.7k
    if (tmphead == NULL) {
440
0
        SCLogDebug("temphead is NULL");
441
0
        return;
442
0
    }
443
444
14.7k
    it = tmphead;
445
14.7k
    next = it->next;
446
447
86.2k
    while (it != NULL) {
448
71.5k
        i++;
449
71.5k
        SCFree(it);
450
71.5k
        SCLogDebug("Item(%p) %"PRIu32" removed", it, i);
451
71.5k
        it = next;
452
453
71.5k
        if (next != NULL)
454
56.8k
            next = next->next;
455
71.5k
    }
456
14.7k
    SCReturn;
457
14.7k
}
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
 */
466
static void IPOnlyCIDRListSetSigNum(IPOnlyCIDRItem *tmphead, SigIntId i)
467
572
{
468
2.48k
    while (tmphead != NULL) {
469
1.91k
        tmphead->signum = i;
470
1.91k
        tmphead = tmphead->next;
471
1.91k
    }
472
572
}
473
474
#ifdef UNITTESTS
475
/**
476
 * \brief This function print a IPOnlyCIDRItem list
477
 * \param tmphead Pointer to the head of IPOnlyCIDRItems list
478
 */
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
 */
500
static void SigNumArrayPrint(void *tmp)
501
0
{
502
0
    SigNumArray *sna = (SigNumArray *)tmp;
503
0
    uint32_t u;
504
505
0
    for (u = 0; u < sna->size; u++) {
506
0
        uint8_t bitarray = sna->array[u];
507
0
        uint8_t i = 0;
508
509
0
        for (; i < 8; i++) {
510
0
            if (bitarray & 0x01)
511
0
                printf(", %"PRIu32"", u * 8 + i);
512
0
            else
513
0
                printf(", ");
514
515
0
            bitarray = bitarray >> 1;
516
0
        }
517
0
    }
518
0
}
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
 */
528
static SigNumArray *SigNumArrayNew(DetectEngineCtx *de_ctx,
529
                            DetectEngineIPOnlyCtx *io_ctx)
530
566
{
531
566
    SigNumArray *new = SCMalloc(sizeof(SigNumArray));
532
533
566
    if (unlikely(new == NULL)) {
534
0
        FatalError(SC_ERR_FATAL,
535
0
                   "Fatal error encountered in SigNumArrayNew. Exiting...");
536
0
    }
537
566
    memset(new, 0, sizeof(SigNumArray));
538
539
566
    new->array = SCMalloc(io_ctx->max_idx / 8 + 1);
540
566
    if (new->array == NULL) {
541
0
       exit(EXIT_FAILURE);
542
0
    }
543
544
566
    memset(new->array, 0, io_ctx->max_idx / 8 + 1);
545
566
    new->size = io_ctx->max_idx / 8 + 1;
546
547
566
    SCLogDebug("max idx= %u", io_ctx->max_idx);
548
549
566
    return new;
550
566
}
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
 */
560
static SigNumArray *SigNumArrayCopy(SigNumArray *orig)
561
784
{
562
784
    SigNumArray *new = SCMalloc(sizeof(SigNumArray));
563
564
784
    if (unlikely(new == NULL)) {
565
0
        FatalError(SC_ERR_FATAL,
566
0
                   "Fatal error encountered in SigNumArrayCopy. Exiting...");
567
0
    }
568
569
784
    memset(new, 0, sizeof(SigNumArray));
570
784
    new->size = orig->size;
571
572
784
    new->array = SCMalloc(orig->size);
573
784
    if (new->array == NULL) {
574
0
        exit(EXIT_FAILURE);
575
0
    }
576
577
784
    memcpy(new->array, orig->array, orig->size);
578
784
    return new;
579
784
}
580
581
/**
582
 * \brief This function free() a SigNumArray
583
 * \param orig Pointer to the original SigNumArray to copy
584
 */
585
static void SigNumArrayFree(void *tmp)
586
1.35k
{
587
1.35k
    SigNumArray *sna = (SigNumArray *)tmp;
588
589
1.35k
    if (sna == NULL)
590
0
        return;
591
592
1.35k
    if (sna->array != NULL)
593
1.35k
        SCFree(sna->array);
594
595
1.35k
    SCFree(sna);
596
1.35k
}
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
 */
608
static IPOnlyCIDRItem *IPOnlyCIDRListParse2(const DetectEngineCtx *de_ctx,
609
                                            char *s, int negate)
610
25.3k
{
611
25.3k
    size_t x = 0;
612
25.3k
    size_t u = 0;
613
25.3k
    int o_set = 0, n_set = 0, d_set = 0;
614
25.3k
    int depth = 0;
615
25.3k
    size_t size = strlen(s);
616
25.3k
    char address[8196] = "";
617
25.3k
    const char *rule_var_address = NULL;
618
25.3k
    char *temp_rule_var_address = NULL;
619
25.3k
    IPOnlyCIDRItem *head;
620
25.3k
    IPOnlyCIDRItem *subhead;
621
25.3k
    head = subhead = NULL;
622
623
25.3k
    SCLogDebug("s %s negate %s", s, negate ? "true" : "false");
624
625
856k
    for (u = 0, x = 0; u < size && x < sizeof(address); u++) {
626
833k
        address[x] = s[u];
627
833k
        x++;
628
629
833k
        if (!o_set && s[u] == '!') {
630
159
            n_set = 1;
631
159
            x--;
632
833k
        } else if (s[u] == '[') {
633
43.4k
            if (!o_set) {
634
6.08k
                o_set = 1;
635
6.08k
                x = 0;
636
6.08k
            }
637
43.4k
            depth++;
638
789k
        } else if (s[u] == ']') {
639
43.4k
            if (depth == 1) {
640
3.87k
                address[x - 1] = '\0';
641
3.87k
                x = 0;
642
643
3.87k
                if ( (subhead = IPOnlyCIDRListParse2(de_ctx, address,
644
3.87k
                                                (negate + n_set) % 2)) == NULL)
645
254
                    goto error;
646
647
3.62k
                head = IPOnlyCIDRItemInsert(head, subhead);
648
3.62k
                n_set = 0;
649
3.62k
            }
650
43.2k
            depth--;
651
746k
        } else if (depth == 0 && s[u] == ',') {
652
37.1k
            if (o_set == 1) {
653
4.26k
                o_set = 0;
654
32.9k
            } else if (d_set == 1) {
655
0
                address[x - 1] = '\0';
656
657
0
                rule_var_address = SCRuleVarsGetConfVar(de_ctx, address,
658
0
                                                  SC_RULE_VARS_ADDRESS_GROUPS);
659
0
                if (rule_var_address == NULL)
660
0
                    goto error;
661
662
0
                if ((negate + n_set) % 2) {
663
0
                    temp_rule_var_address = SCMalloc(strlen(rule_var_address) + 3);
664
0
                    if (unlikely(temp_rule_var_address == NULL)) {
665
0
                        goto error;
666
0
                    }
667
668
0
                    snprintf(temp_rule_var_address, strlen(rule_var_address) + 3,
669
0
                             "[%s]", rule_var_address);
670
0
                } else {
671
0
                    temp_rule_var_address = SCStrdup(rule_var_address);
672
0
                    if (unlikely(temp_rule_var_address == NULL)) {
673
0
                        goto error;
674
0
                    }
675
0
                }
676
677
0
                subhead = IPOnlyCIDRListParse2(de_ctx, temp_rule_var_address,
678
0
                                               (negate + n_set) % 2);
679
0
                head = IPOnlyCIDRItemInsert(head, subhead);
680
681
0
                d_set = 0;
682
0
                n_set = 0;
683
684
0
                SCFree(temp_rule_var_address);
685
686
32.9k
            } else {
687
32.9k
                address[x - 1] = '\0';
688
689
32.9k
                subhead = IPOnlyCIDRItemNew();
690
32.9k
                if (subhead == NULL)
691
0
                    goto error;
692
693
32.9k
                if (!((negate + n_set) % 2))
694
32.9k
                    subhead->negated = 0;
695
0
                else
696
0
                    subhead->negated = 1;
697
698
32.9k
                if (IPOnlyCIDRItemSetup(&subhead, address) < 0) {
699
1.23k
                    IPOnlyCIDRListFree(subhead);
700
1.23k
                    subhead = NULL;
701
1.23k
                    goto error;
702
1.23k
                }
703
31.6k
                head = IPOnlyCIDRItemInsert(head, subhead);
704
705
31.6k
                n_set = 0;
706
31.6k
            }
707
35.9k
            x = 0;
708
709k
        } else if (depth == 0 && s[u] == '$') {
709
256
            d_set = 1;
710
709k
        } else if (depth == 0 && u == size - 1) {
711
22.2k
            if (x == sizeof(address)) {
712
0
                address[x - 1] = '\0';
713
22.2k
            } else {
714
22.2k
                address[x] = '\0';
715
22.2k
            }
716
22.2k
            x = 0;
717
718
22.2k
            if (d_set == 1) {
719
0
                rule_var_address = SCRuleVarsGetConfVar(de_ctx, address,
720
0
                                                    SC_RULE_VARS_ADDRESS_GROUPS);
721
0
                if (rule_var_address == NULL)
722
0
                    goto error;
723
724
0
                if ((negate + n_set) % 2) {
725
0
                    temp_rule_var_address = SCMalloc(strlen(rule_var_address) + 3);
726
0
                    if (unlikely(temp_rule_var_address == NULL)) {
727
0
                        goto error;
728
0
                    }
729
0
                    snprintf(temp_rule_var_address, strlen(rule_var_address) + 3,
730
0
                            "[%s]", rule_var_address);
731
0
                } else {
732
0
                    temp_rule_var_address = SCStrdup(rule_var_address);
733
0
                    if (unlikely(temp_rule_var_address == NULL)) {
734
0
                        goto error;
735
0
                    }
736
0
                }
737
0
                subhead = IPOnlyCIDRListParse2(de_ctx, temp_rule_var_address,
738
0
                                               (negate + n_set) % 2);
739
0
                head = IPOnlyCIDRItemInsert(head, subhead);
740
741
0
                d_set = 0;
742
743
0
                SCFree(temp_rule_var_address);
744
22.2k
            } else {
745
22.2k
                subhead = IPOnlyCIDRItemNew();
746
22.2k
                if (subhead == NULL)
747
0
                    goto error;
748
749
22.2k
                if (!((negate + n_set) % 2))
750
22.2k
                    subhead->negated = 0;
751
0
                else
752
0
                    subhead->negated = 1;
753
754
22.2k
                if (IPOnlyCIDRItemSetup(&subhead, address) < 0) {
755
564
                    IPOnlyCIDRListFree(subhead);
756
564
                    subhead = NULL;
757
564
                    goto error;
758
564
                }
759
21.7k
                head = IPOnlyCIDRItemInsert(head, subhead);
760
21.7k
            }
761
21.7k
            n_set = 0;
762
21.7k
        }
763
833k
    }
764
765
23.3k
    return head;
766
767
2.04k
error:
768
2.04k
    SCLogError(SC_ERR_ADDRESS_ENGINE_GENERIC,"Error parsing addresses");
769
2.04k
    return head;
770
25.3k
}
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
 */
784
static int IPOnlyCIDRListParse(const DetectEngineCtx *de_ctx,
785
                               IPOnlyCIDRItem **gh, char *str)
786
21.4k
{
787
21.4k
    SCLogDebug("gh %p, str %s", gh, str);
788
789
21.4k
    if (gh == NULL)
790
0
        goto error;
791
792
21.4k
    *gh = IPOnlyCIDRListParse2(de_ctx, str, 0);
793
21.4k
    if (*gh == NULL) {
794
654
        SCLogDebug("IPOnlyCIDRListParse2 returned null");
795
654
        goto error;
796
654
    }
797
798
20.8k
    return 0;
799
800
654
error:
801
654
    return -1;
802
21.4k
}
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
 */
816
int IPOnlySigParseAddress(const DetectEngineCtx *de_ctx,
817
                          Signature *s, const char *addrstr, char flag)
818
14.1k
{
819
14.1k
    SCLogDebug("Address Group \"%s\" to be parsed now", addrstr);
820
14.1k
    IPOnlyCIDRItem *tmp = NULL;
821
822
    /* pass on to the address(list) parser */
823
14.1k
    if (flag == 0) {
824
7.23k
        if (strcasecmp(addrstr, "any") == 0) {
825
3.85k
            s->flags |= SIG_FLAG_SRC_ANY;
826
827
3.85k
            if (IPOnlyCIDRListParse(de_ctx, &s->CidrSrc, (char *)"0.0.0.0/0") < 0)
828
0
                goto error;
829
830
3.85k
            if (IPOnlyCIDRListParse(de_ctx, &tmp, (char *)"::/0") < 0)
831
0
                goto error;
832
833
3.85k
            s->CidrSrc = IPOnlyCIDRItemInsert(s->CidrSrc, tmp);
834
835
3.85k
        } else if (IPOnlyCIDRListParse(de_ctx, &s->CidrSrc, (char *)addrstr) < 0) {
836
301
            goto error;
837
301
        }
838
839
        /* IPOnlyCIDRListPrint(s->CidrSrc); */
840
7.23k
    } else {
841
6.93k
        if (strcasecmp(addrstr, "any") == 0) {
842
3.44k
            s->flags |= SIG_FLAG_DST_ANY;
843
844
3.44k
            if (IPOnlyCIDRListParse(de_ctx, &tmp, (char *)"0.0.0.0/0") < 0)
845
0
                goto error;
846
847
3.44k
            if (IPOnlyCIDRListParse(de_ctx, &s->CidrDst, (char *)"::/0") < 0)
848
0
                goto error;
849
850
3.44k
            s->CidrDst = IPOnlyCIDRItemInsert(s->CidrDst, tmp);
851
852
3.48k
        } else if (IPOnlyCIDRListParse(de_ctx, &s->CidrDst, (char *)addrstr) < 0) {
853
353
            goto error;
854
353
        }
855
856
        /* IPOnlyCIDRListPrint(s->CidrDst); */
857
6.93k
    }
858
859
13.5k
    return 0;
860
861
654
error:
862
654
    SCLogError(SC_ERR_ADDRESS_ENGINE_GENERIC, "failed to parse addresses");
863
654
    return -1;
864
14.1k
}
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
 */
872
void IPOnlyInit(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
873
3.88k
{
874
3.88k
    io_ctx->sig_init_size = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
875
876
3.88k
    if ( (io_ctx->sig_init_array = SCMalloc(io_ctx->sig_init_size)) == NULL) {
877
0
        FatalError(SC_ERR_FATAL,
878
0
                   "Fatal error encountered in IPOnlyInit. Exiting...");
879
0
    }
880
881
3.88k
    memset(io_ctx->sig_init_array, 0, io_ctx->sig_init_size);
882
883
3.88k
    io_ctx->tree_ipv4src = SCRadixCreateRadixTree(SigNumArrayFree,
884
3.88k
                                                  SigNumArrayPrint);
885
3.88k
    io_ctx->tree_ipv4dst = SCRadixCreateRadixTree(SigNumArrayFree,
886
3.88k
                                                  SigNumArrayPrint);
887
3.88k
    io_ctx->tree_ipv6src = SCRadixCreateRadixTree(SigNumArrayFree,
888
3.88k
                                                  SigNumArrayPrint);
889
3.88k
    io_ctx->tree_ipv6dst = SCRadixCreateRadixTree(SigNumArrayFree,
890
3.88k
                                                  SigNumArrayPrint);
891
3.88k
}
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
 */
899
void DetectEngineIPOnlyThreadInit(DetectEngineCtx *de_ctx,
900
                                  DetectEngineIPOnlyThreadCtx *io_tctx)
901
50
{
902
    /* initialize the signature bitarray */
903
50
    io_tctx->sig_match_size = de_ctx->io_ctx.max_idx / 8 + 1;
904
50
    io_tctx->sig_match_array = SCMalloc(io_tctx->sig_match_size);
905
50
    if (io_tctx->sig_match_array == NULL) {
906
0
        exit(EXIT_FAILURE);
907
0
    }
908
909
50
    memset(io_tctx->sig_match_array, 0, io_tctx->sig_match_size);
910
50
}
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
 */
918
void IPOnlyPrint(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
919
3.88k
{
920
    /* XXX: how are we going to print the stats now? */
921
3.88k
}
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
 */
929
void IPOnlyDeinit(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
930
3.89k
{
931
932
3.89k
    if (io_ctx == NULL)
933
0
        return;
934
935
3.89k
    if (io_ctx->tree_ipv4src != NULL)
936
3.88k
        SCRadixReleaseRadixTree(io_ctx->tree_ipv4src);
937
3.89k
    io_ctx->tree_ipv4src = NULL;
938
939
3.89k
    if (io_ctx->tree_ipv4dst != NULL)
940
3.88k
        SCRadixReleaseRadixTree(io_ctx->tree_ipv4dst);
941
3.89k
    io_ctx->tree_ipv4dst = NULL;
942
943
3.89k
    if (io_ctx->tree_ipv6src != NULL)
944
3.88k
        SCRadixReleaseRadixTree(io_ctx->tree_ipv6src);
945
3.89k
    io_ctx->tree_ipv6src = NULL;
946
947
3.89k
    if (io_ctx->tree_ipv6dst != NULL)
948
3.88k
        SCRadixReleaseRadixTree(io_ctx->tree_ipv6dst);
949
3.89k
    io_ctx->tree_ipv6dst = NULL;
950
951
3.89k
    if (io_ctx->sig_init_array)
952
3.88k
        SCFree(io_ctx->sig_init_array);
953
3.89k
    io_ctx->sig_init_array = NULL;
954
3.89k
}
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
 */
962
void DetectEngineIPOnlyThreadDeinit(DetectEngineIPOnlyThreadCtx *io_tctx)
963
47
{
964
47
    SCFree(io_tctx->sig_match_array);
965
47
}
966
967
static inline
968
int IPOnlyMatchCompatSMs(ThreadVars *tv,
969
                         DetectEngineThreadCtx *det_ctx,
970
                         Signature *s, Packet *p)
971
4
{
972
4
    KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_MATCH);
973
4
    SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_MATCH];
974
4
    if (smd) {
975
0
        while (1) {
976
0
            DEBUG_VALIDATE_BUG_ON(!(sigmatch_table[smd->type].flags & SIGMATCH_IPONLY_COMPAT));
977
0
            KEYWORD_PROFILING_START;
978
0
            if (sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx) > 0) {
979
0
                KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
980
0
                if (smd->is_last)
981
0
                    break;
982
0
                smd++;
983
0
                continue;
984
0
            }
985
0
            KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
986
0
            return 0;
987
0
        }
988
0
    }
989
4
    return 1;
990
4
}
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
 */
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
2.60M
{
1006
2.60M
    SigNumArray *src = NULL;
1007
2.60M
    SigNumArray *dst = NULL;
1008
2.60M
    void *user_data_src = NULL, *user_data_dst = NULL;
1009
1010
2.60M
    SCEnter();
1011
1012
2.60M
    if (p->src.family == AF_INET) {
1013
732k
        (void)SCRadixFindKeyIPV4BestMatch((uint8_t *)&GET_IPV4_SRC_ADDR_U32(p),
1014
732k
                                              io_ctx->tree_ipv4src, &user_data_src);
1015
1.87M
    } else if (p->src.family == AF_INET6) {
1016
105k
        (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&GET_IPV6_SRC_ADDR(p),
1017
105k
                                              io_ctx->tree_ipv6src, &user_data_src);
1018
105k
    }
1019
1020
2.60M
    if (p->dst.family == AF_INET) {
1021
732k
        (void)SCRadixFindKeyIPV4BestMatch((uint8_t *)&GET_IPV4_DST_ADDR_U32(p),
1022
732k
                                              io_ctx->tree_ipv4dst, &user_data_dst);
1023
1.87M
    } else if (p->dst.family == AF_INET6) {
1024
105k
        (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&GET_IPV6_DST_ADDR(p),
1025
105k
                                              io_ctx->tree_ipv6dst, &user_data_dst);
1026
105k
    }
1027
1028
2.60M
    src = user_data_src;
1029
2.60M
    dst = user_data_dst;
1030
1031
2.60M
    if (src == NULL || dst == NULL)
1032
2.60M
        SCReturn;
1033
1034
4
    uint32_t u;
1035
8
    for (u = 0; u < src->size; u++) {
1036
4
        SCLogDebug("And %"PRIu8" & %"PRIu8, src->array[u], dst->array[u]);
1037
1038
        /* The final results will be at io_tctx */
1039
4
        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
4
        if (io_tctx->sig_match_array[u] != 0) {
1045
            /* We have a match :) Let's see from which signum's */
1046
4
            uint8_t bitarray = io_tctx->sig_match_array[u];
1047
4
            uint8_t i = 0;
1048
1049
36
            for (; i < 8; i++, bitarray = bitarray >> 1) {
1050
32
                if (bitarray & 0x01) {
1051
4
                    Signature *s = de_ctx->sig_array[u * 8 + i];
1052
1053
4
                    if ((s->proto.flags & DETECT_PROTO_IPV4) && !PKT_IS_IPV4(p)) {
1054
0
                        SCLogDebug("ip version didn't match");
1055
0
                        continue;
1056
0
                    }
1057
4
                    if ((s->proto.flags & DETECT_PROTO_IPV6) && !PKT_IS_IPV6(p)) {
1058
0
                        SCLogDebug("ip version didn't match");
1059
0
                        continue;
1060
0
                    }
1061
1062
4
                    if (DetectProtoContainsProto(&s->proto, IP_GET_IPPROTO(p)) == 0) {
1063
0
                        SCLogDebug("proto didn't match");
1064
0
                        continue;
1065
0
                    }
1066
1067
                    /* check the source & dst port in the sig */
1068
4
                    if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP || p->proto == IPPROTO_SCTP) {
1069
2
                        if (!(s->flags & SIG_FLAG_DP_ANY)) {
1070
0
                            if (p->flags & PKT_IS_FRAGMENT)
1071
0
                                continue;
1072
1073
0
                            DetectPort *dport = DetectPortLookupGroup(s->dp,p->dp);
1074
0
                            if (dport == NULL) {
1075
0
                                SCLogDebug("dport didn't match.");
1076
0
                                continue;
1077
0
                            }
1078
0
                        }
1079
2
                        if (!(s->flags & SIG_FLAG_SP_ANY)) {
1080
0
                            if (p->flags & PKT_IS_FRAGMENT)
1081
0
                                continue;
1082
1083
0
                            DetectPort *sport = DetectPortLookupGroup(s->sp,p->sp);
1084
0
                            if (sport == NULL) {
1085
0
                                SCLogDebug("sport didn't match.");
1086
0
                                continue;
1087
0
                            }
1088
0
                        }
1089
2
                    } else if ((s->flags & (SIG_FLAG_DP_ANY|SIG_FLAG_SP_ANY)) != (SIG_FLAG_DP_ANY|SIG_FLAG_SP_ANY)) {
1090
0
                        SCLogDebug("port-less protocol and sig needs ports");
1091
0
                        continue;
1092
0
                    }
1093
1094
4
                    if (!IPOnlyMatchCompatSMs(tv, det_ctx, s, p)) {
1095
0
                        continue;
1096
0
                    }
1097
1098
4
                    SCLogDebug("Signum %"PRIu32" match (sid: %"PRIu32", msg: %s)",
1099
4
                               u * 8 + i, s->id, s->msg);
1100
1101
4
                    if (s->sm_arrays[DETECT_SM_LIST_POSTMATCH] != NULL) {
1102
0
                        KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_POSTMATCH);
1103
0
                        SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_POSTMATCH];
1104
1105
0
                        SCLogDebug("running match functions, sm %p", smd);
1106
1107
0
                        if (smd != NULL) {
1108
0
                            while (1) {
1109
0
                                KEYWORD_PROFILING_START;
1110
0
                                (void)sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx);
1111
0
                                KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
1112
0
                                if (smd->is_last)
1113
0
                                    break;
1114
0
                                smd++;
1115
0
                            }
1116
0
                        }
1117
0
                    }
1118
4
                    PacketAlertAppend(det_ctx, s, p, 0, 0);
1119
4
                }
1120
32
            }
1121
4
        }
1122
4
    }
1123
4
    SCReturn;
1124
2.60M
}
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
 */
1134
void IPOnlyPrepare(DetectEngineCtx *de_ctx)
1135
3.88k
{
1136
3.88k
    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
3.88k
    IPOnlyCIDRItem *src, *dst;
1144
3.88k
    SCRadixNode *node = NULL;
1145
1146
    /* Prepare Src radix trees */
1147
4.85k
    for (src = (de_ctx->io_ctx).ip_src; src != NULL; ) {
1148
972
        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
255
            void *user_data = NULL;
1159
255
            if (src->netmask == 32)
1160
0
                (void)SCRadixFindKeyIPV4ExactMatch((uint8_t *)&src->ip[0],
1161
0
                                                    (de_ctx->io_ctx).tree_ipv4src,
1162
0
                                                    &user_data);
1163
255
            else
1164
255
                (void)SCRadixFindKeyIPV4Netblock((uint8_t *)&src->ip[0],
1165
255
                                                  (de_ctx->io_ctx).tree_ipv4src,
1166
255
                                                  src->netmask, &user_data);
1167
255
            if (user_data == NULL) {
1168
139
                SCLogDebug("Exact match not found");
1169
1170
                /** Not found, look if there's a subnet of this range with
1171
                 * bigger netmask */
1172
139
                (void)SCRadixFindKeyIPV4BestMatch((uint8_t *)&src->ip[0],
1173
139
                                                   (de_ctx->io_ctx).tree_ipv4src,
1174
139
                                                   &user_data);
1175
139
                if (user_data == NULL) {
1176
139
                    SCLogDebug("best match not found");
1177
1178
                    /* Not found, insert a new one */
1179
139
                    SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1180
1181
                    /* Update the sig */
1182
139
                    uint8_t tmp = 1 << (src->signum % 8);
1183
1184
139
                    if (src->negated > 0)
1185
                        /* Unset it */
1186
0
                        sna->array[src->signum / 8] &= ~tmp;
1187
139
                    else
1188
                        /* Set it */
1189
139
                        sna->array[src->signum / 8] |= tmp;
1190
1191
139
                    if (src->netmask == 32)
1192
0
                        node = SCRadixAddKeyIPV4((uint8_t *)&src->ip[0],
1193
0
                                                 (de_ctx->io_ctx).tree_ipv4src, sna);
1194
139
                    else
1195
139
                        node = SCRadixAddKeyIPV4Netblock((uint8_t *)&src->ip[0],
1196
139
                                                         (de_ctx->io_ctx).tree_ipv4src,
1197
139
                                                         sna, src->netmask);
1198
1199
139
                    if (node == NULL)
1200
0
                        SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the "
1201
139
                                                        "src ipv4 radix tree");
1202
139
                } else {
1203
0
                    SCLogDebug("Best match found");
1204
1205
                    /* Found, copy the sig num table, add this signum and insert */
1206
0
                    SigNumArray *sna = NULL;
1207
0
                    sna = SigNumArrayCopy((SigNumArray *) user_data);
1208
1209
                    /* Update the sig */
1210
0
                    uint8_t tmp = 1 << (src->signum % 8);
1211
1212
0
                    if (src->negated > 0)
1213
                        /* Unset it */
1214
0
                        sna->array[src->signum / 8] &= ~tmp;
1215
0
                    else
1216
                        /* Set it */
1217
0
                        sna->array[src->signum / 8] |= tmp;
1218
1219
0
                    if (src->netmask == 32)
1220
0
                        node = SCRadixAddKeyIPV4((uint8_t *)&src->ip[0],
1221
0
                                                 (de_ctx->io_ctx).tree_ipv4src, sna);
1222
0
                    else
1223
0
                        node = SCRadixAddKeyIPV4Netblock((uint8_t *)&src->ip[0],
1224
0
                                                         (de_ctx->io_ctx).tree_ipv4src, sna,
1225
0
                                                         src->netmask);
1226
1227
0
                    if (node == NULL) {
1228
0
                        char tmpstr[64];
1229
0
                        PrintInet(src->family, &src->ip[0], tmpstr, sizeof(tmpstr));
1230
0
                        SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the"
1231
0
                                   " src ipv4 radix tree ip %s netmask %"PRIu8, tmpstr, src->netmask);
1232
                        //SCRadixPrintTree((de_ctx->io_ctx).tree_ipv4src);
1233
0
                        exit(-1);
1234
0
                    }
1235
0
                }
1236
139
            } else {
1237
116
                SCLogDebug("Exact match found");
1238
1239
                /* it's already inserted. Update it */
1240
116
                SigNumArray *sna = (SigNumArray *)user_data;
1241
1242
                /* Update the sig */
1243
116
                uint8_t tmp = 1 << (src->signum % 8);
1244
1245
116
                if (src->negated > 0)
1246
                    /* Unset it */
1247
0
                    sna->array[src->signum / 8] &= ~tmp;
1248
116
                else
1249
                    /* Set it */
1250
116
                    sna->array[src->signum / 8] |= tmp;
1251
116
            }
1252
717
        } else if (src->family == AF_INET6) {
1253
717
            SCLogDebug("To IPv6");
1254
1255
717
            void *user_data = NULL;
1256
717
            if (src->netmask == 128)
1257
362
                (void)SCRadixFindKeyIPV6ExactMatch((uint8_t *)&src->ip[0],
1258
362
                                                    (de_ctx->io_ctx).tree_ipv6src,
1259
362
                                                    &user_data);
1260
355
            else
1261
355
                (void)SCRadixFindKeyIPV6Netblock((uint8_t *)&src->ip[0],
1262
355
                                                  (de_ctx->io_ctx).tree_ipv6src,
1263
355
                                                  src->netmask, &user_data);
1264
1265
717
            if (user_data == NULL) {
1266
                /* Not found, look if there's a subnet of this range with bigger netmask */
1267
528
                (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&src->ip[0],
1268
528
                                                   (de_ctx->io_ctx).tree_ipv6src,
1269
528
                                                   &user_data);
1270
1271
528
                if (user_data == NULL) {
1272
                    /* Not found, insert a new one */
1273
144
                    SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1274
1275
                    /* Update the sig */
1276
144
                    uint8_t tmp = 1 << (src->signum % 8);
1277
1278
144
                    if (src->negated > 0)
1279
                        /* Unset it */
1280
0
                        sna->array[src->signum / 8] &= ~tmp;
1281
144
                    else
1282
                        /* Set it */
1283
144
                        sna->array[src->signum / 8] |= tmp;
1284
1285
144
                    if (src->netmask == 128)
1286
5
                        node = SCRadixAddKeyIPV6((uint8_t *)&src->ip[0],
1287
5
                                                 (de_ctx->io_ctx).tree_ipv6src, sna);
1288
139
                    else
1289
139
                        node = SCRadixAddKeyIPV6Netblock((uint8_t *)&src->ip[0],
1290
139
                                                         (de_ctx->io_ctx).tree_ipv6src,
1291
139
                                                         sna, src->netmask);
1292
144
                    if (node == NULL)
1293
0
                        SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the src "
1294
144
                                   "ipv6 radix tree");
1295
384
                } else {
1296
                    /* Found, copy the sig num table, add this signum and insert */
1297
384
                    SigNumArray *sna = NULL;
1298
384
                    sna = SigNumArrayCopy((SigNumArray *)user_data);
1299
1300
                    /* Update the sig */
1301
384
                    uint8_t tmp = 1 << (src->signum % 8);
1302
384
                    if (src->negated > 0)
1303
                        /* Unset it */
1304
0
                        sna->array[src->signum / 8] &= ~tmp;
1305
384
                    else
1306
                        /* Set it */
1307
384
                        sna->array[src->signum / 8] |= tmp;
1308
1309
384
                    if (src->netmask == 128)
1310
293
                        node = SCRadixAddKeyIPV6((uint8_t *)&src->ip[0],
1311
293
                                                 (de_ctx->io_ctx).tree_ipv6src, sna);
1312
91
                    else
1313
91
                        node = SCRadixAddKeyIPV6Netblock((uint8_t *)&src->ip[0],
1314
91
                                                         (de_ctx->io_ctx).tree_ipv6src,
1315
91
                                                         sna, src->netmask);
1316
384
                    if (node == NULL)
1317
0
                        SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the src "
1318
384
                                   "ipv6 radix tree");
1319
384
                }
1320
528
            } else {
1321
                /* it's already inserted. Update it */
1322
189
                SigNumArray *sna = (SigNumArray *)user_data;
1323
1324
                /* Update the sig */
1325
189
                uint8_t tmp = 1 << (src->signum % 8);
1326
189
                if (src->negated > 0)
1327
                    /* Unset it */
1328
0
                    sna->array[src->signum / 8] &= ~tmp;
1329
189
                else
1330
                    /* Set it */
1331
189
                    sna->array[src->signum / 8] |= tmp;
1332
189
            }
1333
717
        }
1334
972
        IPOnlyCIDRItem *tmpaux = src;
1335
972
        src = src->next;
1336
972
        SCFree(tmpaux);
1337
972
    }
1338
1339
3.88k
    SCLogDebug("dsts:");
1340
1341
    /* Prepare Dst radix trees */
1342
4.82k
    for (dst = (de_ctx->io_ctx).ip_dst; dst != NULL; ) {
1343
938
        if (dst->family == AF_INET) {
1344
1345
255
            SCLogDebug("To IPv4");
1346
255
            SCLogDebug("Item has netmask %"PRIu8" negated: %s; IP: %s; signum:"
1347
255
                       " %"PRIu32"", dst->netmask, (dst->negated)?"yes":"no",
1348
255
                       inet_ntoa(*(struct in_addr*)&dst->ip[0]), dst->signum);
1349
1350
255
            void *user_data = NULL;
1351
255
            if (dst->netmask == 32)
1352
34
                (void) SCRadixFindKeyIPV4ExactMatch((uint8_t *) &dst->ip[0],
1353
34
                                                    (de_ctx->io_ctx).tree_ipv4dst,
1354
34
                                                    &user_data);
1355
221
            else
1356
221
                (void) SCRadixFindKeyIPV4Netblock((uint8_t *) &dst->ip[0],
1357
221
                                                  (de_ctx->io_ctx).tree_ipv4dst,
1358
221
                                                  dst->netmask,
1359
221
                                                  &user_data);
1360
1361
255
            if (user_data == NULL) {
1362
164
                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
164
                (void) SCRadixFindKeyIPV4BestMatch((uint8_t *)&dst->ip[0],
1369
164
                                                   (de_ctx->io_ctx).tree_ipv4dst,
1370
164
                                                   &user_data);
1371
164
                if (user_data == NULL) {
1372
144
                    SCLogDebug("Best match not found");
1373
1374
                    /** Not found, insert a new one */
1375
144
                    SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1376
1377
                    /** Update the sig */
1378
144
                    uint8_t tmp = 1 << (dst->signum % 8);
1379
144
                    if (dst->negated > 0)
1380
                        /** Unset it */
1381
0
                        sna->array[dst->signum / 8] &= ~tmp;
1382
144
                    else
1383
                        /** Set it */
1384
144
                        sna->array[dst->signum / 8] |= tmp;
1385
1386
144
                    if (dst->netmask == 32)
1387
10
                        node = SCRadixAddKeyIPV4((uint8_t *)&dst->ip[0],
1388
10
                                                 (de_ctx->io_ctx).tree_ipv4dst, sna);
1389
134
                    else
1390
134
                        node = SCRadixAddKeyIPV4Netblock((uint8_t *)&dst->ip[0],
1391
134
                                                         (de_ctx->io_ctx).tree_ipv4dst,
1392
134
                                                         sna, dst->netmask);
1393
1394
144
                    if (node == NULL)
1395
0
                        SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the dst "
1396
144
                                   "ipv4 radix tree");
1397
144
                } else {
1398
20
                    SCLogDebug("Best match found");
1399
1400
                    /* Found, copy the sig num table, add this signum and insert */
1401
20
                    SigNumArray *sna = NULL;
1402
20
                    sna = SigNumArrayCopy((SigNumArray *) user_data);
1403
1404
                    /* Update the sig */
1405
20
                    uint8_t tmp = 1 << (dst->signum % 8);
1406
20
                    if (dst->negated > 0)
1407
                        /* Unset it */
1408
0
                        sna->array[dst->signum / 8] &= ~tmp;
1409
20
                    else
1410
                        /* Set it */
1411
20
                        sna->array[dst->signum / 8] |= tmp;
1412
1413
20
                    if (dst->netmask == 32)
1414
20
                        node = SCRadixAddKeyIPV4((uint8_t *)&dst->ip[0],
1415
20
                                                 (de_ctx->io_ctx).tree_ipv4dst, sna);
1416
0
                    else
1417
0
                        node = SCRadixAddKeyIPV4Netblock((uint8_t *)&dst->ip[0],
1418
0
                                                         (de_ctx->io_ctx).tree_ipv4dst,
1419
0
                                                          sna, dst->netmask);
1420
1421
20
                    if (node == NULL)
1422
0
                        SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the dst "
1423
20
                                   "ipv4 radix tree");
1424
20
                }
1425
164
            } else {
1426
91
                SCLogDebug("Exact match found");
1427
1428
                /* it's already inserted. Update it */
1429
91
                SigNumArray *sna = (SigNumArray *)user_data;
1430
1431
                /* Update the sig */
1432
91
                uint8_t tmp = 1 << (dst->signum % 8);
1433
91
                if (dst->negated > 0)
1434
                    /* Unset it */
1435
0
                    sna->array[dst->signum / 8] &= ~tmp;
1436
91
                else
1437
                    /* Set it */
1438
91
                    sna->array[dst->signum / 8] |= tmp;
1439
91
            }
1440
683
        } else if (dst->family == AF_INET6) {
1441
683
            SCLogDebug("To IPv6");
1442
1443
683
            void *user_data = NULL;
1444
683
            if (dst->netmask == 128)
1445
362
                (void) SCRadixFindKeyIPV6ExactMatch((uint8_t *)&dst->ip[0],
1446
362
                                                    (de_ctx->io_ctx).tree_ipv6dst,
1447
362
                                                    &user_data);
1448
321
            else
1449
321
                (void) SCRadixFindKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1450
321
                                                  (de_ctx->io_ctx).tree_ipv6dst,
1451
321
                                                  dst->netmask, &user_data);
1452
1453
683
            if (user_data == NULL) {
1454
                /** Not found, look if there's a subnet of this range with
1455
                 * bigger netmask
1456
                 */
1457
519
                (void) SCRadixFindKeyIPV6BestMatch((uint8_t *)&dst->ip[0],
1458
519
                                                   (de_ctx->io_ctx).tree_ipv6dst,
1459
519
                                                   &user_data);
1460
1461
519
                if (user_data == NULL) {
1462
                    /* Not found, insert a new one */
1463
139
                    SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1464
1465
                    /* Update the sig */
1466
139
                    uint8_t tmp = 1 << (dst->signum % 8);
1467
139
                    if (dst->negated > 0)
1468
                        /* Unset it */
1469
0
                        sna->array[dst->signum / 8] &= ~tmp;
1470
139
                    else
1471
                        /* Set it */
1472
139
                        sna->array[dst->signum / 8] |= tmp;
1473
1474
139
                    if (dst->netmask == 128)
1475
5
                        node = SCRadixAddKeyIPV6((uint8_t *)&dst->ip[0],
1476
5
                                                 (de_ctx->io_ctx).tree_ipv6dst, sna);
1477
134
                    else
1478
134
                        node = SCRadixAddKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1479
134
                                                         (de_ctx->io_ctx).tree_ipv6dst,
1480
134
                                                          sna, dst->netmask);
1481
1482
139
                    if (node == NULL)
1483
0
                        SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the dst "
1484
139
                                   "ipv6 radix tree");
1485
380
                } else {
1486
                    /* Found, copy the sig num table, add this signum and insert */
1487
380
                    SigNumArray *sna = NULL;
1488
380
                    sna = SigNumArrayCopy((SigNumArray *)user_data);
1489
1490
                    /* Update the sig */
1491
380
                    uint8_t tmp = 1 << (dst->signum % 8);
1492
380
                    if (dst->negated > 0)
1493
                        /* Unset it */
1494
0
                        sna->array[dst->signum / 8] &= ~tmp;
1495
380
                    else
1496
                        /* Set it */
1497
380
                        sna->array[dst->signum / 8] |= tmp;
1498
1499
380
                    if (dst->netmask == 128)
1500
293
                        node = SCRadixAddKeyIPV6((uint8_t *)&dst->ip[0],
1501
293
                                                 (de_ctx->io_ctx).tree_ipv6dst, sna);
1502
87
                    else
1503
87
                        node = SCRadixAddKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1504
87
                                                         (de_ctx->io_ctx).tree_ipv6dst,
1505
87
                                                         sna, dst->netmask);
1506
1507
380
                    if (node == NULL)
1508
0
                        SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the dst "
1509
380
                                   "ipv6 radix tree");
1510
380
                }
1511
519
            } else {
1512
                /* it's already inserted. Update it */
1513
164
                SigNumArray *sna = (SigNumArray *)user_data;
1514
1515
                /* Update the sig */
1516
164
                uint8_t tmp = 1 << (dst->signum % 8);
1517
164
                if (dst->negated > 0)
1518
                    /* Unset it */
1519
0
                    sna->array[dst->signum / 8] &= ~tmp;
1520
164
                else
1521
                    /* Set it */
1522
164
                    sna->array[dst->signum / 8] |= tmp;
1523
164
            }
1524
683
        }
1525
938
        IPOnlyCIDRItem *tmpaux = dst;
1526
938
        dst = dst->next;
1527
938
        SCFree(tmpaux);
1528
938
    }
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
3.88k
}
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
 */
1553
void IPOnlyAddSignature(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx,
1554
                        Signature *s)
1555
286
{
1556
286
    if (!(s->flags & SIG_FLAG_IPONLY))
1557
0
        return;
1558
1559
    /* Set the internal signum to the list before merging */
1560
286
    IPOnlyCIDRListSetSigNum(s->CidrSrc, s->num);
1561
1562
286
    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
286
    io_ctx->ip_src = IPOnlyCIDRItemInsert(io_ctx->ip_src, s->CidrSrc);
1569
286
    io_ctx->ip_dst = IPOnlyCIDRItemInsert(io_ctx->ip_dst, s->CidrDst);
1570
1571
286
    if (s->num > io_ctx->max_idx)
1572
221
        io_ctx->max_idx = s->num;
1573
1574
    /* enable the sig in the bitarray */
1575
286
    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
286
    s->CidrSrc = NULL;
1579
286
    s->CidrDst = NULL;
1580
286
}
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
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
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
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
 */
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
 */
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
 */
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
 */
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
 */
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
 */
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
 */
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
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
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
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
 */
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
 */
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
 */
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
2315
void IPOnlyRegisterTests(void)
2316
0
{
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
0
    return;
2352
0
}
2353