123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- /*
- * $Id$
- *
- * Sanity Checks Module
- *
- * Copyright (C) 2006 iptelorg GbmH
- *
- * This file is part of ser, a free SIP server.
- *
- * ser 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
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- * [email protected]
- *
- * ser 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
- #include "mod_sanity.h"
- #include "sanity.h"
- #include "api.h"
- #include "../../sr_module.h"
- #include "../../ut.h"
- #include "../../error.h"
- MODULE_VERSION
- #define PROXY_REQUIRE_DEF ""
- str pr_str = STR_STATIC_INIT(PROXY_REQUIRE_DEF);
- int default_msg_checks = SANITY_DEFAULT_CHECKS;
- int default_uri_checks = SANITY_DEFAULT_URI_CHECKS;
- int _sanity_drop = 1;
- strl* proxyrequire_list = NULL;
- sl_api_t slb;
- static int mod_init(void);
- static int sanity_fixup(void** param, int param_no);
- static int w_sanity_check(struct sip_msg* _msg, char* _foo, char* _bar);
- static int bind_sanity(sanity_api_t* api);
- /*
- * Exported functions
- */
- static cmd_export_t cmds[] = {
- {"sanity_check", (cmd_function)w_sanity_check, 0, 0,
- REQUEST_ROUTE|ONREPLY_ROUTE},
- {"sanity_check", (cmd_function)w_sanity_check, 1, sanity_fixup,
- REQUEST_ROUTE|ONREPLY_ROUTE},
- {"sanity_check", (cmd_function)w_sanity_check, 2, sanity_fixup,
- REQUEST_ROUTE|ONREPLY_ROUTE},
- {"bind_sanity", (cmd_function)bind_sanity, 0, 0, 0},
- {0, 0, 0, 0}
- };
- /*
- * Exported parameters
- */
- static param_export_t params[] = {
- {"default_checks", PARAM_INT, &default_msg_checks },
- {"uri_checks", PARAM_INT, &default_uri_checks },
- {"proxy_require", PARAM_STR, &pr_str },
- {"autodrop", PARAM_INT, &_sanity_drop },
- {0, 0, 0}
- };
- /*
- * Module description
- */
- struct module_exports exports = {
- "sanity", /* Module name */
- cmds, /* Exported functions */
- 0, /* RPC methods */
- params, /* Exported parameters */
- mod_init, /* Initialization function */
- 0, /* Response function */
- 0, /* Destroy function */
- 0, /* OnCancel function */
- 0 /* Child init function */
- };
- /*
- * initialize module
- */
- static int mod_init(void) {
- strl* ptr;
- DBG("sanity initializing\n");
- /* bind the SL API */
- if (sl_load_api(&slb)!=0) {
- LM_ERR("cannot bind to SL API\n");
- return -1;
- }
- DBG("parsing proxy requires string:\n");
- ptr = parse_str_list(&pr_str);
- proxyrequire_list = ptr;
- while (ptr != NULL) {
- DBG("string: '%.*s', next: %p\n", ptr->string.len, ptr->string.s, ptr->next);
- ptr = ptr->next;
- }
- return 0;
- }
- static int sanity_fixup(void** param, int param_no) {
- int checks;
- str in;
- if (param_no == 1) {
- in.s = (char*)*param;
- in.len = strlen(in.s);
- if (str2int(&in, (unsigned int*)&checks) < 0) {
- LOG(L_ERR, "sanity: failed to convert input integer\n");
- return E_UNSPEC;
- }
- if ((checks < 1) || (checks >= (SANITY_MAX_CHECKS))) {
- LOG(L_ERR, "sanity: input parameter (%i) outside of valid range <1-%i)\n", checks, SANITY_MAX_CHECKS);
- return E_UNSPEC;
- }
- *param = (void*)(long)checks;
- }
- if (param_no == 2) {
- in.s = (char*)*param;
- in.len = strlen(in.s);
- if (str2int(&in, (unsigned int*)&checks) < 0) {
- LOG(L_ERR, "sanity: failed to convert second integer argument\n");
- return E_UNSPEC;
- }
- if ((checks < 1) || (checks >= (SANITY_URI_MAX_CHECKS))) {
- LOG(L_ERR, "sanity: second input parameter (%i) outside of valid range <1-%i\n", checks, SANITY_URI_MAX_CHECKS);
- return E_UNSPEC;
- }
- *param = (void*)(long)checks;
- }
- return 0;
- }
- /**
- * perform SIP message sanity check
- * @param _msg - SIP message structure
- * @param msg_checks - bitmask of sanity tests to perform over message
- * @param uri_checks - bitmask of sanity tests to perform over uri
- * @return -1 on error, 0 on tests failure, 1 on success
- */
- int sanity_check(struct sip_msg* _msg, int msg_checks, int uri_checks)
- {
- int ret;
- ret = SANITY_CHECK_PASSED;
- if (SANITY_RURI_SIP_VERSION & msg_checks &&
- (ret = check_ruri_sip_version(_msg)) != SANITY_CHECK_PASSED) {
- goto done;
- }
- if (SANITY_RURI_SCHEME & msg_checks &&
- (ret = check_ruri_scheme(_msg)) != SANITY_CHECK_PASSED) {
- goto done;
- }
- if (SANITY_REQUIRED_HEADERS & msg_checks &&
- (ret = check_required_headers(_msg)) != SANITY_CHECK_PASSED) {
- goto done;
- }
- if (SANITY_VIA_SIP_VERSION & msg_checks &&
- (ret = check_via_sip_version(_msg)) != SANITY_CHECK_PASSED) {
- goto done;
- }
- if (SANITY_VIA_PROTOCOL & msg_checks &&
- (ret = check_via_protocol(_msg)) != SANITY_CHECK_PASSED) {
- goto done;
- }
- if (SANITY_CSEQ_METHOD & msg_checks &&
- (ret = check_cseq_method(_msg)) != SANITY_CHECK_PASSED) {
- goto done;
- }
- if (SANITY_CSEQ_VALUE & msg_checks &&
- (ret = check_cseq_value(_msg)) != SANITY_CHECK_PASSED) {
- goto done;
- }
- if (SANITY_CL & msg_checks &&
- (ret = check_cl(_msg)) != SANITY_CHECK_PASSED) {
- goto done;
- }
- if (SANITY_EXPIRES_VALUE & msg_checks &&
- (ret = check_expires_value(_msg)) != SANITY_CHECK_PASSED) {
- goto done;
- }
- if (SANITY_PROXY_REQUIRE & msg_checks &&
- (ret = check_proxy_require(_msg)) != SANITY_CHECK_PASSED) {
- goto done;
- }
- if (SANITY_PARSE_URIS & msg_checks &&
- (ret = check_parse_uris(_msg, uri_checks)) != SANITY_CHECK_PASSED) {
- goto done;
- }
- if (SANITY_CHECK_DIGEST & msg_checks &&
- (ret = check_digest(_msg, uri_checks)) != SANITY_CHECK_PASSED) {
- goto done;
- }
- if (SANITY_CHECK_DUPTAGS & msg_checks &&
- (ret = check_duptags(_msg)) != SANITY_CHECK_PASSED) {
- goto done;
- }
- done:
- return ret;
- }
- /**
- * do default checks
- */
- int sanity_check_defaults(struct sip_msg* msg)
- {
- return sanity_check(msg, default_msg_checks, default_uri_checks);
- }
- /**
- * wrapper for sanity_check() to be used from config file
- */
- static int w_sanity_check(struct sip_msg* _msg, char* _number, char* _arg) {
- int ret, check, arg;
- if (_number == NULL) {
- check = default_msg_checks;
- }
- else {
- check = (int)(long)_number;
- }
- if (_arg == NULL) {
- arg = default_uri_checks;
- }
- else {
- arg = (int)(long)_arg;
- }
- ret = sanity_check(_msg, check, arg);
- DBG("sanity checks result: %d\n", ret);
- if(_sanity_drop!=0)
- return ret;
- return (ret==SANITY_CHECK_FAILED)?-1:ret;
- }
- /**
- * load sanity module API
- */
- static int bind_sanity(sanity_api_t* api)
- {
- if (!api) {
- ERR("Invalid parameter value\n");
- return -1;
- }
- api->check = sanity_check;
- api->check_defaults = sanity_check_defaults;
- return 0;
- }
|