everything: shotgun attempt to put PROTO_WS and PROTO_WSS across core and in modules...
[sip-router] / modules_k / permissions / hash.c
1 /*
2  * Hash functions for cached trusted and address tables
3  *
4  * Copyright (C) 2003-2012 Juha Heinanen
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License 
19  * along with this program; if not, write to the Free Software 
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include <sys/types.h>
24 #include <regex.h>
25 #include "../../mem/shm_mem.h"
26 #include "../../parser/parse_from.h"
27 #include "../../ut.h"
28 #include "../../hashes.h"
29 #include "../../usr_avp.h"
30 #include "../../ip_addr.h"
31 #include "../../pvar.h"
32 #include "hash.h"
33 #include "trusted.h"
34 #include "address.h"
35
36 #define perm_hash(_s)  core_hash( &(_s), 0, PERM_HASH_SIZE)
37
38
39 /* tag AVP specs */
40 static int     tag_avp_type;
41 static int_str tag_avp;
42
43 extern int peer_tag_mode;
44
45
46
47 /*
48  * Parse and set tag AVP specs
49  */
50 int init_tag_avp(str *tag_avp_param)
51 {
52         pv_spec_t avp_spec;
53         unsigned short avp_flags;
54
55         if (tag_avp_param->s && tag_avp_param->len > 0) {
56                 if (pv_parse_spec(tag_avp_param, &avp_spec)==0
57                                 || avp_spec.type != PVT_AVP) {
58                         LM_ERR("malformed or non "
59                                         "AVP %.*s peer_tag_avp definition\n", tag_avp_param->len, tag_avp_param->s);
60                         return -1;
61                 }
62                 if(pv_get_avp_name(0, &avp_spec.pvp, &tag_avp, &avp_flags)!=0) {
63                         LM_ERR("[%.*s]- invalid "
64                                         "peer_tag_avp AVP definition\n", tag_avp_param->len, tag_avp_param->s);
65                         return -1;
66                 }
67                 tag_avp_type = avp_flags;
68         } else {
69                 tag_avp.n = 0;
70         }
71         return 0;
72 }
73
74
75 /*
76  * Gets tag avp specs
77  */
78 void get_tag_avp(int_str *tag_avp_p, int *tag_avp_type_p)
79 {
80         *tag_avp_p = tag_avp;
81         *tag_avp_type_p = tag_avp_type;
82 }
83
84
85 /*
86  * Create and initialize a hash table
87  */
88 struct trusted_list** new_hash_table(void)
89 {
90         struct trusted_list** ptr;
91
92         /* Initializing hash tables and hash table variable */
93         ptr = (struct trusted_list **)shm_malloc
94                 (sizeof(struct trusted_list*) * PERM_HASH_SIZE);
95         if (!ptr) {
96                 LM_ERR("no shm memory for hash table\n");
97                 return 0;
98         }
99
100         memset(ptr, 0, sizeof(struct trusted_list*) * PERM_HASH_SIZE);
101         return ptr;
102 }
103
104
105 /*
106  * Release all memory allocated for a hash table
107  */
108 void free_hash_table(struct trusted_list** table)
109 {
110         if (!table)
111                 return;
112
113         empty_hash_table(table);
114         shm_free(table);
115 }
116
117
118 /* 
119  * Add <src_ip, proto, pattern, tag> into hash table, where proto is integer
120  * representation of string argument proto.
121  */
122 int hash_table_insert(struct trusted_list** table, char* src_ip, 
123                 char* proto, char* pattern, char* tag)
124 {
125         struct trusted_list *np;
126         unsigned int hash_val;
127
128         np = (struct trusted_list *) shm_malloc(sizeof(*np));
129         if (np == NULL) {
130                 LM_ERR("cannot allocate shm memory for table entry\n");
131                 return -1;
132         }
133
134         if (strcasecmp(proto, "any") == 0) {
135                 np->proto = PROTO_NONE;
136         } else if (strcasecmp(proto, "udp") == 0) {
137                 np->proto = PROTO_UDP;
138         } else if (strcasecmp(proto, "tcp") == 0) {
139                 np->proto = PROTO_TCP;
140         } else if (strcasecmp(proto, "tls") == 0) {
141                 np->proto = PROTO_TLS;
142         } else if (strcasecmp(proto, "sctp") == 0) {
143                 np->proto = PROTO_SCTP;
144         } else if (strcasecmp(proto, "ws") == 0) {
145                 np->proto = PROTO_WS;
146         } else if (strcasecmp(proto, "wss") == 0) {
147                 np->proto = PROTO_WSS;
148         } else if (strcasecmp(proto, "none") == 0) {
149                 shm_free(np);
150                 return 1;
151         } else {
152                 LM_CRIT("unknown protocol\n");
153                 shm_free(np);
154                 return -1;
155         }
156
157         np->src_ip.len = strlen(src_ip);
158         np->src_ip.s = (char *) shm_malloc(np->src_ip.len);
159
160         if (np->src_ip.s == NULL) {
161                 LM_CRIT("cannot allocate shm memory for src_ip string\n");
162                 shm_free(np);
163                 return -1;
164         }
165
166         (void) strncpy(np->src_ip.s, src_ip, np->src_ip.len);
167
168         if (pattern) {
169                 np->pattern = (char *) shm_malloc(strlen(pattern)+1);
170                 if (np->pattern == NULL) {
171                         LM_CRIT("cannot allocate shm memory for pattern string\n");
172                         shm_free(np->src_ip.s);
173                         shm_free(np);
174                         return -1;
175                 }
176                 (void) strcpy(np->pattern, pattern);
177         } else {
178                 np->pattern = 0;
179         }
180
181         if (tag) {
182                 np->tag.len = strlen(tag);
183                 np->tag.s = (char *) shm_malloc((np->tag.len) + 1);
184                 if (np->tag.s == NULL) {
185                         LM_CRIT("cannot allocate shm memory for pattern string\n");
186                         shm_free(np->src_ip.s);
187                         shm_free(np->pattern);
188                         shm_free(np);
189                         return -1;
190                 }
191                 (void) strcpy(np->tag.s, tag);
192         } else {
193                 np->tag.len = 0;
194                 np->tag.s = 0;
195         }
196
197         hash_val = perm_hash(np->src_ip);
198         np->next = table[hash_val];
199         table[hash_val] = np;
200
201         return 1;
202 }
203
204
205 /* 
206  * Check if an entry exists in hash table that has given src_ip and protocol
207  * value and pattern that matches to From URI.  If an entry exists and tag_avp
208  * has been defined, tag of the entry is added as a value to tag_avp.
209  * Returns number of matches or -1 if none matched.
210  */
211 int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
212                 char *src_ip_c_str, int proto)
213 {
214         str uri;
215         char uri_string[MAX_URI_SIZE + 1];
216         regex_t preg;
217         struct trusted_list *np;
218         str src_ip;
219         int_str val;
220         int count = 0;
221
222         src_ip.s = src_ip_c_str;
223         src_ip.len = strlen(src_ip.s);
224
225         if (IS_SIP(msg))
226         {
227                 if (parse_from_header(msg) < 0) return -1;
228                 uri = get_from(msg)->uri;
229                 if (uri.len > MAX_URI_SIZE) {
230                         LM_ERR("from URI too large\n");
231                         return -1;
232                 }
233                 memcpy(uri_string, uri.s, uri.len);
234                 uri_string[uri.len] = (char)0;
235         }
236
237         for (np = table[perm_hash(src_ip)]; np != NULL; np = np->next) {
238             if ((np->src_ip.len == src_ip.len) && 
239                 (strncmp(np->src_ip.s, src_ip.s, src_ip.len) == 0) &&
240                 ((np->proto == PROTO_NONE) || (proto == PROTO_NONE) ||
241                  (np->proto == proto))) {
242                 if (np->pattern && IS_SIP(msg)) {
243                     if (regcomp(&preg, np->pattern, REG_NOSUB)) {
244                         LM_ERR("invalid regular expression\n");
245                         continue;
246                     }
247                     if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
248                         regfree(&preg);
249                         continue;
250                     }
251                     regfree(&preg);
252                 }
253                 /* Found a match */
254                 if (tag_avp.n && np->tag.s) {
255                     val.s = np->tag;
256                     if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
257                         LM_ERR("setting of tag_avp failed\n");
258                         return -1;
259                     }
260                 }
261                 if (!peer_tag_mode)
262                     return 1;
263                 count++;
264             }
265         }
266         if (!count)
267             return -1;
268         else 
269             return count;
270 }
271
272
273 /* 
274  * Print trusted entries stored in hash table 
275  */
276 int hash_table_mi_print(struct trusted_list** table, struct mi_node* rpl)
277 {
278         int i;
279         struct trusted_list *np;
280
281         for (i = 0; i < PERM_HASH_SIZE; i++) {
282                 np = table[i];
283                 while (np) {
284                         if (addf_mi_node_child(rpl, 0, 0, 0,
285                                                 "%4d <%.*s, %d, %s, %s>",
286                                                 i,
287                                                 np->src_ip.len, ZSW(np->src_ip.s),
288                                                 np->proto,
289                                                 np->pattern?np->pattern:"NULL",
290                                                 np->tag.len?np->tag.s:"NULL") == 0) {
291                                 return -1;
292                         }
293                         np = np->next;
294                 }
295         }
296         return 0;
297 }
298
299
300 /* 
301  * Free contents of hash table, it doesn't destroy the
302  * hash table itself
303  */
304 void empty_hash_table(struct trusted_list **table)
305 {
306         int i;
307         struct trusted_list *np, *next;
308
309         for (i = 0; i < PERM_HASH_SIZE; i++) {
310                 np = table[i];
311                 while (np) {
312                         if (np->src_ip.s) shm_free(np->src_ip.s);
313                         if (np->pattern) shm_free(np->pattern);
314                         if (np->tag.s) shm_free(np->tag.s);
315                         next = np->next;
316                         shm_free(np);
317                         np = next;
318                 }
319                 table[i] = 0;
320         }
321 }
322
323
324 /*
325  * Create and initialize an address hash table
326  */
327 struct addr_list** new_addr_hash_table(void)
328 {
329         struct addr_list** ptr;
330
331         /* Initializing hash tables and hash table variable */
332         ptr = (struct addr_list **)shm_malloc
333                 (sizeof(struct addr_list*) * PERM_HASH_SIZE);
334         if (!ptr) {
335                 LM_ERR("no shm memory for hash table\n");
336                 return 0;
337         }
338
339         memset(ptr, 0, sizeof(struct addr_list*) * PERM_HASH_SIZE);
340         return ptr;
341 }
342
343
344 /*
345  * Release all memory allocated for a hash table
346  */
347 void free_addr_hash_table(struct addr_list** table)
348 {
349         if (!table)
350                 return;
351
352         empty_addr_hash_table(table);
353         shm_free(table);
354 }
355
356
357 /* 
358  * Add <grp, ip_addr, port> into hash table
359  */
360 int addr_hash_table_insert(struct addr_list** table, unsigned int grp,
361                 ip_addr_t *addr, unsigned int port, char *tagv)
362 {
363         struct addr_list *np;
364         unsigned int hash_val;
365         str addr_str;
366         int len;
367
368         len = sizeof(struct addr_list);
369         if(tagv!=NULL)
370                 len += strlen(tagv) + 1;
371
372         np = (struct addr_list *) shm_malloc(len);
373         if (np == NULL) {
374                 LM_ERR("no shm memory for table entry\n");
375                 return -1;
376         }
377
378         memset(np, 0, len);
379
380         np->grp = grp;
381         memcpy(&np->addr, addr, sizeof(ip_addr_t));
382         np->port = port;
383         if(tagv!=NULL)
384         {
385                 np->tag.s = (char*)np + sizeof(struct addr_list);
386                 np->tag.len = strlen(tagv);
387                 strcpy(np->tag.s, tagv);
388         }
389
390         addr_str.s = (char*)addr->u.addr;
391         addr_str.len = 4;
392         hash_val = perm_hash(addr_str);
393         np->next = table[hash_val];
394         table[hash_val] = np;
395
396         return 1;
397 }
398
399
400 /* 
401  * Check if an entry exists in hash table that has given group, ip_addr, and
402  * port.  Port 0 in hash table matches any port.
403  */
404 int match_addr_hash_table(struct addr_list** table, unsigned int group,
405                 ip_addr_t *addr, unsigned int port)
406 {
407         struct addr_list *np;
408         str addr_str;
409         avp_value_t val;
410
411         addr_str.s = (char*)addr->u.addr;
412         addr_str.len = 4;
413
414         for (np = table[perm_hash(addr_str)]; np != NULL; np = np->next) {
415                 if ( (np->grp == group)
416                                 && ((np->port == 0) || (np->port == port))
417                                 && ip_addr_cmp(&np->addr, addr)) {
418
419                         if (tag_avp.n && np->tag.s) {
420                                 val.s = np->tag;
421                                 if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
422                                         LM_ERR("setting of tag_avp failed\n");
423                                         return -1;
424                                 }
425                         }
426
427                         return 1;
428                 }
429         }
430
431         return -1;
432 }
433
434
435 /* 
436  * Check if an ip_addr/port entry exists in hash table in any group.
437  * Returns first group in which ip_addr/port is found.
438  * Port 0 in hash table matches any port. 
439  */
440 int find_group_in_addr_hash_table(struct addr_list** table,
441                 ip_addr_t *addr, unsigned int port)
442 {
443         struct addr_list *np;
444         str addr_str;
445
446         addr_str.s = (char*)addr->u.addr;
447         addr_str.len = 4;
448
449         for (np = table[perm_hash(addr_str)]; np != NULL; np = np->next) {
450                 if (((np->port == 0) || (np->port == port))
451                                 && ip_addr_cmp(&np->addr, addr)) {
452                         return np->grp;
453                 }
454         }
455
456         return -1;
457 }
458
459
460 /* 
461  * Print addresses stored in hash table 
462  */
463 int addr_hash_table_mi_print(struct addr_list** table, struct mi_node* rpl)
464 {
465         int i;
466         struct addr_list *np;
467
468         for (i = 0; i < PERM_HASH_SIZE; i++) {
469                 np = table[i];
470                 while (np) {
471                         if (addf_mi_node_child(rpl, 0, 0, 0,
472                                                 "%4d <%u, %s, %u> [%s]",
473                                                 i, np->grp, ip_addr2a(&np->addr),
474                                                 np->port, (np->tag.s==NULL)?"":np->tag.s) == 0)
475                                 return -1;
476                         np = np->next;
477                 }
478         }
479         return 0;
480 }
481
482
483 /* 
484  * Free contents of hash table, it doesn't destroy the
485  * hash table itself
486  */
487 void empty_addr_hash_table(struct addr_list **table)
488 {
489         int i;
490         struct addr_list *np, *next;
491
492         for (i = 0; i < PERM_HASH_SIZE; i++) {
493                 np = table[i];
494                 while (np) {
495                         next = np->next;
496                         shm_free(np);
497                         np = next;
498                 }
499                 table[i] = 0;
500         }
501 }
502
503
504 /*
505  * Create and initialize a subnet table
506  */
507 struct subnet* new_subnet_table(void)
508 {
509         struct subnet* ptr;
510
511         /* subnet record [PERM_MAX_SUBNETS] contains in its grp field 
512            the number of subnet records in the subnet table */
513         ptr = (struct subnet *)shm_malloc
514                 (sizeof(struct subnet) * (PERM_MAX_SUBNETS + 1));
515         if (!ptr) {
516                 LM_ERR("no shm memory for subnet table\n");
517                 return 0;
518         }
519         memset(ptr, 0, sizeof(struct subnet) * (PERM_MAX_SUBNETS + 1));
520         return ptr;
521 }
522
523
524 /* 
525  * Add <grp, subnet, mask, port, tag> into subnet table so that table is
526  * kept in increasing ordered according to grp.
527  */
528 int subnet_table_insert(struct subnet* table, unsigned int grp,
529                 ip_addr_t *subnet, unsigned int mask,
530                 unsigned int port, char *tagv)
531 {
532         int i;
533         unsigned int count;
534         str tags;
535
536         count = table[PERM_MAX_SUBNETS].grp;
537
538         if (count == PERM_MAX_SUBNETS) {
539                 LM_CRIT("subnet table is full\n");
540                 return 0;
541         }
542
543         if(tagv==NULL)
544         {
545                 tags.s = NULL;
546                 tags.len = 0;
547         } else {
548                 tags.len = strlen(tagv);
549                 tags.s = (char*)shm_malloc(tags.len+1);
550                 if(tags.s==NULL)
551                 {
552                         LM_ERR("No more shared memory\n");
553                         return 0;
554                 }
555                 strcpy(tags.s, tagv);
556         }
557
558         i = count - 1;
559
560         while ((i >= 0) && (table[i].grp > grp)) {
561                 table[i + 1] = table[i];
562                 i--;
563         }
564
565         table[i + 1].grp = grp;
566         memcpy(&table[i + 1].subnet, subnet, sizeof(ip_addr_t));
567         table[i + 1].port = port;
568         table[i + 1].mask = mask;
569         table[i + 1].tag = tags;
570
571         table[PERM_MAX_SUBNETS].grp = count + 1;
572
573         return 1;
574 }
575
576
577 /* 
578  * Check if an entry exists in subnet table that matches given group, ip_addr,
579  * and port.  Port 0 in subnet table matches any port.
580  */
581 int match_subnet_table(struct subnet* table, unsigned int grp,
582                 ip_addr_t *addr, unsigned int port)
583 {
584         unsigned int count, i;
585         avp_value_t val;
586
587         count = table[PERM_MAX_SUBNETS].grp;
588
589         i = 0;
590         while ((i < count) && (table[i].grp < grp))
591                 i++;
592
593         if (i == count) return -1;
594
595         while ((i < count) && (table[i].grp == grp)) {
596                 if (((table[i].port == port) || (table[i].port == 0))
597                         && (ip_addr_match_net(addr, &table[i].subnet, table[i].mask)==0))
598                 {
599                         if (tag_avp.n && table[i].tag.s) {
600                                 val.s = table[i].tag;
601                                 if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
602                                         LM_ERR("setting of tag_avp failed\n");
603                                         return -1;
604                                 }
605                         }
606                         return 1;
607                 }
608                 i++;
609         }
610
611         return -1;
612 }
613
614
615 /* 
616  * Check if an entry exists in subnet table that matches given ip_addr,
617  * and port.  Port 0 in subnet table matches any port.  Return group of
618  * first match or -1 if no match is found.
619  */
620 int find_group_in_subnet_table(struct subnet* table,
621                 ip_addr_t *addr, unsigned int port)
622 {
623         unsigned int count, i;
624
625         count = table[PERM_MAX_SUBNETS].grp;
626
627         i = 0;
628         while (i < count) {
629                 if ( ((table[i].port == port) || (table[i].port == 0))
630                         && (ip_addr_match_net(addr, &table[i].subnet, table[i].mask)==0))
631                         return table[i].grp;
632                 i++;
633         }
634
635         return -1;
636 }
637
638
639 /* 
640  * Print subnets stored in subnet table 
641  */
642 int subnet_table_mi_print(struct subnet* table, struct mi_node* rpl)
643 {
644         unsigned int count, i;
645
646         count = table[PERM_MAX_SUBNETS].grp;
647
648         for (i = 0; i < count; i++) {
649                 if (addf_mi_node_child(rpl, 0, 0, 0,
650                                         "%4d <%u, %s, %u, %u> [%s]",
651                                         i, table[i].grp, ip_addr2a(&table[i].subnet),
652                                         table[i].mask, table[i].port,
653                                         (table[i].tag.s==NULL)?"":table[i].tag.s) == 0) {
654                         return -1;
655                 }
656         }
657         return 0;
658 }
659
660
661 /* 
662  * Empty contents of subnet table
663  */
664 void empty_subnet_table(struct subnet *table)
665 {
666         int i;
667         table[PERM_MAX_SUBNETS].grp = 0;
668         for(i=0; i<PERM_MAX_SUBNETS; i++)
669         {
670                 if(table[i].tag.s!=NULL)
671                 {
672                         shm_free(table[i].tag.s);
673                         table[i].tag.s = NULL;
674                         table[i].tag.len =0;
675                 }
676         }
677 }
678
679
680 /*
681  * Release memory allocated for a subnet table
682  */
683 void free_subnet_table(struct subnet* table)
684 {
685         int i;
686         if (!table)
687                 return;
688         for(i=0; i<PERM_MAX_SUBNETS; i++)
689         {
690                 if(table[i].tag.s!=NULL)
691                 {
692                         shm_free(table[i].tag.s);
693                         table[i].tag.s = NULL;
694                         table[i].tag.len =0;
695                 }
696         }
697
698         shm_free(table);
699 }