1 /*
2 * ModSecurity for Apache 2.x, http://www.modsecurity.org/
3 * Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
4 *
5 * You may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * If any of the files related to licensing are missing or if you have any
11 * other questions related to licensing please contact Trustwave Holdings, Inc.
12 * directly using the email address security@modsecurity.org.
13 */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <apr.h>
18 #if APR_HAVE_STDINT_H
19 #include <stdint.h>
20 #endif
21 #include <string.h>
22 #if APR_HAVE_NETINET_IN_H
23 #include <netinet/in.h>
24 #endif
25 #if APR_HAVE_ARPA_INET_H
26 #include <arpa/inet.h>
27 #endif
28 #include "apr_lib.h"
29 #include "msc_util.h"
30 #include "msc_tree.h"
31
CPTCreateRadixTree(apr_pool_t * pool)32 CPTTree *CPTCreateRadixTree(apr_pool_t *pool) {
33 CPTTree *tree = NULL;
34
35 tree = apr_palloc(pool, sizeof(CPTTree));
36
37 if(tree == NULL)
38 return NULL;
39
40 memset(tree, 0, sizeof(CPTTree));
41 tree->pool = pool;
42
43 return tree;
44 }
45
ConvertIPNetmask(unsigned char * buffer,unsigned char netmask,unsigned int ip_bitmask)46 void ConvertIPNetmask(unsigned char *buffer, unsigned char netmask, unsigned int ip_bitmask) {
47 int aux = 0, bytes = 0;
48 int mask = 0, mask_bit = 0;
49
50 bytes = ip_bitmask/8;
51
52 while(aux < bytes) {
53 mask_bit = ((1+aux) * 8);
54
55 if (mask_bit > netmask) {
56 mask = 0;
57 if ((mask_bit - netmask) < 8) mask = SHIFT_LEFT_MASK(mask_bit - netmask);
58 } else {
59 mask = -1;
60 }
61
62 buffer[aux] &= mask;
63 aux++;
64 }
65
66 return;
67 }
68
CPTCreateNode(apr_pool_t * pool)69 TreeNode *CPTCreateNode(apr_pool_t *pool) {
70 TreeNode *node = NULL;
71
72 node = apr_palloc(pool, sizeof(TreeNode));
73
74 if(node == NULL)
75 return NULL;
76
77 memset(node, 0, sizeof(TreeNode));
78 return node;
79 }
80
CPTCreateCPTData(unsigned char netmask,apr_pool_t * pool)81 CPTData *CPTCreateCPTData(unsigned char netmask, apr_pool_t *pool) {
82
83 CPTData *prefix_data = apr_palloc(pool, sizeof(CPTData));
84
85 if (prefix_data == NULL) {
86 return NULL;
87 }
88
89 memset(prefix_data, 0, sizeof(CPTData));
90
91 prefix_data->netmask = netmask;
92
93 return prefix_data;
94 }
95
InsertDataPrefix(TreePrefix * prefix,unsigned char * ipdata,unsigned int ip_bitmask,unsigned char netmask,apr_pool_t * pool)96 TreePrefix *InsertDataPrefix(TreePrefix *prefix, unsigned char *ipdata, unsigned int ip_bitmask,
97 unsigned char netmask, apr_pool_t *pool) {
98
99 if(prefix == NULL)
100 return NULL;
101
102 memcpy(prefix->buffer, ipdata, ip_bitmask/8);
103 prefix->bitlen = ip_bitmask;
104
105 prefix->prefix_data = CPTCreateCPTData(netmask, pool);
106
107 if(prefix->prefix_data == NULL)
108 return NULL;
109
110 return prefix;
111 }
112
CPTCreatePrefix(unsigned char * ipdata,unsigned int ip_bitmask,unsigned char netmask,apr_pool_t * pool)113 TreePrefix *CPTCreatePrefix(unsigned char *ipdata, unsigned int ip_bitmask,
114 unsigned char netmask, apr_pool_t *pool) {
115
116 TreePrefix *prefix = NULL;
117 int bytes = ip_bitmask/8;
118
119 if ((ip_bitmask % 8 != 0) || (ipdata == NULL)) {
120 return NULL;
121 }
122
123 prefix = apr_palloc(pool, sizeof(TreePrefix));
124 if (prefix == NULL)
125 return NULL;
126
127 memset(prefix, 0, sizeof(TreePrefix));
128
129 prefix->buffer = apr_palloc(pool, bytes);
130
131 if(prefix->buffer == NULL)
132 return NULL;
133
134 memset(prefix->buffer, 0, bytes);
135
136 return InsertDataPrefix(prefix, ipdata, ip_bitmask, netmask, pool);
137 }
138
CPTAppendToCPTDataList(CPTData * new,CPTData ** list)139 void CPTAppendToCPTDataList(CPTData *new, CPTData **list) {
140 CPTData *temp = NULL, *prev = NULL;
141
142 if (new == NULL) {
143 return;
144 }
145
146 if (list == NULL) {
147 return;
148 }
149
150 prev = *list;
151 temp = *list;
152
153 while (temp != NULL) {
154 if (new->netmask > temp->netmask)
155 break;
156 prev = temp;
157 temp = temp->next;
158 }
159
160 if (temp == *list) {
161 new->next = *list;
162 *list = new;
163 } else {
164 new->next = prev->next;
165 prev->next = new;
166 }
167
168 return;
169 }
170
TreePrefixContainNetmask(TreePrefix * prefix,unsigned char netmask)171 int TreePrefixContainNetmask(TreePrefix *prefix, unsigned char netmask) {
172 CPTData *prefix_data = NULL;
173
174 if (prefix == NULL) {
175 return 0;
176 }
177
178 prefix_data = prefix->prefix_data;
179
180 while (prefix_data != NULL) {
181 if (prefix_data->netmask == netmask)
182 return 1;
183 prefix_data = prefix_data->next;
184 }
185
186 return 0;
187 }
188
CheckBitmask(unsigned char netmask,unsigned int ip_bitmask)189 int CheckBitmask(unsigned char netmask, unsigned int ip_bitmask) {
190
191 switch(netmask) {
192
193 case 0xff:
194 return 1;
195 case 0x20:
196 if(ip_bitmask == 0x20)
197 return 1;
198 break;
199 case 0x80:
200 if(ip_bitmask == 0x80)
201 return 1;
202 break;
203 }
204
205 return 0;
206 }
207
CPTCreateHead(TreePrefix * prefix,TreeNode * node,CPTTree * tree,unsigned char netmask,unsigned int ip_bitmask)208 TreeNode *CPTCreateHead(TreePrefix *prefix, TreeNode *node, CPTTree *tree, unsigned char netmask, unsigned int ip_bitmask) {
209
210 if(tree == NULL)
211 return NULL;
212
213 if(prefix == NULL)
214 return NULL;
215
216 if (node != NULL) {
217
218 node->prefix = prefix;
219 node->bit = prefix->bitlen;
220 tree->head = node;
221
222 if(CheckBitmask(netmask, ip_bitmask))
223 return node;
224
225 node->count++;
226 node->netmasks = apr_palloc(tree->pool, (node->count * sizeof(unsigned char)));
227
228 if(node->netmasks)
229 node->netmasks[0] = netmask;
230
231 return node;
232
233 } else {
234 return NULL;
235 }
236
237 return NULL;
238 }
239
SetParentNode(TreeNode * node,TreeNode * new_node,CPTTree * tree)240 TreeNode *SetParentNode(TreeNode *node, TreeNode *new_node, CPTTree *tree) {
241
242 if (node->parent == NULL)
243 tree->head = new_node;
244 else if (node->parent->right == node)
245 node->parent->right = new_node;
246 else
247 node->parent->left = new_node;
248
249 return new_node;
250 }
251
InsertNetmask(TreeNode * node,TreeNode * parent,TreeNode * new_node,CPTTree * tree,unsigned char netmask,unsigned char bitlen)252 int InsertNetmask(TreeNode *node, TreeNode *parent, TreeNode *new_node,
253 CPTTree *tree, unsigned char netmask, unsigned char bitlen) {
254 int i;
255
256 if (netmask != NETMASK_256-1 && netmask != NETMASK_128) {
257 if ((netmask != NETMASK_32 || (netmask == NETMASK_32 && bitlen != NETMASK_32))) {
258
259 node = new_node;
260 parent = new_node->parent;
261
262 while (parent != NULL && netmask < (parent->bit + 1)) {
263 node = parent;
264 parent = parent->parent;
265 }
266
267 node->count++;
268 node->netmasks = apr_palloc(tree->pool, (node->count * sizeof(unsigned char)));
269
270 if(node->netmasks == NULL)
271 return 0;
272 if ((node->count-1) == 0) {
273 node->netmasks[0] = netmask;
274 return 1;
275 }
276
277 node->netmasks[node->count - 1] = netmask;
278
279 i = node->count - 2;
280 while (i >= 0) {
281 if (netmask < node->netmasks[i]) {
282 node->netmasks[i + 1] = netmask;
283 break;
284 }
285
286 node->netmasks[i + 1] = node->netmasks[i];
287 node->netmasks[i] = netmask;
288 i--;
289 }
290 }
291 }
292
293 return 0;
294 }
295
CPTAddElement(unsigned char * ipdata,unsigned int ip_bitmask,CPTTree * tree,unsigned char netmask)296 TreeNode *CPTAddElement(unsigned char *ipdata, unsigned int ip_bitmask, CPTTree *tree, unsigned char netmask) {
297 unsigned char *buffer = NULL;
298 unsigned char bitlen = 0;
299 int bit_validation = 0, test_bit = 0;
300 int i = 0, j = 0, temp = 0;
301 unsigned int x, y;
302 TreeNode *node = NULL, *new_node = NULL;
303 TreeNode *parent = NULL, *i_node = NULL;
304 TreeNode *bottom_node = NULL;
305 TreePrefix *prefix = NULL;
306
307 if (tree == NULL) {
308 return NULL;
309 }
310
311 ConvertIPNetmask(ipdata, netmask, ip_bitmask);
312
313 prefix = CPTCreatePrefix(ipdata, ip_bitmask, netmask, tree->pool);
314
315 if (prefix == NULL) {
316 return NULL;
317 }
318
319 if (tree->head == NULL) {
320 node = CPTCreateNode(tree->pool);
321 return CPTCreateHead(prefix, node, tree, netmask, ip_bitmask);
322 }
323
324 node = tree->head;
325 buffer = prefix->buffer;
326 bitlen = prefix->bitlen;
327
328 while (node->bit < bitlen || node->prefix == NULL) {
329
330 if (bitlen < node->bit) {
331 if (node->right == NULL)
332 break;
333 else
334 node = node->right;
335 } else {
336 x = SHIFT_RIGHT_MASK(node->bit, 3); y = SHIFT_RIGHT_MASK(NETMASK_128, (node->bit % 8));
337
338 if (TREE_CHECK(buffer[x],y)) {
339 if (node->right == NULL)
340 break;
341 node = node->right;
342 } else {
343 if (node->left == NULL)
344 break;
345 else
346 node = node->left;
347 }
348 }
349 }
350
351 bottom_node = node;
352
353 if(node->bit < bitlen)
354 bit_validation = node->bit;
355 else
356 bit_validation = bitlen;
357
358 for (i = 0; (i * NETMASK_8) < bit_validation; i++) {
359 int net = 0, div = 0;
360 int cnt = 0;
361
362 if ((temp = (buffer[i] ^ bottom_node->prefix->buffer[i])) == 0) {
363 test_bit = (i + 1) * NETMASK_8;
364 continue;
365 }
366
367 temp += temp;
368
369 for(cnt = 0, net = NETMASK_256, div = 2; net >= NETMASK_2; net = NETMASK_256/div,
370 div += div, cnt++) {
371 if(temp >= net) {
372 test_bit = (i * NETMASK_8) + cnt;
373 break;
374 }
375 }
376 break;
377 }
378
379 if (bit_validation < test_bit)
380 test_bit = bit_validation;
381
382 parent = node->parent;
383
384 while (parent && test_bit <= parent->bit) {
385 node = parent;
386 parent = node->parent;
387 }
388
389 if (test_bit == bitlen && node->bit == bitlen) {
390 if (node->prefix != NULL) {
391 int found = 0;
392 CPTData *prefix_data = NULL;
393
394 prefix_data = node->prefix->prefix_data;
395
396 while(prefix_data != NULL) {
397 if (prefix_data->netmask == netmask)
398 ++found;
399 prefix_data = prefix_data->next;
400 }
401
402 if (found != 0) {
403
404 CPTData *prefix_data = CPTCreateCPTData(netmask, tree->pool);
405 CPTAppendToCPTDataList(prefix_data, &prefix->prefix_data);
406
407 if(CheckBitmask(netmask, ip_bitmask))
408 return node;
409
410 parent = node->parent;
411 while (parent != NULL && netmask < (parent->bit + 1)) {
412 node = parent;
413 parent = parent->parent;
414 }
415
416 node->count++;
417 new_node = node;
418 node->netmasks = apr_palloc(tree->pool, (node->count * sizeof(unsigned char)));
419
420 if ((node->count -1) == 0) {
421 node->netmasks[0] = netmask;
422 return new_node;
423 }
424
425 node->netmasks[node->count - 1] = netmask;
426
427 i = node->count - 2;
428 while (i >= 0) {
429 if (netmask < node->netmasks[i]) {
430 node->netmasks[i + 1] = netmask;
431 break;
432 }
433
434 node->netmasks[i + 1] = node->netmasks[i];
435 node->netmasks[i] = netmask;
436 i--;
437 }
438 }
439 } else {
440 node->prefix = CPTCreatePrefix(prefix->buffer, prefix->bitlen,
441 NETMASK_256-1, tree->pool);
442 }
443 return node;
444 }
445
446 new_node = CPTCreateNode(tree->pool);
447
448 if(new_node == NULL)
449 return NULL;
450
451 new_node->prefix = prefix;
452 new_node->bit = prefix->bitlen;
453
454 if (test_bit == bitlen) {
455
456 x = SHIFT_RIGHT_MASK(test_bit, 3); y = SHIFT_RIGHT_MASK(NETMASK_128, (test_bit % 8));
457
458 if (TREE_CHECK(bottom_node->prefix->buffer[x],y)) {
459 new_node->right = node;
460 } else {
461 new_node->left = node;
462 }
463
464 new_node->parent = node->parent;
465 node->parent = SetParentNode(node, new_node, tree);
466
467 } else {
468 i_node = CPTCreateNode(tree->pool);
469
470 if(i_node == NULL)
471 return NULL;
472
473 //i_node->prefix = NULL;
474 i_node->bit = test_bit;
475 i_node->parent = node->parent;
476
477 if (node->netmasks != NULL) {
478 i = 0;
479 while(i < node->count) {
480 if (node->netmasks[i] < test_bit + 1)
481 break;
482 i++;
483 }
484
485 i_node->netmasks = apr_palloc(tree->pool, (node->count - i) * sizeof(unsigned char));
486
487 if(i_node->netmasks == NULL) {
488 return NULL;
489 }
490
491 j = 0;
492 while (j < (node->count - i)) {
493 i_node->netmasks[j] = node->netmasks[i + j];
494 j++;
495 }
496
497 i_node->count = (node->count - i);
498 node->count = i;
499
500 if (node->count == 0) {
501 node->netmasks = NULL;
502 }
503 }
504
505 x = SHIFT_RIGHT_MASK(test_bit, 3); y = SHIFT_RIGHT_MASK(NETMASK_128, (test_bit % 8));
506
507 if (TREE_CHECK(buffer[x],y)) {
508 i_node->left = node;
509 i_node->right = new_node;
510 } else {
511 i_node->left = new_node;
512 i_node->right = node;
513 }
514
515 new_node->parent = i_node;
516 node->parent = SetParentNode(node, i_node, tree);
517 }
518
519 if (InsertNetmask(node, parent, new_node, tree, netmask, bitlen))
520 return new_node;
521
522 return new_node;
523 }
524
TreeCheckData(TreePrefix * prefix,CPTData * prefix_data,unsigned int netmask)525 int TreeCheckData(TreePrefix *prefix, CPTData *prefix_data, unsigned int netmask) {
526
527 while(prefix_data != NULL) {
528 if (prefix_data->netmask == netmask) {
529 return 1;
530 }
531 prefix_data = prefix_data->next;
532 }
533
534 return 0;
535 }
536
TreePrefixNetmask(modsec_rec * msr,TreePrefix * prefix,unsigned int netmask,int flag)537 int TreePrefixNetmask(modsec_rec *msr, TreePrefix *prefix, unsigned int netmask, int flag) {
538 CPTData *prefix_data = NULL;
539 int ret = 0;
540
541 if (prefix == NULL) {
542 if (msr && msr->txcfg->debuglog_level >= 9) {
543 msr_log(msr, 9, "TreePrefixNetmask: prefix is NULL.");
544 }
545 return 0;
546 }
547
548 prefix_data = prefix->prefix_data;
549
550 if (flag == 1) {
551
552 if(prefix_data == NULL) return 0;
553
554 if (prefix_data->netmask != netmask) {
555 if (msr && msr->txcfg->debuglog_level >= 9) {
556 msr_log(msr, 9, "TreePrefixNetmask: Cannot find a prefix with correct netmask.");
557 }
558 return 0;
559 } else {
560 if (msr && msr->txcfg->debuglog_level >= 9) {
561 msr_log(msr, 9, "TreePrefixNetmask: Found a prefix with correct netmask.");
562 }
563 return 1;
564 }
565 }
566
567 if (msr && msr->txcfg->debuglog_level >= 9) {
568 msr_log(msr, 9, "TreePrefixNetmask: Check if a prefix has a the correct netmask");
569 }
570
571 ret = TreeCheckData(prefix, prefix_data, netmask);
572
573 return ret;
574 }
575
CPTRetriveNode(modsec_rec * msr,unsigned char * buffer,unsigned int ip_bitmask,TreeNode * node)576 TreeNode *CPTRetriveNode(modsec_rec *msr, unsigned char *buffer, unsigned int ip_bitmask, TreeNode *node) {
577 unsigned int x, y;
578
579 if(node == NULL) {
580 if (msr && msr->txcfg->debuglog_level >= 9) {
581 msr_log(msr, 9, "CPTRetriveNode: Node tree is NULL.");
582 }
583 return NULL;
584 }
585
586 if(buffer == NULL) {
587 if (msr && msr->txcfg->debuglog_level >= 9) {
588 msr_log(msr, 9, "CPTRetriveNode: Empty ip address. Nothing to search for.");
589 }
590 return NULL;
591 }
592
593 while (node->bit < ip_bitmask) {
594
595 x = SHIFT_RIGHT_MASK(node->bit, 3); y = SHIFT_RIGHT_MASK(NETMASK_128, (node->bit % 8));
596
597 if (TREE_CHECK(buffer[x], y)) {
598 node = node->right;
599 if (node == NULL) return NULL;
600 } else {
601 node = node->left;
602 if (node == NULL) return NULL;
603 }
604 }
605
606 if (msr && msr->txcfg->debuglog_level >= 9) {
607 msr_log(msr, 9, "CPTRetriveNode: Found the node for provided ip address.");
608 }
609
610
611 return node;
612 }
613
CPTRetriveParentNode(TreeNode * node)614 TreeNode *CPTRetriveParentNode(TreeNode *node) {
615
616 while (node != NULL && node->netmasks == NULL)
617 node = node->parent;
618
619 return node;
620 }
621
CPTFindElementIPNetblock(modsec_rec * msr,unsigned char * ipdata,unsigned char ip_bitmask,TreeNode * node)622 TreeNode *CPTFindElementIPNetblock(modsec_rec *msr, unsigned char *ipdata, unsigned char ip_bitmask, TreeNode *node) {
623 TreeNode *netmask_node = NULL;
624 int mask = 0, bytes = 0;
625 int i = 0, j = 0;
626 int mask_bits = 0;
627
628 node = CPTRetriveParentNode(node);
629
630 if (node == NULL) {
631 if (msr && msr->txcfg->debuglog_level >= 9) {
632 msr_log(msr, 9, "CPTFindElementIPNetblock: Node tree is NULL.");
633 }
634 return NULL;
635 }
636
637 netmask_node = node;
638
639 while(j < netmask_node->count) {
640 bytes = ip_bitmask / 8;
641
642 while( i < bytes ) {
643
644 mask = -1;
645 mask_bits = ((i + 1) * 8);
646
647 if (mask_bits > netmask_node->netmasks[j]) {
648 if ((mask_bits - netmask_node->netmasks[j]) < 8)
649 mask = SHIFT_LEFT_MASK(mask_bits - netmask_node->netmasks[j]);
650 else
651 mask = 0;
652 }
653
654 ipdata[i] &= mask;
655 i++;
656 }
657
658 node = CPTRetriveNode(msr, ipdata, ip_bitmask, node);
659
660 if (node && node->bit != ip_bitmask) {
661 if (msr && msr->txcfg->debuglog_level >= 9) {
662 msr_log(msr, 9, "CPTFindElementIPNetblock: Found a tree node but netmask is different.");
663 }
664 return NULL;
665 }
666
667 if (node && node->prefix == NULL) {
668 if (msr && msr->txcfg->debuglog_level >= 9) {
669 msr_log(msr, 9, "CPTFindElementIPNetblock: Found a tree node but prefix is NULL.");
670 }
671 return NULL;
672 }
673
674 if (memcmp(node->prefix->buffer, ipdata, bytes) == 0) {
675 mask = SHIFT_LEFT_MASK(8 - ip_bitmask % 8);
676
677 if ((ip_bitmask % 8) == 0) {
678 if (TreePrefixNetmask(msr, node->prefix, netmask_node->netmasks[j], FALSE)) {
679 if (msr && msr->txcfg->debuglog_level >= 9) {
680 msr_log(msr, 9, "CPTFindElementIPNetblock: Node found for provided ip address");
681 }
682 return node;
683 }
684 }
685
686 if ((node->prefix->buffer[bytes] & mask) == (ipdata[bytes] & mask)) {
687 if (TreePrefixNetmask(msr, node->prefix, netmask_node->netmasks[j], FALSE)) {
688 if (msr && msr->txcfg->debuglog_level >= 9) {
689 msr_log(msr, 9, "CPTFindElementIPNetblock: Node found for provided ip address");
690 }
691 return node;
692 }
693 }
694 }
695
696 j++;
697 }
698
699 return CPTFindElementIPNetblock(msr, ipdata, ip_bitmask, netmask_node->parent);
700 }
701
CPTFindElement(modsec_rec * msr,unsigned char * ipdata,unsigned int ip_bitmask,CPTTree * tree)702 TreeNode *CPTFindElement(modsec_rec *msr, unsigned char *ipdata, unsigned int ip_bitmask, CPTTree *tree) {
703 TreeNode *node = NULL;
704 int mask = 0, bytes = 0;
705 unsigned char temp_data[NETMASK_256-1];
706
707 if (tree == NULL) {
708 if (msr && msr->txcfg->debuglog_level >= 9) {
709 msr_log(msr, 9, "CPTFindElement: Tree is NULL. Cannot proceed searching the ip.");
710 }
711 return node;
712 }
713
714 if (tree->head == NULL) {
715 if (msr && msr->txcfg->debuglog_level >= 9) {
716 msr_log(msr, 9, "CPTFindElement: Tree head is NULL. Cannot proceed searching the ip.");
717 }
718 return node;
719 }
720
721 node = tree->head;
722
723 if (ip_bitmask > (NETMASK_256-1)) {
724 if (msr && msr->txcfg->debuglog_level >= 9) {
725 msr_log(msr, 9, "CPTFindElement: Netmask cannot be greater than 255");
726 }
727 return NULL;
728 }
729
730 bytes = ip_bitmask/8;
731
732 memset(temp_data, 0, NETMASK_256-1);
733 memcpy(temp_data, ipdata, bytes);
734
735 node = CPTRetriveNode(msr, temp_data, ip_bitmask, node);
736
737 if (node && (node->bit != ip_bitmask)) {
738 if (msr && msr->txcfg->debuglog_level >= 9) {
739 msr_log(msr, 9, "CPTFindElement: Found a tree node but netmask is different.");
740 }
741 return NULL;
742 }
743
744 if(node == NULL) {
745 if (msr && msr->txcfg->debuglog_level >= 9) {
746 msr_log(msr, 9, "CPTFindElement: Node tree is NULL.");
747 }
748 return node;
749 }
750
751 if(node->prefix == NULL) {
752 if (msr && msr->txcfg->debuglog_level >= 9) {
753 msr_log(msr, 9, "CPTFindElement: Found a tree node but prefix is NULL.");
754 }
755 return node;
756 }
757
758 if ((node->netmasks == NULL) && (memcmp(node->prefix->buffer, temp_data, bytes) == 0)) {
759 mask = SHIFT_LEFT_MASK(8 - ip_bitmask % 8);
760
761 if ((ip_bitmask % 8) == 0) {
762 if (TreePrefixNetmask(msr, node->prefix, ip_bitmask, TRUE)) {
763 if (msr && msr->txcfg->debuglog_level >= 9) {
764 msr_log(msr, 9, "CPTFindElement: Node found for provided ip address");
765 }
766 return node;
767 }
768 }
769
770 if ((node->prefix->buffer[bytes] & mask) == (temp_data[bytes] & mask)) {
771 if (TreePrefixNetmask(msr, node->prefix, ip_bitmask, TRUE)) {
772 if (msr && msr->txcfg->debuglog_level >= 9) {
773 msr_log(msr, 9, "CPTFindElement: Node found for provided ip address");
774 }
775 return node;
776 }
777 }
778 }
779
780 return CPTFindElementIPNetblock(msr, temp_data, ip_bitmask, node);
781 }
782
CPTIpMatch(modsec_rec * msr,unsigned char * ipdata,CPTTree * tree,int type)783 TreeNode *CPTIpMatch(modsec_rec *msr, unsigned char *ipdata, CPTTree *tree, int type) {
784
785 if(tree == NULL) {
786 if (msr && msr->txcfg->debuglog_level >= 9) {
787 msr_log(msr, 9, "CPTIpMatch: Tree is NULL. Cannot proceed searching the ip.");
788 }
789 return NULL;
790 }
791
792 if(ipdata == NULL) {
793 if (msr && msr->txcfg->debuglog_level >= 9) {
794 msr_log(msr, 9, "CPTIpMatch: Empty ip address. Nothing to search for.");
795 }
796 return NULL;
797 }
798
799 switch(type) {
800 case IPV4_TREE:
801 if (msr && msr->txcfg->debuglog_level >= 9) {
802 msr_log(msr, 9, "CPTIpMatch: Searching ip type 0x%x", type);
803 }
804 return CPTFindElement(msr, ipdata, NETMASK_32, tree);
805 case IPV6_TREE:
806 if (msr && msr->txcfg->debuglog_level >= 9) {
807 msr_log(msr, 9, "CPTIpMatch: Searching ip type 0x%x", type);
808 }
809 return CPTFindElement(msr, ipdata, NETMASK_128, tree);
810 default:
811 if (msr && msr->txcfg->debuglog_level >= 9) {
812 msr_log(msr, 9, "CPTIpMatch: Unknown ip type 0x%x", type);
813 }
814 return NULL;
815 }
816 }
817
TreeAddIP(const char * buffer,CPTTree * tree,int type)818 TreeNode *TreeAddIP(const char *buffer, CPTTree *tree, int type) {
819 unsigned long ip, ret;
820 unsigned char netmask_v4 = NETMASK_32, netmask_v6 = NETMASK_128;
821 char ip_strv4[NETMASK_32], ip_strv6[NETMASK_128];
822 struct in_addr addr4;
823 struct in6_addr addr6;
824 int pos = 0;
825 char *ptr = NULL;
826
827 if(tree == NULL)
828 return NULL;
829
830 pos = strchr(buffer, '/') - buffer;
831
832 switch(type) {
833
834 case IPV4_TREE:
835 memset(&addr4, 0, sizeof(addr4));
836 memset(ip_strv4, 0x0, NETMASK_32);
837
838 strncpy(ip_strv4, buffer, sizeof(ip_strv4));
839 *(ip_strv4 + (sizeof(ip_strv4) - 1)) = '\0';
840
841 ptr = strdup(ip_strv4);
842 netmask_v4 = is_netmask_v4(ptr);
843
844 if (netmask_v4 > NETMASK_32) {
845 free(ptr);
846 ptr = NULL;
847 return NULL;
848 }
849
850 if(ptr != NULL) {
851 free(ptr);
852 ptr = NULL;
853 }
854
855 if(netmask_v4 == 0) {
856 return NULL;
857 }
858 else if (netmask_v4 != NETMASK_32 && pos < strlen(ip_strv4)) {
859 ip_strv4[pos] = '\0';
860 }
861
862 ret = inet_pton(AF_INET, ip_strv4, &addr4);
863
864 if (ret <= 0) {
865 return NULL;
866 }
867
868 ip = addr4.s_addr;
869
870 tree->count++;
871
872 return CPTAddElement((unsigned char *)&ip, NETMASK_32, tree, netmask_v4);
873
874 case IPV6_TREE:
875 memset(&addr6, 0, sizeof(addr6));
876 memset(ip_strv6, 0x0, NETMASK_128);
877
878 strncpy(ip_strv6, buffer, sizeof(ip_strv6));
879 *(ip_strv6 + sizeof(ip_strv6) - 1) = '\0';
880
881 ptr = strdup(ip_strv6);
882 netmask_v6 = is_netmask_v6(ptr);
883
884 if (netmask_v6 > NETMASK_128) {
885 free(ptr);
886 ptr = NULL;
887 return NULL;
888 }
889
890 if(ptr != NULL) {
891 free(ptr);
892 ptr = NULL;
893 }
894
895 if(netmask_v6 == 0) {
896 return NULL;
897 }
898 else if (netmask_v6 != NETMASK_128 && pos < strlen(ip_strv6)) {
899 ip_strv6[pos] = '\0';
900 }
901
902 ret = inet_pton(AF_INET6, ip_strv6, &addr6);
903
904 if (ret <= 0)
905 {
906 return NULL;
907 }
908
909 tree->count++;
910
911 return CPTAddElement((unsigned char *)&addr6.s6_addr, NETMASK_128, tree, netmask_v6);
912 default:
913 return NULL;
914 }
915
916 return NULL;
917 }
918