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