permissions.c

Go to the documentation of this file.
00001 /*
00002  * $Id: permissions.c 4657 2008-08-10 22:51:44Z henningw $
00003  *
00004  * PERMISSIONS module
00005  *
00006  * Copyright (C) 2003 Miklós Tirpák (mtirpak@sztaki.hu)
00007  * Copyright (C) 2003 iptel.org
00008  * Copyright (C) 2003-2007 Juha Heinanen
00009  *
00010  * This file is part of Kamailio, a free SIP server.
00011  *
00012  * Kamailio is free software; you can redistribute it and/or modify
00013  * it under the terms of the GNU General Public License as published by
00014  * the Free Software Foundation; either version 2 of the License, or
00015  * (at your option) any later version
00016  *
00017  * Kamailio is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  * GNU General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU General Public License 
00023  * along with this program; if not, write to the Free Software 
00024  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025  *
00026  */
00027  
00028 #include <stdio.h>
00029 #include "permissions.h"
00030 #include "parse_config.h"
00031 #include "trusted.h"
00032 #include "address.h"
00033 #include "hash.h"
00034 #include "mi.h"
00035 #include "../../mem/mem.h"
00036 #include "../../parser/parse_from.h"
00037 #include "../../parser/parse_uri.h"
00038 #include "../../parser/parse_refer_to.h"
00039 #include "../../parser/contact/parse_contact.h"
00040 #include "../../str.h"
00041 #include "../../dset.h"
00042 #include "../../globals.h"
00043 #include "../../mod_fix.h"
00044 #include "../../ut.h"
00045 
00046 MODULE_VERSION
00047 
00048 static rule_file_t allow[MAX_RULE_FILES]; /* Parsed allow files */
00049 static rule_file_t deny[MAX_RULE_FILES];  /* Parsed deny files */
00050 static int rules_num;  /* Number of parsed allow/deny files */
00051 
00052 
00053 /* Module parameter variables */
00054 static char* default_allow_file = DEFAULT_ALLOW_FILE;
00055 static char* default_deny_file = DEFAULT_DENY_FILE;
00056 char* allow_suffix = ".allow";
00057 static char* deny_suffix = ".deny";
00058 
00059 
00060 /* for allow_trusted and allow_address function */
00061 str db_url = {NULL, 0};                    /* Don't connect to the database by default */
00062 
00063 /* for allow_trusted function */
00064 int db_mode = DISABLE_CACHE;               /* Database usage mode: 0=no cache, 1=cache */
00065 str trusted_table = str_init("trusted");   /* Name of trusted table */
00066 str source_col = str_init("src_ip");       /* Name of source address column */
00067 str proto_col = str_init("proto");         /* Name of protocol column */
00068 str from_col = str_init("from_pattern");   /* Name of from pattern column */
00069 str tag_col = str_init("tag");             /* Name of tag column */
00070 str tag_avp_param = {NULL, 0};             /* Peer tag AVP spec */
00071 
00072 /* for allow_address function */
00073 str address_table = str_init("address");   /* Name of address table */
00074 str grp_col = str_init("grp");             /* Name of address group column */
00075 str ip_addr_col = str_init("ip_addr");     /* Name of ip address column */
00076 str mask_col = str_init("mask");           /* Name of mask column */
00077 str port_col = str_init("port");           /* Name of port column */
00078 
00079 
00080 /*
00081  * By default we check all branches
00082  */
00083 static int check_all_branches = 1;
00084 
00085 
00086 /*  
00087  * Convert the name of the files into table index
00088  */
00089 static int load_fixup(void** param, int param_no);
00090 
00091 /*
00092  * Convert the name of the file into table index, this
00093  * function takes just one name, appends .allow and .deny
00094  * to and and the rest is same as in load_fixup
00095  */
00096 static int single_fixup(void** param, int param_no);
00097 
00098 
00099 /*
00100  * Parse pseudo variable parameter
00101  */
00102 static int double_fixup(void** param, int param_no);
00103 
00104 static int allow_routing_0(struct sip_msg* msg, char* str1, char* str2);
00105 static int allow_routing_1(struct sip_msg* msg, char* basename, char* str2);
00106 static int allow_routing_2(struct sip_msg* msg, char* allow_file, char* deny_file);
00107 static int allow_register_1(struct sip_msg* msg, char* basename, char* s);
00108 static int allow_register_2(struct sip_msg* msg, char* allow_file, char* deny_file);
00109 static int allow_uri(struct sip_msg* msg, char* basename, char* uri);
00110 
00111 static int mod_init(void);
00112 static void mod_exit(void);
00113 static int child_init(int rank);
00114 static int mi_trusted_child_init();
00115 static int mi_addr_child_init();
00116 
00117 
00118 /* Exported functions */
00119 static cmd_export_t cmds[] = {
00120    {"allow_routing",  (cmd_function)allow_routing_0,  0, 0, 0,
00121       REQUEST_ROUTE | FAILURE_ROUTE|LOCAL_ROUTE},
00122    {"allow_routing",  (cmd_function)allow_routing_1,  1, single_fixup, 0,
00123       REQUEST_ROUTE | FAILURE_ROUTE|LOCAL_ROUTE},
00124    {"allow_routing",  (cmd_function)allow_routing_2,  2, load_fixup, 0,
00125       REQUEST_ROUTE | FAILURE_ROUTE|LOCAL_ROUTE},
00126    {"allow_register", (cmd_function)allow_register_1, 1, single_fixup, 0,
00127       REQUEST_ROUTE | FAILURE_ROUTE},
00128    {"allow_register", (cmd_function)allow_register_2, 2, load_fixup, 0,
00129       REQUEST_ROUTE | FAILURE_ROUTE},
00130    {"allow_trusted",  (cmd_function)allow_trusted_0,  0, 0, 0,
00131       REQUEST_ROUTE | FAILURE_ROUTE},
00132    {"allow_trusted",  (cmd_function)allow_trusted_2,  2, fixup_pvar_pvar,
00133            fixup_free_pvar_pvar, REQUEST_ROUTE | FAILURE_ROUTE},
00134    {"allow_uri",      (cmd_function)allow_uri, 2, double_fixup, 0,
00135       REQUEST_ROUTE | FAILURE_ROUTE|LOCAL_ROUTE},
00136    {"allow_address",  (cmd_function)allow_address, 3, fixup_igp_pvar_pvar,
00137            fixup_free_igp_pvar_pvar, REQUEST_ROUTE|FAILURE_ROUTE|LOCAL_ROUTE},
00138    {"allow_source_address", (cmd_function)allow_source_address, 1, fixup_igp_null, 0,
00139       REQUEST_ROUTE | FAILURE_ROUTE},
00140    {"allow_source_address_group", (cmd_function)allow_source_address_group, 0, 0, 0,
00141       REQUEST_ROUTE | FAILURE_ROUTE},
00142    {0, 0, 0, 0, 0, 0}
00143 };
00144 
00145 /* Exported parameters */
00146 static param_export_t params[] = {
00147    {"default_allow_file", STR_PARAM, &default_allow_file},
00148    {"default_deny_file",  STR_PARAM, &default_deny_file },
00149    {"check_all_branches", INT_PARAM, &check_all_branches},
00150    {"allow_suffix",       STR_PARAM, &allow_suffix      },
00151    {"deny_suffix",        STR_PARAM, &deny_suffix       },
00152    {"db_url",             STR_PARAM, &db_url.s          },
00153    {"db_mode",            INT_PARAM, &db_mode           },
00154    {"trusted_table",      STR_PARAM, &trusted_table.s   },
00155    {"source_col",         STR_PARAM, &source_col.s      },
00156    {"proto_col",          STR_PARAM, &proto_col.s       },
00157    {"from_col",           STR_PARAM, &from_col.s        },
00158    {"tag_col",            STR_PARAM, &tag_col.s         },
00159    {"peer_tag_avp",       STR_PARAM, &tag_avp_param.s   },
00160    {"address_table",      STR_PARAM, &address_table.s   },
00161    {"grp_col",            STR_PARAM, &grp_col.s         },
00162    {"ip_addr_col",        STR_PARAM, &ip_addr_col.s     },
00163    {"mask_col",           STR_PARAM, &mask_col.s        },
00164    {"port_col",           STR_PARAM, &port_col.s        },
00165    {0, 0, 0}
00166 };
00167 
00168 /*
00169  * Exported MI functions
00170  */
00171 static mi_export_t mi_cmds[] = {
00172    { MI_TRUSTED_RELOAD,  mi_trusted_reload,  MI_NO_INPUT_FLAG,  0,
00173                                        mi_trusted_child_init },
00174    { MI_TRUSTED_DUMP,    mi_trusted_dump,    MI_NO_INPUT_FLAG,  0,  0 },
00175    { MI_ADDRESS_RELOAD,  mi_address_reload,  MI_NO_INPUT_FLAG,  0,
00176                                        mi_addr_child_init },
00177    { MI_ADDRESS_DUMP,    mi_address_dump,    MI_NO_INPUT_FLAG,  0,  0 },
00178    { MI_SUBNET_DUMP,     mi_subnet_dump,     MI_NO_INPUT_FLAG,  0,  0 },
00179    { MI_ALLOW_URI,       mi_allow_uri,       0,  0,  0 },
00180    { 0, 0, 0, 0, 0 }
00181 };
00182 
00183 /* Module interface */
00184 struct module_exports exports = {
00185    "permissions",
00186    DEFAULT_DLFLAGS, /* dlopen flags */
00187    cmds,      /* Exported functions */
00188    params,    /* Exported parameters */
00189    0,         /* exported statistics */
00190    mi_cmds,   /* exported MI functions */
00191    0,         /* exported pseudo-variables */
00192    0,         /* extra processes */
00193    mod_init,  /* module initialization function */
00194    0,         /* response function */
00195    mod_exit,  /* destroy function */
00196    child_init /* child initialization function */
00197 };
00198 
00199 
00200 /*
00201  * Extract path (the beginning of the string
00202  * up to the last / character
00203  * Returns length of the path
00204  */
00205 static int get_path(char* pathname)
00206 {
00207    char* c;
00208    if (!pathname) return 0;
00209    
00210    c = strrchr(pathname, '/');
00211    if (!c) return 0;
00212 
00213    return c - pathname + 1;
00214 }
00215 
00216 
00217 /*
00218  * Prepend path if necessary
00219  */
00220 static char* get_pathname(char* name)
00221 {
00222    char* buffer;
00223    int path_len, name_len;
00224 
00225    if (!name) return 0;
00226    
00227    name_len = strlen(name);
00228    if (strchr(name, '/')) {
00229       buffer = (char*)pkg_malloc(name_len + 1);
00230       if (!buffer) goto err;
00231       strcpy(buffer, name);
00232       return buffer;
00233    } else {
00234       path_len = get_path(cfg_file);
00235       buffer = (char*)pkg_malloc(path_len + name_len + 1);
00236       if (!buffer) goto err;
00237       memcpy(buffer, cfg_file, path_len);
00238       memcpy(buffer + path_len, name, name_len);
00239       buffer[path_len + name_len] = '\0';
00240       return buffer;
00241    }
00242 
00243  err:
00244    LM_ERR("no pkg memory left\n");
00245    return 0;
00246 }
00247 
00248 
00249 /*
00250  * If the file pathname has been parsed already then the
00251  * function returns its index in the tables, otherwise it
00252  * returns -1 to indicate that the file needs to be read
00253  * and parsed yet
00254  */
00255 static int find_index(rule_file_t* array, char* pathname)
00256 {
00257    int i;
00258 
00259    for(i = 0; i < rules_num; i++) {
00260       if (!strcmp(pathname, array[i].filename)) return i;
00261    }
00262 
00263    return -1;
00264 }
00265 
00266 
00267 /*
00268  * Return URI without all the bells and whistles, that means only
00269  * sip:username@domain, resulting buffer is statically allocated and
00270  * zero terminated
00271  */
00272 static char* get_plain_uri(const str* uri)
00273 {
00274    static char buffer[EXPRESSION_LENGTH + 1];
00275    struct sip_uri puri;
00276    int len;
00277 
00278    if (!uri) return 0;
00279 
00280    if (parse_uri(uri->s, uri->len, &puri) < 0) {
00281       LM_ERR("failed to parse URI\n");
00282       return 0;
00283    }
00284    
00285    if (puri.user.len) {
00286       len = puri.user.len + puri.host.len + 5;
00287    } else {
00288       len = puri.host.len + 4;
00289    }
00290 
00291    if (len > EXPRESSION_LENGTH) {
00292       LM_ERR("Request-URI is too long: %d chars\n", len);
00293       return 0;
00294    }
00295    
00296    strcpy(buffer, "sip:");
00297    if (puri.user.len) {
00298       memcpy(buffer + 4, puri.user.s, puri.user.len);
00299            buffer[puri.user.len + 4] = '@';
00300       memcpy(buffer + puri.user.len + 5, puri.host.s, puri.host.len);
00301    } else {
00302       memcpy(buffer + 4, puri.host.s, puri.host.len);
00303    }
00304 
00305    buffer[len] = '\0';
00306    return buffer;
00307 }
00308 
00309 
00310 /*
00311  * determines the permission of the call
00312  * return values:
00313  * -1:   deny
00314  * 1: allow
00315  */
00316 static int check_routing(struct sip_msg* msg, int idx) 
00317 {
00318    struct hdr_field *from;
00319    int len, q;
00320    static char from_str[EXPRESSION_LENGTH+1];
00321    static char ruri_str[EXPRESSION_LENGTH+1];
00322    char* uri_str;
00323    str branch;
00324    int br_idx;
00325 
00326    /* turn off control, allow any routing */
00327    if ((!allow[idx].rules) && (!deny[idx].rules)) {
00328       LM_DBG("no rules => allow any routing\n");
00329       return 1;
00330    }
00331    
00332    /* looking for FROM HF */
00333         if ((!msg->from) && (parse_headers(msg, HDR_FROM_F, 0) == -1)) {
00334                 LM_ERR("failed to parse message\n");
00335                 return -1;
00336         }
00337    
00338    if (!msg->from) {
00339       LM_ERR("FROM header field not found\n");
00340       return -1;
00341    }
00342    
00343    /* we must call parse_from_header explicitly */
00344         if ((!(msg->from)->parsed) && (parse_from_header(msg) < 0)) {
00345                 LM_ERR("failed to parse From body\n");
00346                 return -1;
00347         }
00348    
00349    from = msg->from;
00350    len = ((struct to_body*)from->parsed)->uri.len;
00351    if (len > EXPRESSION_LENGTH) {
00352                 LM_ERR("From header field is too long: %d chars\n", len);
00353                 return -1;
00354    }
00355    strncpy(from_str, ((struct to_body*)from->parsed)->uri.s, len);
00356    from_str[len] = '\0';
00357    
00358    /* looking for request URI */
00359    if (parse_sip_msg_uri(msg) < 0) {
00360            LM_ERR("uri parsing failed\n");
00361            return -1;
00362    }
00363    
00364    len = msg->parsed_uri.user.len + msg->parsed_uri.host.len + 5;
00365    if (len > EXPRESSION_LENGTH) {
00366                 LM_ERR("Request URI is too long: %d chars\n", len);
00367                 return -1;
00368    }
00369    
00370    strcpy(ruri_str, "sip:");
00371    memcpy(ruri_str + 4, msg->parsed_uri.user.s, msg->parsed_uri.user.len);
00372    ruri_str[msg->parsed_uri.user.len + 4] = '@';
00373    memcpy(ruri_str + msg->parsed_uri.user.len + 5, msg->parsed_uri.host.s, msg->parsed_uri.host.len);
00374    ruri_str[len] = '\0';
00375    
00376         LM_DBG("looking for From: %s Request-URI: %s\n", from_str, ruri_str);
00377         /* rule exists in allow file */
00378    if (search_rule(allow[idx].rules, from_str, ruri_str)) {
00379       if (check_all_branches) goto check_branches;
00380          LM_DBG("allow rule found => routing is allowed\n");
00381       return 1;
00382    }
00383    
00384    /* rule exists in deny file */
00385    if (search_rule(deny[idx].rules, from_str, ruri_str)) {
00386       LM_DBG("deny rule found => routing is denied\n");
00387       return -1;
00388    }
00389 
00390    if (!check_all_branches) {
00391       LM_DBG("neither allow nor deny rule found => routing is allowed\n");
00392       return 1;
00393    }
00394 
00395  check_branches:
00396    for( br_idx=0 ; (branch.s=get_branch(br_idx,&branch.len,&q,0,0,0,0))!=0 ;
00397    br_idx++ ) {
00398       uri_str = get_plain_uri(&branch);
00399       if (!uri_str) {
00400          LM_ERR("failed to extract plain URI\n");
00401          return -1;
00402       }
00403       LM_DBG("looking for From: %s Branch: %s\n", from_str, uri_str);
00404       
00405       if (search_rule(allow[idx].rules, from_str, uri_str)) {
00406          continue;
00407       }
00408       
00409       if (search_rule(deny[idx].rules, from_str, uri_str)) {
00410          LM_DBG("deny rule found for one of branches => routing"
00411                 "is denied\n");
00412          return -1;
00413       }
00414    }
00415    
00416    LM_DBG("check of branches passed => routing is allowed\n");
00417    return 1;
00418 }
00419 
00420 
00421 /*  
00422  * Convert the name of the files into table index
00423  */
00424 static int load_fixup(void** param, int param_no)
00425 {
00426    char* pathname;
00427    int idx;
00428    rule_file_t* table;
00429 
00430    if (param_no == 1) {
00431       table = allow;
00432    } else {
00433       table = deny;
00434    }
00435 
00436    pathname = get_pathname(*param);
00437    idx = find_index(table, pathname);
00438 
00439    if (idx == -1) {
00440            /* Not opened yet, open the file and parse it */
00441       table[rules_num].filename = pathname;
00442       table[rules_num].rules = parse_config_file(pathname);
00443       if (table[rules_num].rules) {
00444          LM_DBG("file (%s) parsed\n", pathname);
00445       } else {
00446          LM_WARN("file (%s) not found => empty rule set\n", pathname);
00447       }
00448       *param = (void*)(long)rules_num;
00449       if (param_no == 2) rules_num++;
00450    } else {
00451            /* File already parsed, re-use it */
00452       LM_DBG("file (%s) already loaded, re-using\n", pathname);
00453       pkg_free(pathname);
00454       *param = (void*)(long)idx;
00455    }
00456 
00457    return 0;
00458 }
00459 
00460 
00461 /*
00462  * Convert the name of the file into table index
00463  */
00464 static int single_fixup(void** param, int param_no)
00465 {
00466    char* buffer;
00467    void* tmp;
00468    int param_len, ret, suffix_len;
00469 
00470    if (param_no != 1) return 0;
00471 
00472    param_len = strlen((char*)*param);
00473    if (strlen(allow_suffix) > strlen(deny_suffix)) {
00474       suffix_len = strlen(allow_suffix);
00475    } else {
00476       suffix_len = strlen(deny_suffix);
00477    }
00478 
00479    buffer = pkg_malloc(param_len + suffix_len + 1);
00480    if (!buffer) {
00481       LM_ERR("no pkg memory left\n");
00482       return -1;
00483    }
00484 
00485    strcpy(buffer, (char*)*param);
00486    strcat(buffer, allow_suffix);
00487    tmp = buffer; 
00488    ret = load_fixup(&tmp, 1);
00489 
00490    strcpy(buffer + param_len, deny_suffix);
00491    tmp = buffer;
00492    ret |= load_fixup(&tmp, 2);
00493 
00494    *param = tmp;
00495 
00496    pkg_free(buffer);
00497    return ret;
00498 }
00499 
00500 
00501 /*
00502  * Convert the name of the file into table index and pvar into parsed pseudo
00503  * variable specification
00504  */
00505 static int double_fixup(void** param, int param_no)
00506 {
00507    char* buffer;
00508    void* tmp;
00509    int param_len, ret, suffix_len;
00510    pv_spec_t *sp;
00511    str s;
00512 
00513    if (param_no == 1) { /* basename */
00514        param_len = strlen((char*)*param);
00515        if (strlen(allow_suffix) > strlen(deny_suffix)) {
00516       suffix_len = strlen(allow_suffix);
00517        } else {
00518       suffix_len = strlen(deny_suffix);
00519        }
00520 
00521        buffer = pkg_malloc(param_len + suffix_len + 1);
00522        if (!buffer) {
00523       LM_ERR("no pkg memory left\n");
00524       return -1;
00525        }
00526        
00527        strcpy(buffer, (char*)*param);
00528        strcat(buffer, allow_suffix);
00529        tmp = buffer; 
00530        ret = load_fixup(&tmp, 1);
00531 
00532        strcpy(buffer + param_len, deny_suffix);
00533        tmp = buffer;
00534        ret |= load_fixup(&tmp, 2);
00535 
00536        *param = tmp;
00537        pkg_free(buffer);
00538 
00539        return 0;
00540 
00541    } else if (param_no == 2) { /* pseudo variable */
00542 
00543        sp = (pv_spec_t*)pkg_malloc(sizeof(pv_spec_t));
00544        if (sp == 0) {
00545       LM_ERR("no pkg memory left\n");
00546       return -1;
00547        }
00548       s.s = (char*)*param; s.len = strlen(s.s);
00549        if (pv_parse_spec(&s, sp) == 0) {
00550       LM_ERR("parsing of pseudo variable %s failed!\n", (char*)*param);
00551       pkg_free(sp);
00552       return -1;
00553        }
00554 
00555        if (sp->type == PVT_NULL) {
00556       LM_ERR("bad pseudo variable\n");
00557       pkg_free(sp);
00558       return -1;
00559        }
00560 
00561        *param = (void*)sp;
00562 
00563        return 0;
00564    }
00565 
00566    *param = (void *)0;
00567 
00568    return 0;
00569 }
00570 
00571 
00572 /*
00573  * module initialization function 
00574  */
00575 static int mod_init(void)
00576 {
00577    if (db_url.s)
00578       db_url.len = strlen(db_url.s);
00579    trusted_table.len = strlen(trusted_table.s);
00580    source_col.len = strlen(source_col.s);
00581    proto_col.len = strlen(proto_col.s);
00582    from_col.len = strlen(from_col.s);
00583    tag_col.len = strlen(tag_col.s);
00584    if (tag_avp_param.s)
00585       tag_avp_param.len = strlen(tag_avp_param.s);
00586    address_table.len = strlen(address_table.s);
00587    grp_col.len = strlen(grp_col.s);
00588    ip_addr_col.len = strlen(ip_addr_col.s);
00589    mask_col.len = strlen(mask_col.s);
00590    port_col.len = strlen(port_col.s);
00591 
00592    allow[0].filename = get_pathname(default_allow_file);
00593    allow[0].rules = parse_config_file(allow[0].filename);
00594    if (allow[0].rules) {
00595       LM_DBG("default allow file (%s) parsed\n", allow[0].filename);
00596    } else {
00597       LM_WARN("default allow file (%s) not found => empty rule set\n",
00598          allow[0].filename);
00599    }
00600 
00601    deny[0].filename = get_pathname(default_deny_file);
00602    deny[0].rules = parse_config_file(deny[0].filename);
00603    if (deny[0].rules) {
00604       LM_DBG("default deny file (%s) parsed\n", deny[0].filename);
00605    } else {
00606       LM_WARN("default deny file (%s) not found => empty rule set\n",
00607          deny[0].filename);
00608    }
00609 
00610    if (init_trusted() != 0) {
00611       LM_ERR("failed to initialize the allow_trusted function\n");
00612       return -1;
00613    }
00614 
00615    if (init_tag_avp(&tag_avp_param) < 0) {
00616       LM_ERR("failed to process peer_tag_avp AVP param\n");
00617       return -1;
00618    }
00619 
00620    if (init_addresses() != 0) {
00621       LM_ERR("failed to initialize the allow_address function\n");
00622       return -1;
00623    }
00624 
00625    if ((db_mode != DISABLE_CACHE) && (db_mode != ENABLE_CACHE)) {
00626            LM_ERR("invalid db_mode value: %d\n", db_mode);
00627       return -1;
00628    }
00629        
00630    rules_num = 1;
00631    return 0;
00632 }
00633 
00634 
00635 static int child_init(int rank)
00636 {
00637    if (init_child_trusted(rank) == -1)
00638       return -1;
00639    return 0;
00640 }
00641 
00642 
00643 static int mi_trusted_child_init(void)
00644 {
00645     return mi_init_trusted();
00646 }
00647 
00648 
00649 static int mi_addr_child_init(void)
00650 {
00651     return mi_init_addresses();
00652 }
00653 
00654 
00655 /* 
00656  * destroy function 
00657  */
00658 static void mod_exit(void) 
00659 {
00660    int i;
00661 
00662    for(i = 0; i < rules_num; i++) {
00663       free_rule(allow[i].rules);
00664       pkg_free(allow[i].filename);
00665 
00666       free_rule(deny[i].rules);
00667       pkg_free(deny[i].filename);
00668    }
00669 
00670    clean_trusted();
00671 
00672    clean_addresses();
00673 }
00674 
00675 
00676 /*
00677  * Uses default rule files from the module parameters
00678  */
00679 int allow_routing_0(struct sip_msg* msg, char* str1, char* str2)
00680 {
00681    return check_routing(msg, 0);
00682 }
00683 
00684 
00685 int allow_routing_1(struct sip_msg* msg, char* basename, char* s)
00686 {
00687    return check_routing(msg, (int)(long)basename);
00688 }
00689 
00690 
00691 /*
00692  * Accepts allow and deny files as parameters
00693  */
00694 int allow_routing_2(struct sip_msg* msg, char* allow_file, char* deny_file)
00695 {
00696         /* Index converted by load_lookup */
00697    return check_routing(msg, (int)(long)allow_file);
00698 }
00699 
00700 
00701 /*
00702  * Test of REGISTER messages. Creates To-Contact pairs and compares them
00703  * against rules in allow and deny files passed as parameters. The function
00704  * iterates over all Contacts and creates a pair with To for each contact 
00705  * found. That allows to restrict what IPs may be used in registrations, for
00706  * example
00707  */
00708 static int check_register(struct sip_msg* msg, int idx)
00709 {
00710    int len;
00711    static char to_str[EXPRESSION_LENGTH + 1];
00712    char* contact_str;
00713    contact_t* c;
00714 
00715         /* turn off control, allow any routing */
00716    if ((!allow[idx].rules) && (!deny[idx].rules)) {
00717       LM_DBG("no rules => allow any registration\n");
00718       return 1;
00719    }
00720 
00721         /*
00722          * Note: We do not parse the whole header field here although the message can
00723          * contain multiple Contact header fields. We try contacts one by one and if one
00724          * of them causes reject then we don't look at others, this could improve performance
00725          * a little bit in some situations
00726          */
00727    if (parse_headers(msg, HDR_TO_F | HDR_CONTACT_F, 0) == -1) {
00728       LM_ERR("failed to parse headers\n");
00729       return -1;
00730    }
00731 
00732    if (!msg->to) {
00733       LM_ERR("To or Contact not found\n");
00734       return -1;
00735    }
00736    
00737    if (!msg->contact) {
00738            /* REGISTER messages that contain no Contact header field
00739             * are allowed. Such messages do not modify the contents of
00740             * the user location database anyway and thus are not harmful
00741             */
00742       LM_DBG("no Contact found, allowing\n");
00743       return 1;
00744    }
00745 
00746         /* Check if the REGISTER message contains start Contact and if
00747          * so then allow it
00748          */
00749    if (parse_contact(msg->contact) < 0) {
00750       LM_ERR("failed to parse Contact HF\n");
00751       return -1;
00752    }
00753 
00754    if (((contact_body_t*)msg->contact->parsed)->star) {
00755       LM_DBG("* Contact found, allowing\n");
00756       return 1;
00757    }
00758 
00759    len = ((struct to_body*)msg->to->parsed)->uri.len;
00760    if (len > EXPRESSION_LENGTH) {
00761                 LM_ERR("To header field is too long: %d chars\n", len);
00762                 return -1;
00763    }
00764    strncpy(to_str, ((struct to_body*)msg->to->parsed)->uri.s, len);
00765    to_str[len] = '\0';
00766 
00767    if (contact_iterator(&c, msg, 0) < 0) {
00768       return -1;
00769    }
00770 
00771    while(c) {
00772       contact_str = get_plain_uri(&c->uri);
00773       if (!contact_str) {
00774          LM_ERR("can't extract plain Contact URI\n");
00775          return -1;
00776       }
00777 
00778       LM_DBG("looking for To: %s Contact: %s\n", to_str, contact_str);
00779 
00780            /* rule exists in allow file */
00781       if (search_rule(allow[idx].rules, to_str, contact_str)) {
00782          if (check_all_branches) goto skip_deny;
00783       }
00784    
00785            /* rule exists in deny file */
00786       if (search_rule(deny[idx].rules, to_str, contact_str)) {
00787          LM_DBG("deny rule found => Register denied\n");
00788          return -1;
00789       }
00790 
00791    skip_deny:
00792       if (contact_iterator(&c, msg, c) < 0) {
00793          return -1;
00794       }
00795    }
00796 
00797    LM_DBG("no contact denied => Allowed\n");
00798    return 1;
00799 }
00800 
00801 
00802 int allow_register_1(struct sip_msg* msg, char* basename, char* s)
00803 {
00804    return check_register(msg, (int)(long)basename);
00805 }
00806 
00807 
00808 int allow_register_2(struct sip_msg* msg, char* allow_file, char* deny_file)
00809 {
00810    return check_register(msg, (int)(long)allow_file);
00811 }
00812 
00813 
00814 /*
00815  * determines the permission to an uri
00816  * return values:
00817  * -1:   deny
00818  * 1: allow
00819  */
00820 static int allow_uri(struct sip_msg* msg, char* _idx, char* _sp) 
00821 {
00822    struct hdr_field *from;
00823    int idx, len;
00824    static char from_str[EXPRESSION_LENGTH+1];
00825    static char uri_str[EXPRESSION_LENGTH+1];
00826    pv_spec_t *sp;
00827    pv_value_t pv_val;
00828 
00829    idx = (int)(long)_idx;
00830    sp = (pv_spec_t *)_sp;
00831    
00832    /* turn off control, allow any uri */
00833    if ((!allow[idx].rules) && (!deny[idx].rules)) {
00834       LM_DBG("no rules => allow any uri\n");
00835       return 1;
00836    }
00837    
00838    /* looking for FROM HF */
00839         if ((!msg->from) && (parse_headers(msg, HDR_FROM_F, 0) == -1)) {
00840                 LM_ERR("failed to parse message\n");
00841                 return -1;
00842         }
00843    
00844    if (!msg->from) {
00845       LM_ERR("FROM header field not found\n");
00846       return -1;
00847    }
00848    
00849    /* we must call parse_from_header explicitly */
00850         if ((!(msg->from)->parsed) && (parse_from_header(msg) < 0)) {
00851                 LM_ERR("failed to parse From body\n");
00852                 return -1;
00853         }
00854    
00855    from = msg->from;
00856    len = ((struct to_body*)from->parsed)->uri.len;
00857    if (len > EXPRESSION_LENGTH) {
00858                LM_ERR("From header field is too long: %d chars\n", len);
00859                 return -1;
00860    }
00861    strncpy(from_str, ((struct to_body*)from->parsed)->uri.s, len);
00862    from_str[len] = '\0';
00863 
00864    if (sp && (pv_get_spec_value(msg, sp, &pv_val) == 0)) {
00865        if (pv_val.flags & PV_VAL_STR) {
00866       if (pv_val.rs.len > EXPRESSION_LENGTH) {
00867           LM_ERR("pseudo variable value is too "
00868                "long: %d chars\n", pv_val.rs.len);
00869           return -1;
00870       }
00871       strncpy(uri_str, pv_val.rs.s, pv_val.rs.len);
00872       uri_str[pv_val.rs.len] = '\0';
00873        } else {
00874       LM_ERR("pseudo variable value is not string\n");
00875       return -1;
00876        }
00877    } else {
00878        LM_ERR("cannot get pseudo variable value\n");
00879        return -1;
00880    }
00881 
00882     LM_DBG("looking for From: %s URI: %s\n", from_str, uri_str);
00883         /* rule exists in allow file */
00884    if (search_rule(allow[idx].rules, from_str, uri_str)) {
00885          LM_DBG("allow rule found => URI is allowed\n");
00886       return 1;
00887    }
00888    
00889    /* rule exists in deny file */
00890    if (search_rule(deny[idx].rules, from_str, uri_str)) {
00891        LM_DBG("deny rule found => URI is denied\n");
00892        return -1;
00893    }
00894 
00895    LM_DBG("neither allow nor deny rule found => URI is allowed\n");
00896 
00897    return 1;
00898 }
00899 
00900 
00901 /*
00902  * Test URI against Contact.
00903  */
00904 int allow_test(char *file, char *uri, char *contact)
00905 {
00906     char *pathname;
00907     int idx;
00908     
00909     pathname = get_pathname(file);
00910     if (!pathname) {
00911    LM_ERR("Cannot get pathname of <%s>\n", file);
00912    return 0;
00913     }
00914 
00915     idx = find_index(allow, pathname);
00916     if (idx == -1) {
00917    LM_ERR("File <%s> has not been loaded\n", pathname);
00918    pkg_free(pathname);
00919    return 0;
00920     }
00921 
00922     pkg_free(pathname);
00923    
00924     /* turn off control, allow any routing */
00925     if ((!allow[idx].rules) && (!deny[idx].rules)) {
00926    LM_DBG("No rules => Allowed\n");
00927    return 1;
00928     }
00929     
00930     LM_DBG("Looking for URI: %s, Contact: %s\n", uri, contact);
00931 
00932     /* rule exists in allow file */
00933     if (search_rule(allow[idx].rules, uri, contact)) {
00934    LM_DBG("Allow rule found => Allowed\n");
00935    return 1;
00936     }
00937    
00938     /* rule exists in deny file */
00939     if (search_rule(deny[idx].rules, uri, contact)) {
00940    LM_DBG("Deny rule found => Denied\n");
00941    return 0;
00942     }
00943 
00944     LM_DBG("Neither allow or deny rule found => Allowed\n");
00945     return 1;
00946 
00947 }

Generated on Thu May 24 02:00:29 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6