From fbe1ed25ee1b783a99e9ac1ac46347f526e2b356 Mon Sep 17 00:00:00 2001 From: Rick Date: Mon, 27 Mar 2017 19:58:18 +0200 Subject: [PATCH] uri_db: rework the possibiltiy to use any sip uri (#1034) * uri_db: added subscriber and realm param to check_uri * uri_db: fix whitespace bevor tab * uri_db: last fix for log macros * uri_db: removed change from log macros --- src/modules/uri_db/checks.c | 135 ++++++++++++++++++++++-------------- src/modules/uri_db/checks.h | 9 +-- src/modules/uri_db/uri_db.c | 20 ++++-- 3 files changed, 104 insertions(+), 60 deletions(-) diff --git a/src/modules/uri_db/checks.c b/src/modules/uri_db/checks.c index 12fb44d59a3..8f5e4cfe4dd 100644 --- a/src/modules/uri_db/checks.c +++ b/src/modules/uri_db/checks.c @@ -15,8 +15,8 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ @@ -41,10 +41,12 @@ static db_func_t uridb_dbf; * Check if a header field contains the same username * as digest credentials */ -static inline int check_username(struct sip_msg* _m, struct sip_uri *_uri) +static inline int check_username(struct sip_msg* _m, struct sip_uri *_uri, + str* _username, str* _realm) { - struct hdr_field* h; - auth_body_t* c; + str username; + str realm; + db_key_t keys[3]; db_val_t vals[3]; db_key_t cols[1]; @@ -55,19 +57,6 @@ static inline int check_username(struct sip_msg* _m, struct sip_uri *_uri) return -1; } - /* Get authorized digest credentials */ - get_authorized_cred(_m->authorization, &h); - if (!h) { - get_authorized_cred(_m->proxy_auth, &h); - if (!h) { - LM_ERR("No authorized credentials found (error in scripts)\n"); - LM_ERR("Call {www,proxy}_authorize before calling check_* functions!\n"); - return -2; - } - } - - c = (auth_body_t*)(h->parsed); - /* Parse To/From URI */ /* Make sure that the URI contains username */ if (!_uri->user.len) { @@ -75,6 +64,31 @@ static inline int check_username(struct sip_msg* _m, struct sip_uri *_uri) return -4; } + /* use digest credentials if no other credentials are supplied */ + if (!_username || !_realm) { + struct hdr_field* h; + auth_body_t* c; + + /* Get authorized digest credentials */ + get_authorized_cred(_m->authorization, &h); + if (!h) { + get_authorized_cred(_m->proxy_auth, &h); + if (!h) { + LM_ERR("No authorized credentials found (error in scripts)\n"); + LM_ERR("Call {www,proxy}_authorize before calling check_* functions!\n"); + return -2; + } + } + + c = (auth_body_t*)(h->parsed); + + username = c->digest.username.user; + realm = *GET_REALM(&c->digest); + } else { + username = *_username; + realm = *_realm; + } + /* If use_uri_table is set, use URI table to determine if Digest username * and To/From username match. URI table is a table enumerating all allowed * usernames for a single, thus a user can have several different usernames @@ -94,8 +108,8 @@ static inline int check_username(struct sip_msg* _m, struct sip_uri *_uri) VAL_TYPE(vals) = VAL_TYPE(vals + 1) = VAL_TYPE(vals + 2) = DB1_STR; VAL_NULL(vals) = VAL_NULL(vals + 1) = VAL_NULL(vals + 2) = 0; - VAL_STR(vals) = c->digest.username.user; - VAL_STR(vals + 1) = *GET_REALM(&c->digest); + VAL_STR(vals) = username; + VAL_STR(vals + 1) = realm; VAL_STR(vals + 2) = _uri->user; if (uridb_dbf.query(db_handle, keys, 0, vals, cols, 3, 1, 0, &res) < 0) @@ -110,7 +124,7 @@ static inline int check_username(struct sip_msg* _m, struct sip_uri *_uri) */ if (RES_ROW_N(res) == 0) { LM_DBG("From/To user '%.*s' is spoofed\n", - _uri->user.len, ZSW(_uri->user.s)); + _uri->user.len, ZSW(_uri->user.s)); uridb_dbf.free_result(db_handle, res); return -9; } else { @@ -123,9 +137,8 @@ static inline int check_username(struct sip_msg* _m, struct sip_uri *_uri) /* URI table not used, simply compare digest username and From/To * username, the comparison is case insensitive */ - if (_uri->user.len == c->digest.username.user.len) { - if (!strncasecmp(_uri->user.s, c->digest.username.user.s, - _uri->user.len)) { + if (_uri->user.len == username.len) { + if (!strncasecmp(_uri->user.s, username.s, _uri->user.len)) { LM_DBG("Digest username and URI username match\n"); return 1; } @@ -146,12 +159,12 @@ int check_to(struct sip_msg* _m, char* _s1, char* _s2) LM_ERR("Error while parsing To header field\n"); return -1; } - if(parse_to_uri(_m)==NULL) { + if (parse_to_uri(_m)==NULL) { LM_ERR("Error while parsing To header URI\n"); return -1; } - return check_username(_m, &get_to(_m)->parsed_uri); + return check_username(_m, &get_to(_m)->parsed_uri, NULL, NULL); } @@ -169,31 +182,51 @@ int check_from(struct sip_msg* _m, char* _s1, char* _s2) return -1; } - return check_username(_m, &get_from(_m)->parsed_uri); + return check_username(_m, &get_from(_m)->parsed_uri, NULL, NULL); } /* - * + * Checks username part of the supplied sip URI. + * Optinal with supplied credentials. */ -int check_uri(struct sip_msg* msg, char* uri, char* _s2) +int check_uri(struct sip_msg* msg, char* uri, char* username, char* realm) { - str suri; - struct sip_uri parsed_uri; - - if (fixup_get_svalue(msg, (gparam_t*)uri, &suri) != 0) - { - ERR("cannot get uri value\n"); - return -1; - } - - if (parse_uri(suri.s, suri.len, &parsed_uri) != 0) - { - ERR("Error while parsing URI\n"); - return -1; - } - - return check_username(msg, &parsed_uri); + str suri; + str susername; + str srealm; + + struct sip_uri parsed_uri; + + if (get_str_fparam(&suri, msg, (fparam_t*) uri) != 0) + { + LM_ERR("Error while getting URI value\n"); + return -1; + } + + if (parse_uri(suri.s, suri.len, &parsed_uri) != 0) + { + LM_ERR("Error while parsing URI\n"); + return -1; + } + + if (!username || !realm) { + return check_username(msg, &parsed_uri, NULL, NULL); + } + + if (get_str_fparam(&susername, msg, (fparam_t*) username) != 0) + { + LM_ERR("Error while getting username value\n"); + return -1; + } + + if (get_str_fparam(&srealm, msg, (fparam_t*) realm) != 0) + { + LM_ERR("Error while getting realm value\n"); + return -1; + } + + return check_username(msg, &parsed_uri, &susername, &srealm); } @@ -240,7 +273,7 @@ int does_uri_exist(struct sip_msg* _msg, char* _s1, char* _s2) LM_ERR("Error while querying database\n"); return -4; } - + if (RES_ROW_N(res) == 0) { LM_DBG("User in request uri does not exist\n"); uridb_dbf.free_result(db_handle, res); @@ -257,10 +290,10 @@ int does_uri_exist(struct sip_msg* _msg, char* _s1, char* _s2) int uridb_db_init(const str* db_url) { if (uridb_dbf.init==0){ - LM_CRIT("BUG: null dbf\n"); - return -1; + LM_BUG("null dbf\n"); + return -1; } - + db_handle=uridb_dbf.init(db_url); if (db_handle==0){ LM_ERR("unable to connect to the database\n"); @@ -300,9 +333,9 @@ int uridb_db_ver(const str* db_url, str* name) { db1_con_t* dbh; int ver; - + if (uridb_dbf.init==0){ - LM_CRIT("BUG: unbound database\n"); + LM_BUG("unbound database\n"); return -1; } diff --git a/src/modules/uri_db/checks.h b/src/modules/uri_db/checks.h index 1cc675a3d9f..5c97867dff7 100644 --- a/src/modules/uri_db/checks.h +++ b/src/modules/uri_db/checks.h @@ -15,8 +15,8 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ @@ -43,9 +43,10 @@ int check_from(struct sip_msg* _msg, char* _str1, char* _str2); /* - * + * Checks username part of the supplied sip URI. + * Optinal with supplied credentials. */ -int check_uri(struct sip_msg* msg, char* uri, char* _s2); +int check_uri(struct sip_msg* msg, char* uri, char* username, char* realm); /* diff --git a/src/modules/uri_db/uri_db.c b/src/modules/uri_db/uri_db.c index b2356ca3cf8..4b4bd60f6a0 100644 --- a/src/modules/uri_db/uri_db.c +++ b/src/modules/uri_db/uri_db.c @@ -1,4 +1,4 @@ -/* +/* * Various URI related functions * * Copyright (C) 2001-2003 FhG Fokus @@ -15,8 +15,8 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ @@ -71,6 +71,8 @@ int use_domain = 0; /* Should does_uri_exist honor the domain part ? */ static int fixup_exist(void** param, int param_no); +static int w_check_uri1(struct sip_msg* _m, char* _uri, char* _s); + /* * Exported functions */ @@ -79,8 +81,10 @@ static cmd_export_t cmds[] = { REQUEST_ROUTE}, {"check_from", (cmd_function)check_from, 0, 0, 0, REQUEST_ROUTE}, - {"check_uri", (cmd_function)check_uri, 1, fixup_spve_null, 0, - REQUEST_ROUTE}, + {"check_uri", (cmd_function)w_check_uri1, 1, fixup_spve_null, 0, + REQUEST_ROUTE}, + {"check_uri", (cmd_function)check_uri, 3, fixup_spve_all, 0, + REQUEST_ROUTE}, {"does_uri_exist", (cmd_function)does_uri_exist, 0, 0, fixup_exist, REQUEST_ROUTE|LOCAL_ROUTE}, {0, 0, 0, 0, 0, 0} @@ -193,3 +197,9 @@ static int fixup_exist(void** param, int param_no) } return 0; } + + +static int w_check_uri1(struct sip_msg* msg, char* uri, char* _s) +{ + return check_uri(msg, uri, NULL, NULL); +}