mod_sanity.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*
  2. * $Id$
  3. *
  4. * Sanity Checks Module
  5. *
  6. * Copyright (C) 2006 iptelorg GbmH
  7. *
  8. * This file is part of ser, a free SIP server.
  9. *
  10. * ser is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version
  14. *
  15. * For a license to use the ser software under conditions
  16. * other than those described here, or to purchase support for this
  17. * software, please contact iptel.org by e-mail at the following addresses:
  18. * [email protected]
  19. *
  20. * ser is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program; if not, write to the Free Software
  27. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  28. *
  29. */
  30. #include "mod_sanity.h"
  31. #include "sanity.h"
  32. #include "api.h"
  33. #include "../../sr_module.h"
  34. #include "../../ut.h"
  35. #include "../../error.h"
  36. MODULE_VERSION
  37. #define PROXY_REQUIRE_DEF ""
  38. str pr_str = STR_STATIC_INIT(PROXY_REQUIRE_DEF);
  39. int default_msg_checks = SANITY_DEFAULT_CHECKS;
  40. int default_uri_checks = SANITY_DEFAULT_URI_CHECKS;
  41. int _sanity_drop = 1;
  42. strl* proxyrequire_list = NULL;
  43. sl_api_t slb;
  44. static int mod_init(void);
  45. static int sanity_fixup(void** param, int param_no);
  46. static int w_sanity_check(struct sip_msg* _msg, char* _foo, char* _bar);
  47. static int bind_sanity(sanity_api_t* api);
  48. /*
  49. * Exported functions
  50. */
  51. static cmd_export_t cmds[] = {
  52. {"sanity_check", (cmd_function)w_sanity_check, 0, 0,
  53. REQUEST_ROUTE|ONREPLY_ROUTE},
  54. {"sanity_check", (cmd_function)w_sanity_check, 1, sanity_fixup,
  55. REQUEST_ROUTE|ONREPLY_ROUTE},
  56. {"sanity_check", (cmd_function)w_sanity_check, 2, sanity_fixup,
  57. REQUEST_ROUTE|ONREPLY_ROUTE},
  58. {"bind_sanity", (cmd_function)bind_sanity, 0, 0, 0},
  59. {0, 0, 0, 0}
  60. };
  61. /*
  62. * Exported parameters
  63. */
  64. static param_export_t params[] = {
  65. {"default_checks", PARAM_INT, &default_msg_checks },
  66. {"uri_checks", PARAM_INT, &default_uri_checks },
  67. {"proxy_require", PARAM_STR, &pr_str },
  68. {"autodrop", PARAM_INT, &_sanity_drop },
  69. {0, 0, 0}
  70. };
  71. /*
  72. * Module description
  73. */
  74. struct module_exports exports = {
  75. "sanity", /* Module name */
  76. cmds, /* Exported functions */
  77. 0, /* RPC methods */
  78. params, /* Exported parameters */
  79. mod_init, /* Initialization function */
  80. 0, /* Response function */
  81. 0, /* Destroy function */
  82. 0, /* OnCancel function */
  83. 0 /* Child init function */
  84. };
  85. /*
  86. * initialize module
  87. */
  88. static int mod_init(void) {
  89. strl* ptr;
  90. DBG("sanity initializing\n");
  91. /* bind the SL API */
  92. if (sl_load_api(&slb)!=0) {
  93. LM_ERR("cannot bind to SL API\n");
  94. return -1;
  95. }
  96. DBG("parsing proxy requires string:\n");
  97. ptr = parse_str_list(&pr_str);
  98. proxyrequire_list = ptr;
  99. while (ptr != NULL) {
  100. DBG("string: '%.*s', next: %p\n", ptr->string.len, ptr->string.s, ptr->next);
  101. ptr = ptr->next;
  102. }
  103. return 0;
  104. }
  105. static int sanity_fixup(void** param, int param_no) {
  106. int checks;
  107. str in;
  108. if (param_no == 1) {
  109. in.s = (char*)*param;
  110. in.len = strlen(in.s);
  111. if (str2int(&in, (unsigned int*)&checks) < 0) {
  112. LOG(L_ERR, "sanity: failed to convert input integer\n");
  113. return E_UNSPEC;
  114. }
  115. if ((checks < 1) || (checks >= (SANITY_MAX_CHECKS))) {
  116. LOG(L_ERR, "sanity: input parameter (%i) outside of valid range <1-%i)\n", checks, SANITY_MAX_CHECKS);
  117. return E_UNSPEC;
  118. }
  119. *param = (void*)(long)checks;
  120. }
  121. if (param_no == 2) {
  122. in.s = (char*)*param;
  123. in.len = strlen(in.s);
  124. if (str2int(&in, (unsigned int*)&checks) < 0) {
  125. LOG(L_ERR, "sanity: failed to convert second integer argument\n");
  126. return E_UNSPEC;
  127. }
  128. if ((checks < 1) || (checks >= (SANITY_URI_MAX_CHECKS))) {
  129. LOG(L_ERR, "sanity: second input parameter (%i) outside of valid range <1-%i\n", checks, SANITY_URI_MAX_CHECKS);
  130. return E_UNSPEC;
  131. }
  132. *param = (void*)(long)checks;
  133. }
  134. return 0;
  135. }
  136. /**
  137. * perform SIP message sanity check
  138. * @param _msg - SIP message structure
  139. * @param msg_checks - bitmask of sanity tests to perform over message
  140. * @param uri_checks - bitmask of sanity tests to perform over uri
  141. * @return -1 on error, 0 on tests failure, 1 on success
  142. */
  143. int sanity_check(struct sip_msg* _msg, int msg_checks, int uri_checks)
  144. {
  145. int ret;
  146. ret = SANITY_CHECK_PASSED;
  147. if (SANITY_RURI_SIP_VERSION & msg_checks &&
  148. (ret = check_ruri_sip_version(_msg)) != SANITY_CHECK_PASSED) {
  149. goto done;
  150. }
  151. if (SANITY_RURI_SCHEME & msg_checks &&
  152. (ret = check_ruri_scheme(_msg)) != SANITY_CHECK_PASSED) {
  153. goto done;
  154. }
  155. if (SANITY_REQUIRED_HEADERS & msg_checks &&
  156. (ret = check_required_headers(_msg)) != SANITY_CHECK_PASSED) {
  157. goto done;
  158. }
  159. if (SANITY_VIA_SIP_VERSION & msg_checks &&
  160. (ret = check_via_sip_version(_msg)) != SANITY_CHECK_PASSED) {
  161. goto done;
  162. }
  163. if (SANITY_VIA_PROTOCOL & msg_checks &&
  164. (ret = check_via_protocol(_msg)) != SANITY_CHECK_PASSED) {
  165. goto done;
  166. }
  167. if (SANITY_CSEQ_METHOD & msg_checks &&
  168. (ret = check_cseq_method(_msg)) != SANITY_CHECK_PASSED) {
  169. goto done;
  170. }
  171. if (SANITY_CSEQ_VALUE & msg_checks &&
  172. (ret = check_cseq_value(_msg)) != SANITY_CHECK_PASSED) {
  173. goto done;
  174. }
  175. if (SANITY_CL & msg_checks &&
  176. (ret = check_cl(_msg)) != SANITY_CHECK_PASSED) {
  177. goto done;
  178. }
  179. if (SANITY_EXPIRES_VALUE & msg_checks &&
  180. (ret = check_expires_value(_msg)) != SANITY_CHECK_PASSED) {
  181. goto done;
  182. }
  183. if (SANITY_PROXY_REQUIRE & msg_checks &&
  184. (ret = check_proxy_require(_msg)) != SANITY_CHECK_PASSED) {
  185. goto done;
  186. }
  187. if (SANITY_PARSE_URIS & msg_checks &&
  188. (ret = check_parse_uris(_msg, uri_checks)) != SANITY_CHECK_PASSED) {
  189. goto done;
  190. }
  191. if (SANITY_CHECK_DIGEST & msg_checks &&
  192. (ret = check_digest(_msg, uri_checks)) != SANITY_CHECK_PASSED) {
  193. goto done;
  194. }
  195. if (SANITY_CHECK_DUPTAGS & msg_checks &&
  196. (ret = check_duptags(_msg)) != SANITY_CHECK_PASSED) {
  197. goto done;
  198. }
  199. done:
  200. return ret;
  201. }
  202. /**
  203. * do default checks
  204. */
  205. int sanity_check_defaults(struct sip_msg* msg)
  206. {
  207. return sanity_check(msg, default_msg_checks, default_uri_checks);
  208. }
  209. /**
  210. * wrapper for sanity_check() to be used from config file
  211. */
  212. static int w_sanity_check(struct sip_msg* _msg, char* _number, char* _arg) {
  213. int ret, check, arg;
  214. if (_number == NULL) {
  215. check = default_msg_checks;
  216. }
  217. else {
  218. check = (int)(long)_number;
  219. }
  220. if (_arg == NULL) {
  221. arg = default_uri_checks;
  222. }
  223. else {
  224. arg = (int)(long)_arg;
  225. }
  226. ret = sanity_check(_msg, check, arg);
  227. DBG("sanity checks result: %d\n", ret);
  228. if(_sanity_drop!=0)
  229. return ret;
  230. return (ret==SANITY_CHECK_FAILED)?-1:ret;
  231. }
  232. /**
  233. * load sanity module API
  234. */
  235. static int bind_sanity(sanity_api_t* api)
  236. {
  237. if (!api) {
  238. ERR("Invalid parameter value\n");
  239. return -1;
  240. }
  241. api->check = sanity_check;
  242. api->check_defaults = sanity_check_defaults;
  243. return 0;
  244. }