trusted.c

Go to the documentation of this file.
00001 /*
00002  * $Id: trusted.c 4518 2008-07-28 15:39:28Z henningw $
00003  *
00004  * allow_trusted related functions
00005  *
00006  * Copyright (C) 2003 Juha Heinanen
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  * History:
00025  * --------
00026  *  2004-06-07  updated to the new DB api, moved reload_trusted_table (andrei)
00027  */
00028 
00029 #include <sys/types.h>
00030 #include <regex.h>
00031 #include <string.h>
00032 
00033 #include "permissions.h"
00034 #include "hash.h"
00035 #include "../../config.h"
00036 #include "../../db/db.h"
00037 #include "../../ip_addr.h"
00038 #include "../../mem/shm_mem.h"
00039 #include "../../parser/msg_parser.h"
00040 #include "../../parser/parse_from.h"
00041 #include "../../usr_avp.h"
00042 
00043 #define TABLE_VERSION 4
00044 
00045 struct trusted_list ***hash_table;     /* Pointer to current hash table pointer */
00046 struct trusted_list **hash_table_1;   /* Pointer to hash table 1 */
00047 struct trusted_list **hash_table_2;   /* Pointer to hash table 2 */
00048 
00049 
00050 static db_con_t* db_handle = 0;
00051 static db_func_t perm_dbf;
00052 
00053 
00054 /*
00055  * Reload trusted table to new hash table and when done, make new hash table
00056  * current one.
00057  */
00058 int reload_trusted_table(void)
00059 {
00060    db_key_t cols[4];
00061    db_res_t* res = NULL;
00062    db_row_t* row;
00063    db_val_t* val;
00064 
00065    struct trusted_list **new_hash_table;
00066    int i;
00067 
00068    char *pattern, *tag;
00069 
00070    cols[0] = &source_col;
00071    cols[1] = &proto_col;
00072    cols[2] = &from_col;
00073    cols[3] = &tag_col;
00074 
00075    if (perm_dbf.use_table(db_handle, &trusted_table) < 0) {
00076       LM_ERR("failed to use trusted table\n");
00077       return -1;
00078    }
00079 
00080    if (perm_dbf.query(db_handle, NULL, 0, NULL, cols, 0, 4, 0, &res) < 0) {
00081       LM_ERR("failed to query database\n");
00082       return -1;
00083    }
00084 
00085    /* Choose new hash table and free its old contents */
00086    if (*hash_table == hash_table_1) {
00087       empty_hash_table(hash_table_2);
00088       new_hash_table = hash_table_2;
00089    } else {
00090       empty_hash_table(hash_table_1);
00091       new_hash_table = hash_table_1;
00092    }
00093 
00094    row = RES_ROWS(res);
00095 
00096    LM_DBG("number of rows in trusted table: %d\n", RES_ROW_N(res));
00097       
00098    for (i = 0; i < RES_ROW_N(res); i++) {
00099        val = ROW_VALUES(row + i);
00100        if ((ROW_N(row + i) == 4) &&
00101       (VAL_TYPE(val) == DB_STRING) && !VAL_NULL(val) &&
00102       (VAL_TYPE(val + 1) == DB_STRING) && !VAL_NULL(val + 1) &&
00103       (VAL_NULL(val + 2) ||
00104        ((VAL_TYPE(val + 2) == DB_STRING) && !VAL_NULL(val + 2))) &&
00105       (VAL_NULL(val + 3) ||
00106        ((VAL_TYPE(val + 3) == DB_STRING) && !VAL_NULL(val + 3)))) {
00107       if (VAL_NULL(val + 2)) {
00108           pattern = 0;
00109       } else {
00110           pattern = (char *)VAL_STRING(val + 2);
00111       }
00112       if (VAL_NULL(val + 3)) {
00113           tag = 0;
00114       } else {
00115           tag = (char *)VAL_STRING(val + 3);
00116       }
00117       if (hash_table_insert(new_hash_table,
00118                   (char *)VAL_STRING(val),
00119                   (char *)VAL_STRING(val + 1),
00120                   pattern, tag) == -1) {
00121           LM_ERR("hash table problem\n");
00122           perm_dbf.free_result(db_handle, res);
00123           return -1;
00124       }
00125       LM_DBG("tuple <%s, %s, %s, %s> inserted into trusted hash "
00126           "table\n", VAL_STRING(val), VAL_STRING(val + 1),
00127           pattern, tag);
00128        } else {
00129       LM_ERR("database problem\n");
00130       perm_dbf.free_result(db_handle, res);
00131       return -1;
00132        }
00133    }
00134 
00135    perm_dbf.free_result(db_handle, res);
00136 
00137    *hash_table = new_hash_table;
00138 
00139    LM_DBG("trusted table reloaded successfully.\n");
00140    
00141    return 1;
00142 }
00143 
00144 
00145 /*
00146  * Initialize data structures
00147  */
00148 int init_trusted(void)
00149 {
00150    /* Check if hash table needs to be loaded from trusted table */
00151    if (!db_url.s) {
00152       LM_INFO("db_url parameter of permissions module not set, "
00153          "disabling allow_trusted\n");
00154       return 0;
00155    } else {
00156       if (db_bind_mod(&db_url, &perm_dbf) < 0) {
00157          LM_ERR("load a database support module\n");
00158          return -1;
00159       }
00160 
00161       if (!DB_CAPABILITY(perm_dbf, DB_CAP_QUERY)) {
00162          LM_ERR("database module does not implement 'query' function\n");
00163          return -1;
00164       }
00165    }
00166 
00167    hash_table_1 = hash_table_2 = 0;
00168    hash_table = 0;
00169 
00170    if (db_mode == ENABLE_CACHE) {
00171       db_handle = perm_dbf.init(&db_url);
00172       if (!db_handle) {
00173          LM_ERR("unable to connect database\n");
00174          return -1;
00175       }
00176 
00177       if(db_check_table_version(&perm_dbf, db_handle, &trusted_table, TABLE_VERSION) < 0) {
00178          LM_ERR("error during table version check.\n");
00179          perm_dbf.close(db_handle);
00180          return -1;
00181       }
00182 
00183       hash_table_1 = new_hash_table();
00184       if (!hash_table_1) return -1;
00185       
00186       hash_table_2  = new_hash_table();
00187       if (!hash_table_2) goto error;
00188       
00189       hash_table = (struct trusted_list ***)shm_malloc
00190          (sizeof(struct trusted_list **));
00191       if (!hash_table) goto error;
00192 
00193       *hash_table = hash_table_1;
00194 
00195       if (reload_trusted_table() == -1) {
00196          LM_CRIT("reload of trusted table failed\n");
00197          goto error;
00198       }
00199 
00200       perm_dbf.close(db_handle);
00201       db_handle = 0;
00202    }
00203    return 0;
00204 
00205 error:
00206    if (hash_table_1) {
00207       free_hash_table(hash_table_1);
00208       hash_table_1 = 0;
00209    }
00210    if (hash_table_2) {
00211       free_hash_table(hash_table_2);
00212       hash_table_2 = 0;
00213    }
00214    if (hash_table) {
00215       shm_free(hash_table);
00216       hash_table = 0;
00217    }
00218    perm_dbf.close(db_handle);
00219    db_handle = 0;
00220    return -1;
00221 }
00222 
00223 
00224 /*
00225  * Open database connections if necessary
00226  */
00227 int init_child_trusted(int rank)
00228 {
00229    if (!db_url.s) {
00230       return 0;
00231    }
00232    
00233    /* Check if database is needed by child */
00234    if (db_mode==DISABLE_CACHE && rank>0) {
00235       db_handle = perm_dbf.init(&db_url);
00236       if (!db_handle) {
00237          LM_ERR("unable to connect database\n");
00238          return -1;
00239       }
00240 
00241       if(db_check_table_version(&perm_dbf, db_handle, &trusted_table, TABLE_VERSION) < 0) {
00242          LM_ERR("error during table version check.\n");
00243          perm_dbf.close(db_handle);
00244          return -1;
00245       }
00246 
00247    }
00248 
00249    return 0;
00250 }
00251 
00252 
00253 /*
00254  * Open database connection if necessary
00255  */
00256 int mi_init_trusted(void)
00257 {
00258     if (!db_url.s || db_handle) return 0;
00259     db_handle = perm_dbf.init(&db_url);
00260     if (!db_handle) {
00261    LM_ERR("unable to connect database\n");
00262    return -1;
00263     }
00264     return 0;
00265 }
00266 
00267 
00268 /*
00269  * Close connections and release memory
00270  */
00271 void clean_trusted(void)
00272 {
00273    if (hash_table_1) free_hash_table(hash_table_1);
00274    if (hash_table_2) free_hash_table(hash_table_2);
00275    if (hash_table) shm_free(hash_table);
00276 }
00277 
00278 
00279 /*
00280  * Matches protocol string against the protocol of the request.  Returns 1 on
00281  * success and 0 on failure.
00282  */
00283 static inline int match_proto(const char *proto_string, int proto_int)
00284 {
00285    if (strcasecmp(proto_string, "any") == 0) return 1;
00286    
00287    if (proto_int == PROTO_UDP) {
00288       if (strcasecmp(proto_string, "udp") == 0) {
00289          return 1;
00290       } else {
00291          return 0;
00292       }
00293    }
00294    
00295    if (proto_int == PROTO_TCP) {
00296       if (strcasecmp(proto_string, "tcp") == 0) {
00297          return 1;
00298       } else {
00299          return 0;
00300       }
00301    }
00302    
00303    if (proto_int == PROTO_TLS) {
00304       if (strcasecmp(proto_string, "tls") == 0) {
00305          return 1;
00306       } else {
00307          return 0;
00308       }
00309    }
00310    
00311    if (proto_int == PROTO_SCTP) {
00312       if (strcasecmp(proto_string, "sctp") == 0) {
00313          return 1;
00314       } else {
00315          return 0;
00316       }
00317    }
00318 
00319    LM_ERR("unknown request protocol\n");
00320 
00321    return 0;
00322 }
00323 
00324 /*
00325  * Matches from uri against patterns returned from database.  Returns 1 when
00326  * first pattern matches and 0 if none of the patterns match.
00327  */
00328 static int match_res(struct sip_msg* msg, int proto, db_res_t* _r)
00329 {
00330         int i, tag_avp_type;
00331    str uri;
00332    char uri_string[MAX_URI_SIZE+1];
00333    db_row_t* row;
00334    db_val_t* val;
00335    regex_t preg;
00336    int_str tag_avp, avp_val;
00337 
00338    if (parse_from_header(msg) < 0) return -1;
00339    uri = get_from(msg)->uri;
00340    if (uri.len > MAX_URI_SIZE) {
00341       LM_ERR("message has From URI too large\n");
00342       return -1;
00343    }
00344    memcpy(uri_string, uri.s, uri.len);
00345    uri_string[uri.len] = (char)0;
00346 
00347    row = RES_ROWS(_r);
00348       
00349    for(i = 0; i < RES_ROW_N(_r); i++) {
00350        val = ROW_VALUES(row + i);
00351        if ((ROW_N(row + i) == 3) &&
00352       (VAL_TYPE(val) == DB_STRING) && !VAL_NULL(val) &&
00353       match_proto(VAL_STRING(val), proto) &&
00354       (VAL_NULL(val + 1) ||
00355        ((VAL_TYPE(val + 1) == DB_STRING) && !VAL_NULL(val + 1))) &&
00356       (VAL_NULL(val + 2) ||
00357        ((VAL_TYPE(val + 2) == DB_STRING) && !VAL_NULL(val + 2))))
00358        {
00359       if (VAL_NULL(val + 1)) goto found;
00360       if (regcomp(&preg, (char *)VAL_STRING(val + 1), REG_NOSUB)) {
00361           LM_ERR("invalid regular expression\n");
00362           continue;
00363       }
00364       if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
00365           regfree(&preg);
00366           continue;
00367       } else {
00368           regfree(&preg);
00369           goto found;
00370       }
00371        }
00372    }
00373    return -1;
00374 
00375 found:
00376    get_tag_avp(&tag_avp, &tag_avp_type);
00377    if (tag_avp.n && !VAL_NULL(val + 2)) {
00378        avp_val.s.s = (char *)VAL_STRING(val + 2);
00379        avp_val.s.len = strlen(avp_val.s.s);
00380        if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, avp_val) != 0) {
00381       LM_ERR("failed to set of tag_avp failed\n");
00382       return -1;
00383        }
00384    }
00385    return 1;
00386 }
00387 
00388 
00389 /*
00390  * Checks based on given source IP address and protocol, and From URI
00391  * of request if request can be trusted without authentication.
00392  */
00393 int allow_trusted(struct sip_msg* msg, char *src_ip, int proto) 
00394 {
00395    int result;
00396    db_res_t* res = NULL;
00397    
00398    db_key_t keys[1];
00399    db_val_t vals[1];
00400    db_key_t cols[3];
00401    
00402    if (!db_url.s) {
00403       LM_ERR("db_url parameter has not been set\n");
00404       return -1;
00405    }
00406 
00407    if (db_mode == DISABLE_CACHE) {
00408       keys[0] = &source_col;
00409       cols[0] = &proto_col;
00410       cols[1] = &from_col;
00411       cols[2] = &tag_col;
00412 
00413       if (perm_dbf.use_table(db_handle, &trusted_table) < 0) {
00414          LM_ERR("failed to use trusted table\n");
00415          return -1;
00416       }
00417       
00418       VAL_TYPE(vals) = DB_STRING;
00419       VAL_NULL(vals) = 0;
00420       VAL_STRING(vals) = src_ip;
00421 
00422       if (perm_dbf.query(db_handle, keys, 0, vals, cols, 1, 3, 0,
00423                &res) < 0){
00424          LM_ERR("failed to query database\n");
00425          perm_dbf.close(db_handle);
00426          return -1;
00427       }
00428 
00429       if (RES_ROW_N(res) == 0) {
00430          perm_dbf.free_result(db_handle, res);
00431          return -1;
00432       }
00433       
00434       result = match_res(msg, proto, res);
00435       perm_dbf.free_result(db_handle, res);
00436       return result;
00437    } else {
00438       return match_hash_table(*hash_table, msg, src_ip, proto);
00439    }
00440 }
00441 
00442 
00443 /*
00444  * Checks based on request's source address, protocol, and From URI
00445  * if request can be trusted without authentication.
00446  */
00447 int allow_trusted_0(struct sip_msg* _msg, char* str1, char* str2) 
00448 {
00449     return allow_trusted(_msg, ip_addr2a(&(_msg->rcv.src_ip)),
00450           _msg->rcv.proto);
00451 }
00452 
00453 
00454 /*
00455  * Checks based on source address and protocol given in pvar arguments and
00456  * and requests's From URI, if request can be trusted without authentication.
00457  */
00458 int allow_trusted_2(struct sip_msg* _msg, char* _src_ip_sp, char* _proto_sp) 
00459 {
00460     pv_spec_t *src_ip_sp, *proto_sp;
00461     pv_value_t pv_val;
00462     char *src_ip, *proto;
00463     int proto_int;
00464 
00465     src_ip_sp = (pv_spec_t *)_src_ip_sp;
00466     proto_sp = (pv_spec_t *)_proto_sp;
00467     
00468     if (src_ip_sp && (pv_get_spec_value(_msg, src_ip_sp, &pv_val) == 0)) {
00469    if (pv_val.flags & PV_VAL_STR) {
00470        src_ip = pv_val.rs.s;
00471    } else {
00472        LM_ERR("src_ip pvar value is not string\n");
00473        return -1;
00474    }
00475     } else {
00476    LM_ERR("src_ip pvar does not exist or has no value\n");
00477    return -1;
00478     }
00479     
00480     if (proto_sp && (pv_get_spec_value(_msg, proto_sp, &pv_val) == 0)) {
00481    if (pv_val.flags & PV_VAL_STR) {
00482        proto = pv_val.rs.s;
00483    } else {
00484        LM_ERR("proto pvar value is not string\n");
00485        return -1;
00486    }
00487     } else {
00488    LM_ERR("proto pvar does not exist or has no value\n");
00489    return -1;
00490     }
00491 
00492     if (strcmp(proto, "UDP") == 0) {
00493    proto_int = PROTO_UDP;
00494     } else if (strcmp(proto, "TCP") == 0) {
00495    proto_int = PROTO_TCP;
00496     } else if (strcmp(proto, "TLS") == 0) {
00497    proto_int = PROTO_TLS;
00498     } else if (strcmp(proto, "SCTP") == 0) {
00499    proto_int = PROTO_SCTP;
00500     } else {
00501    LM_ERR("unknown protocol %s\n", proto);
00502    return -1;
00503     }
00504 
00505     return allow_trusted(_msg, src_ip, proto_int);
00506 }

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