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