uri_db/checks.c

Go to the documentation of this file.
00001 /*
00002  * $Id: checks.c 4682 2008-08-12 09:42:21Z henningw $
00003  *
00004  * Various URI checks
00005  *
00006  * Copyright (C) 2001-2004 FhG FOKUS
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  * 2003-02-26: Created by janakj
00027  * 2004-03-20: has_totag introduced (jiri)
00028  * 2004-06-07  updated to the new DB api, added uridb_db_{bind,init,close,ver}
00029  *              (andrei)
00030  */
00031 
00032 #include <string.h>
00033 #include "../../str.h"
00034 #include "../../dprint.h"               /* Debugging */
00035 #include "../../parser/digest/digest.h" /* get_authorized_cred */
00036 #include "../../parser/parse_from.h"
00037 #include "../../parser/parse_uri.h"
00038 #include "../../ut.h"                   /* Handy utilities */
00039 #include "../../db/db.h"                /* Database API */
00040 #include "uridb_mod.h"
00041 #include "checks.h"
00042 
00043 static db_con_t* db_handle = 0;   /* Database connection handle */
00044 static db_func_t uridb_dbf;
00045 
00046 
00047 /*
00048  * Check if a header field contains the same username
00049  * as digest credentials
00050  */
00051 static inline int check_username(struct sip_msg* _m, struct sip_uri *_uri)
00052 {
00053    struct hdr_field* h;
00054    auth_body_t* c;
00055    db_key_t keys[3];
00056    db_val_t vals[3];
00057    db_key_t cols[1];
00058    db_res_t* res = NULL;
00059 
00060    if (!_uri) {
00061       LM_ERR("Bad parameter\n");
00062       return -1;
00063    }
00064 
00065    /* Get authorized digest credentials */
00066    get_authorized_cred(_m->authorization, &h);
00067    if (!h) {
00068       get_authorized_cred(_m->proxy_auth, &h);
00069       if (!h) {
00070          LM_ERR("No authorized credentials found (error in scripts)\n");
00071          LM_ERR("Call {www,proxy}_authorize before calling check_* functions!\n");
00072          return -2;
00073       }
00074    }
00075 
00076    c = (auth_body_t*)(h->parsed);
00077 
00078    /* Parse To/From URI */
00079    /* Make sure that the URI contains username */
00080    if (!_uri->user.len) {
00081       LM_ERR("Username not found in URI\n");
00082       return -4;
00083    }
00084 
00085    /* If use_uri_table is set, use URI table to determine if Digest username
00086     * and To/From username match. URI table is a table enumerating all allowed
00087     * usernames for a single, thus a user can have several different usernames
00088     * (which are different from digest username and it will still match)
00089     */
00090    if (use_uri_table) {
00091       if (uridb_dbf.use_table(db_handle, &db_table) < 0) {
00092          LM_ERR("Error while trying to use uri table\n");
00093          return -7;
00094       }
00095 
00096       keys[0] = &uridb_user_col;
00097       keys[1] = &uridb_domain_col;
00098       keys[2] = &uridb_uriuser_col;
00099       cols[0] = &uridb_user_col;
00100 
00101       VAL_TYPE(vals) = VAL_TYPE(vals + 1) = VAL_TYPE(vals + 2) = DB_STR;
00102       VAL_NULL(vals) = VAL_NULL(vals + 1) = VAL_NULL(vals + 2) = 0;
00103 
00104       VAL_STR(vals) = c->digest.username.user;
00105       VAL_STR(vals + 1) = *GET_REALM(&c->digest);
00106       VAL_STR(vals + 2) = _uri->user;
00107 
00108       if (uridb_dbf.query(db_handle, keys, 0, vals, cols, 3, 1, 0, &res) < 0)
00109       {
00110          LM_ERR("Error while querying database\n");
00111          return -8;
00112       }
00113 
00114       /* If the previous function returns at least one row, it means
00115        * there is an entry for given digest username and URI username
00116        * and thus this combination is allowed and the function will match
00117        */
00118       if (RES_ROW_N(res) == 0) {
00119          LM_DBG("From/To user '%.*s' is spoofed\n",
00120                _uri->user.len, ZSW(_uri->user.s));
00121          uridb_dbf.free_result(db_handle, res);
00122          return -9;
00123       } else {
00124          LM_DBG("From/To user '%.*s' and auth user match\n",
00125                _uri->user.len, ZSW(_uri->user.s));
00126          uridb_dbf.free_result(db_handle, res);
00127          return 1;
00128       }
00129    } else {
00130       /* URI table not used, simply compare digest username and From/To
00131        * username, the comparison is case insensitive
00132        */
00133       if (_uri->user.len == c->digest.username.user.len) {
00134          if (!strncasecmp(_uri->user.s, c->digest.username.user.s, 
00135          _uri->user.len)) {
00136             LM_DBG("Digest username and URI username match\n");
00137             return 1;
00138          }
00139       }
00140 
00141       LM_DBG("Digest username and URI username do NOT match\n");
00142       return -10;
00143    }
00144 }
00145 
00146 
00147 /*
00148  * Check username part in To header field
00149  */
00150 int check_to(struct sip_msg* _m, char* _s1, char* _s2)
00151 {
00152    if (!_m->to && ((parse_headers(_m, HDR_TO_F, 0) == -1) || (!_m->to))) {
00153       LM_ERR("Error while parsing To header field\n");
00154       return -1;
00155    }
00156    if(parse_to_uri(_m)==NULL) {
00157       LM_ERR("Error while parsing To header URI\n");
00158       return -1;
00159    }
00160 
00161    return check_username(_m, &get_to(_m)->parsed_uri);
00162 }
00163 
00164 
00165 /*
00166  * Check username part in From header field
00167  */
00168 int check_from(struct sip_msg* _m, char* _s1, char* _s2)
00169 {
00170    if (parse_from_header(_m) < 0) {
00171       LM_ERR("Error while parsing From header field\n");
00172       return -1;
00173    }
00174    if(parse_from_uri(_m)==NULL) {
00175       LM_ERR("Error while parsing From header URI\n");
00176       return -1;
00177    }
00178 
00179    return check_username(_m, &get_from(_m)->parsed_uri);
00180 }
00181 
00182 
00183 /*
00184  * Check if uri belongs to a local user
00185  */
00186 int does_uri_exist(struct sip_msg* _msg, char* _s1, char* _s2)
00187 {
00188    db_key_t keys[2];
00189    db_val_t vals[2];
00190    db_key_t cols[1];
00191    db_res_t* res = NULL;
00192 
00193    if (parse_sip_msg_uri(_msg) < 0) {
00194       LM_ERR("Error while parsing URI\n");
00195       return -1;
00196    }
00197 
00198    if (use_uri_table) {
00199       if (uridb_dbf.use_table(db_handle, &db_table) < 0) {
00200          LM_ERR("Error while trying to use uri table\n");
00201          return -2;
00202       }
00203       keys[0] = &uridb_uriuser_col;
00204       keys[1] = &uridb_domain_col;
00205       cols[0] = &uridb_uriuser_col;
00206    } else {
00207       if (uridb_dbf.use_table(db_handle, &db_table) < 0) {
00208          LM_ERR("Error while trying to use subscriber table\n");
00209          return -3;
00210       }
00211       keys[0] = &uridb_user_col;
00212       keys[1] = &uridb_domain_col;
00213       cols[0] = &uridb_user_col;
00214    }
00215 
00216    VAL_TYPE(vals) = VAL_TYPE(vals + 1) = DB_STR;
00217    VAL_NULL(vals) = VAL_NULL(vals + 1) = 0;
00218    VAL_STR(vals) = _msg->parsed_uri.user;
00219    VAL_STR(vals + 1) = _msg->parsed_uri.host;
00220 
00221    if (uridb_dbf.query(db_handle, keys, 0, vals, cols, (use_domain ? 2 : 1),
00222             1, 0, &res) < 0) {
00223       LM_ERR("Error while querying database\n");
00224       return -4;
00225    }
00226    
00227    if (RES_ROW_N(res) == 0) {
00228       LM_DBG("User in request uri does not exist\n");
00229       uridb_dbf.free_result(db_handle, res);
00230       return -5;
00231    } else {
00232       LM_DBG("User in request uri does exist\n");
00233       uridb_dbf.free_result(db_handle, res);
00234       return 1;
00235    }
00236 }
00237 
00238 
00239 
00240 int uridb_db_init(const str* db_url)
00241 {
00242    if (uridb_dbf.init==0){
00243       LM_CRIT("BUG: null dbf\n");
00244       return -1; 
00245    }
00246    
00247    db_handle=uridb_dbf.init(db_url);
00248    if (db_handle==0){
00249       LM_ERR("unable to connect to the database\n");
00250       return -1;
00251    }
00252    return 0;
00253 }
00254 
00255 
00256 
00257 int uridb_db_bind(const str* db_url)
00258 {
00259    if (db_bind_mod(db_url, &uridb_dbf)<0){
00260       LM_ERR("unable to bind to the database module\n");
00261       return -1;
00262    }
00263 
00264    if (!DB_CAPABILITY(uridb_dbf, DB_CAP_QUERY)) {
00265       LM_ERR("Database module does not implement the 'query' function\n");
00266       return -1;
00267    }
00268 
00269    return 0;
00270 }
00271 
00272 
00273 void uridb_db_close(void)
00274 {
00275    if (db_handle && uridb_dbf.close){
00276       uridb_dbf.close(db_handle);
00277       db_handle=0;
00278    }
00279 }
00280 
00281 
00282 int uridb_db_ver(const str* db_url, str* name)
00283 {
00284    db_con_t* dbh;
00285    int ver;
00286    
00287    if (uridb_dbf.init==0){
00288       LM_CRIT("BUG: unbound database\n");
00289       return -1;
00290    }
00291 
00292    dbh=uridb_dbf.init(db_url);
00293    if (dbh==0){
00294       LM_ERR("unable to open database connection\n");
00295       return -1;
00296    }
00297    ver=db_table_version(&uridb_dbf, dbh, name);
00298    uridb_dbf.close(dbh);
00299    return ver;
00300 }

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