📄 trusted.c
字号:
/* * $Id: trusted.c,v 1.6 2006/06/28 09:35:11 bogdan_iancu Exp $ * * allow_trusted related functions * * Copyright (C) 2003 Juha Heinanen * * This file is part of openser, a free SIP server. * * openser is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * openser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * 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 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * History: * -------- * 2004-06-07 updated to the new DB api, moved reload_trusted_table (andrei) */#include <sys/types.h>#include <regex.h>#include <string.h>#include "permissions.h"#include "hash.h"#include "fifo.h"#include "unixsock.h"#include "../../config.h"#include "../../db/db.h"#include "../../ip_addr.h"#include "../../mem/shm_mem.h"#include "../../parser/msg_parser.h"#include "../../parser/parse_from.h"#include "../../usr_avp.h"#define TABLE_VERSION 3struct trusted_list ***hash_table; /* Pointer to current hash table pointer */struct trusted_list **hash_table_1; /* Pointer to hash table 1 */struct trusted_list **hash_table_2; /* Pointer to hash table 2 */static db_con_t* db_handle = 0;static db_func_t perm_dbf;/* * Initialize data structures */int init_trusted(void){ int ver; str name; /* Check if hash table needs to be loaded from trusted table */ if (!db_url) { LOG(L_INFO, "db_url parameter of permissions module not set, " "disabling allow_trusted\n"); return 0; } else { if (bind_dbmod(db_url, &perm_dbf) < 0) { LOG(L_ERR, "ERROR: permissions: init_trusted: " "load a database support module\n"); return -1; } if (!DB_CAPABILITY(perm_dbf, DB_CAP_QUERY)) { LOG(L_ERR, "ERROR: permissions: init_trusted: " "Database module does not implement 'query' function\n"); return -1; } } hash_table_1 = hash_table_2 = 0; hash_table = 0; if (db_mode == ENABLE_CACHE) { db_handle = perm_dbf.init(db_url); if (!db_handle) { LOG(L_ERR, "ERROR: permissions: init_trusted():" " Unable to connect database\n"); return -1; } name.s = trusted_table; name.len = strlen(trusted_table); ver = table_version(&perm_dbf, db_handle, &name); if (ver < 0) { LOG(L_ERR, "permissions:init_trusted(): Error while querying " "table version\n"); perm_dbf.close(db_handle); return -1; } else if (ver < TABLE_VERSION) { LOG(L_ERR, "permissions:init_trusted(): Invalid table version %d " "- expected %d (use openser_mysql.sh reinstall)\n", ver,TABLE_VERSION); perm_dbf.close(db_handle); return -1; } /* Initialize fifo interface */ (void)init_trusted_fifo(); if (init_trusted_unixsock() < 0) { LOG(L_ERR, "permissions:init_trusted(): Error while initializing " "unixsock interface\n"); perm_dbf.close(db_handle); return -1; } hash_table_1 = new_hash_table(); if (!hash_table_1) return -1; hash_table_2 = new_hash_table(); if (!hash_table_2) goto error; hash_table = (struct trusted_list ***)shm_malloc (sizeof(struct trusted_list **)); if (!hash_table) goto error; *hash_table = hash_table_1; if (reload_trusted_table() == -1) { LOG(L_CRIT, "init_trusted(): Reload of trusted table failed\n"); goto error; } perm_dbf.close(db_handle); db_handle = 0; } return 0;error: if (hash_table_1) { free_hash_table(hash_table_1); hash_table_1 = 0; } if (hash_table_2) { free_hash_table(hash_table_2); hash_table_2 = 0; } if (hash_table) { shm_free(hash_table); hash_table = 0; } perm_dbf.close(db_handle); db_handle = 0; return -1;}/* * Open database connections if necessary */int init_child_trusted(int rank){ str name; int ver; if (!db_url) { return 0; } /* Check if database is needed by child */ if (((db_mode == DISABLE_CACHE) && (rank > 0)) || ((db_mode == ENABLE_CACHE) && (rank == PROC_FIFO)) ) { db_handle = perm_dbf.init(db_url); if (!db_handle) { LOG(L_ERR, "ERROR: permissions: init_child_trusted():" " Unable to connect database\n"); return -1; } name.s = trusted_table; name.len = strlen(trusted_table); ver = table_version(&perm_dbf, db_handle, &name); if (ver < 0) { LOG(L_ERR, "ERROR: permissions: init_child_trusted():" " Error while querying table version\n"); perm_dbf.close(db_handle); return -1; } else if (ver < TABLE_VERSION) { LOG(L_ERR, "ERROR: permissions: init_child_trusted():" " Invalid table version (use openser_mysql.sh reinstall)\n"); perm_dbf.close(db_handle); return -1; } } return 0;}/* * Close connections and release memory */void clean_trusted(void){ if (hash_table_1) free_hash_table(hash_table_1); if (hash_table_2) free_hash_table(hash_table_2); if (hash_table) shm_free(hash_table);}/* * Matches protocol string against the protocol of the request. Returns 1 on * success and 0 on failure. */static inline int match_proto(char *proto_string, int proto_int){ if (strcasecmp(proto_string, "any") == 0) return 1; if (proto_int == PROTO_UDP) { if (strcasecmp(proto_string, "udp") == 0) { return 1; } else { return 0; } } if (proto_int == PROTO_TCP) { if (strcasecmp(proto_string, "tcp") == 0) { return 1; } else { return 0; } } if (proto_int == PROTO_TLS) { if (strcasecmp(proto_string, "tls") == 0) { return 1; } else { return 0; } } if (proto_int == PROTO_SCTP) { if (strcasecmp(proto_string, "sctp") == 0) { return 1; } else { return 0; } } LOG(L_ERR, "match_proto(): Unknown request protocol\n"); return 0;}/* * Matches from uri against patterns returned from database. Returns 1 when * first pattern matches and 0 if none of the patterns match. */static int match_res(struct sip_msg* msg, db_res_t* _r){ int i, tag_avp_type; str uri; char uri_string[MAX_URI_SIZE+1]; db_row_t* row; db_val_t* val; regex_t preg; int_str tag_avp, avp_val; if (parse_from_header(msg) < 0) return -1; uri = get_from(msg)->uri; if (uri.len > MAX_URI_SIZE) { LOG(L_ERR, "match_res(): From URI too large\n"); return -1; } memcpy(uri_string, uri.s, uri.len); uri_string[uri.len] = (char)0; row = RES_ROWS(_r); for(i = 0; i < RES_ROW_N(_r); i++) { val = ROW_VALUES(row + i); if ((ROW_N(row + i) == 3) && (VAL_TYPE(val) == DB_STRING) && !VAL_NULL(val) && match_proto((char *)VAL_STRING(val), msg->rcv.proto) && (VAL_NULL(val + 1) || ((VAL_TYPE(val + 1) == DB_STRING) && !VAL_NULL(val + 1))) && (VAL_NULL(val + 2) || ((VAL_TYPE(val + 2) == DB_STRING) && !VAL_NULL(val + 2)))) { if (VAL_NULL(val + 1)) goto found; if (regcomp(&preg, (char *)VAL_STRING(val + 1), REG_NOSUB)) { LOG(L_ERR, "match_res(): Error in regular expression\n"); continue; } if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) { regfree(&preg); continue; } else { regfree(&preg); goto found; } } } return -1;found: get_tag_avp(&tag_avp, &tag_avp_type); if (tag_avp.n && !VAL_NULL(val + 2)) { avp_val.s.s = (char *)VAL_STRING(val + 2); avp_val.s.len = strlen(avp_val.s.s); if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, avp_val) != 0) { LOG(L_ERR, "match_res(): ERROR: setting of " "tag_avp failed\n"); return -1; } } return 1;}/* * Checks based on request's source address, protocol, and from field * if request can be trusted without authentication. Possible protocol * values are "any" (that matches any protocol), "tcp", "udp", "tls", * and "sctp". */int allow_trusted(struct sip_msg* _msg, char* str1, char* str2) { int result; db_res_t* res; db_key_t keys[1]; db_val_t vals[1]; db_key_t cols[3]; if (!db_url) { LOG(L_ERR, "allow_trusted(): ERROR set db_mode parameter of permissions module first !\n"); return -1; } if (db_mode == DISABLE_CACHE) { keys[0] = source_col; cols[0] = proto_col; cols[1] = from_col; cols[2] = tag_col; if (perm_dbf.use_table(db_handle, trusted_table) < 0) { LOG(L_ERR, "allow_trusted(): Error while trying to use trusted table\n"); return -1; } VAL_TYPE(vals) = DB_STRING; VAL_NULL(vals) = 0; VAL_STRING(vals) = ip_addr2a(&(_msg->rcv.src_ip)); if (perm_dbf.query(db_handle, keys, 0, vals, cols, 1, 3, 0, &res) < 0){ LOG(L_ERR, "allow_trusted(): Error while querying database\n"); perm_dbf.close(db_handle); return -1; } if (RES_ROW_N(res) == 0) { perm_dbf.free_result(db_handle, res); return -1; } result = match_res(_msg, res); perm_dbf.free_result(db_handle, res); return result; } else if (db_mode == ENABLE_CACHE) { return match_hash_table(*hash_table, _msg); } else { LOG(L_ERR, "allow_trusted(): Error - set db_mode parameter of permissions module properly\n"); return -1; }}/* * Reload trusted table to new hash table and when done, make new hash table * current one. */int reload_trusted_table(void){ db_key_t cols[4]; db_res_t* res; db_row_t* row; db_val_t* val; struct trusted_list **new_hash_table; int i; cols[0] = source_col; cols[1] = proto_col; cols[2] = from_col; cols[3] = tag_col; char *pattern, *tag; if (perm_dbf.use_table(db_handle, trusted_table) < 0) { LOG(L_ERR, "ERROR: permissions: reload_trusted_table():" " Error while trying to use trusted table\n"); return -1; } if (perm_dbf.query(db_handle, NULL, 0, NULL, cols, 0, 4, 0, &res) < 0) { LOG(L_ERR, "ERROR: permissions: reload_trusted_table():" " Error while querying database\n"); return -1; } /* Choose new hash table and free its old contents */ if (*hash_table == hash_table_1) { empty_hash_table(hash_table_2); new_hash_table = hash_table_2; } else { empty_hash_table(hash_table_1); new_hash_table = hash_table_1; } row = RES_ROWS(res); DBG("Number of rows in trusted table: %d\n", RES_ROW_N(res)); for (i = 0; i < RES_ROW_N(res); i++) { val = ROW_VALUES(row + i); if ((ROW_N(row + i) == 4) && (VAL_TYPE(val) == DB_STRING) && !VAL_NULL(val) && (VAL_TYPE(val + 1) == DB_STRING) && !VAL_NULL(val + 1) && (VAL_NULL(val + 2) || ((VAL_TYPE(val + 2) == DB_STRING) && !VAL_NULL(val + 2))) && (VAL_NULL(val + 3) || ((VAL_TYPE(val + 3) == DB_STRING) && !VAL_NULL(val + 3)))) { if (VAL_NULL(val + 2)) { pattern = 0; } else { pattern = (char *)VAL_STRING(val + 2); } if (VAL_NULL(val + 3)) { tag = 0; } else { tag = (char *)VAL_STRING(val + 3); } if (hash_table_insert(new_hash_table, (char *)VAL_STRING(val), (char *)VAL_STRING(val + 1), pattern, tag) == -1) { LOG(L_ERR, "ERROR: permissions: " "trusted_reload(): Hash table problem\n"); perm_dbf.free_result(db_handle, res); return -1; } DBG("Tuple <%s, %s, %s, %s> inserted into trusted hash " "table\n", VAL_STRING(val), VAL_STRING(val + 1), pattern, tag); } else { LOG(L_ERR, "ERROR: permissions: trusted_reload():" " Database problem\n"); perm_dbf.free_result(db_handle, res); return -1; } } perm_dbf.free_result(db_handle, res); *hash_table = new_hash_table; DBG("Trusted table reloaded successfully.\n"); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -