2
0

uid_uri_db_mod.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /*
  2. * $Id$
  3. *
  4. * Various URI related functions
  5. *
  6. * Copyright (C) 2001-2003 FhG Fokus
  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. * History:
  30. * -------
  31. * 2003-03-11: New module interface (janakj)
  32. * 2003-03-16: flags export parameter added (janakj)
  33. * 2003-03-19 replaces all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
  34. * 2003-04-05: default_uri #define used (jiri)
  35. * 2004-03-20: has_totag introduced (jiri)
  36. * 2004-06-07 updated to the new DB api (andrei)
  37. */
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include "../../sr_module.h"
  42. #include "../../dprint.h"
  43. #include "../../ut.h"
  44. #include "../../error.h"
  45. #include "../../mem/mem.h"
  46. #include "../../id.h"
  47. #include "../../parser/parse_from.h"
  48. #include "../../parser/parse_uri.h"
  49. #include "../../lib/srdb2/db.h"
  50. #include "uid_uri_db_mod.h"
  51. #include "../../usr_avp.h"
  52. #include "../uid_domain/domain.h"
  53. MODULE_VERSION
  54. #define USE_RURI 0
  55. #define USE_FROM 1
  56. #define USE_TO 2
  57. /*
  58. * Version of domain table required by the module,
  59. * increment this value if you change the table in
  60. * an backwards incompatible way
  61. */
  62. #define URI_TABLE_VERSION 2
  63. static void destroy(void); /* Module destroy function */
  64. static int child_init(int rank); /* Per-child initialization function */
  65. static int lookup_user(struct sip_msg* msg, char* s1, char* s2);
  66. static int lookup_user_2(struct sip_msg* msg, char* s1, char* s2);
  67. static int check_uri(struct sip_msg* msg, char* s1, char* s2);
  68. static int header_fixup(void** param, int param_no);
  69. static int lookup_user_fixup(void** param, int param_no);
  70. #define URI_TABLE "uid_uri"
  71. #define UID_COL "uid"
  72. #define DID_COL "did"
  73. #define USERNAME_COL "username"
  74. #define FLAGS_COL "flags"
  75. #define SCHEME_COL "scheme"
  76. #define CANONICAL_AVP "ruri_canonical"
  77. #define CANONICAL_AVP_VAL "1"
  78. /*
  79. * Module parameter variables
  80. */
  81. str db_url = STR_STATIC_INIT(DEFAULT_RODB_URL);
  82. str uri_table = STR_STATIC_INIT(URI_TABLE);
  83. str uid_col = STR_STATIC_INIT(UID_COL);
  84. str did_col = STR_STATIC_INIT(DID_COL);
  85. str username_col = STR_STATIC_INIT(USERNAME_COL);
  86. str flags_col = STR_STATIC_INIT(FLAGS_COL);
  87. str scheme_col = STR_STATIC_INIT(SCHEME_COL);
  88. str canonical_avp = STR_STATIC_INIT(CANONICAL_AVP);
  89. str canonical_avp_val = STR_STATIC_INIT(CANONICAL_AVP_VAL);
  90. static db_ctx_t* db = NULL;
  91. static db_cmd_t* lookup_uid_cmd = NULL;
  92. static domain_get_did_t dm_get_did = NULL;
  93. /* default did value */
  94. str default_did = STR_STATIC_INIT("_default");
  95. /*
  96. * Exported functions
  97. */
  98. static cmd_export_t cmds[] = {
  99. {"lookup_user", lookup_user, 1, header_fixup, REQUEST_ROUTE | FAILURE_ROUTE},
  100. {"lookup_user", lookup_user_2, 2, lookup_user_fixup, REQUEST_ROUTE | FAILURE_ROUTE},
  101. {"check_uri", check_uri, 1, header_fixup, REQUEST_ROUTE | FAILURE_ROUTE},
  102. {0, 0, 0, 0, 0}
  103. };
  104. /*
  105. * Exported parameters
  106. */
  107. static param_export_t params[] = {
  108. {"db_url", PARAM_STR, &db_url },
  109. {"uri_table", PARAM_STR, &uri_table },
  110. {"uid_column", PARAM_STR, &uid_col },
  111. {"did_column", PARAM_STR, &did_col },
  112. {"username_column", PARAM_STR, &username_col },
  113. {"flags_column", PARAM_STR, &flags_col },
  114. {"scheme_column", PARAM_STR, &scheme_col },
  115. {0, 0, 0}
  116. };
  117. /*
  118. * Module interface
  119. */
  120. struct module_exports exports = {
  121. "uid_uri_db",
  122. cmds, /* Exported functions */
  123. 0, /* RPC methods */
  124. params, /* Exported parameters */
  125. 0, /* module initialization function */
  126. 0, /* response function */
  127. destroy, /* destroy function */
  128. 0, /* oncancel function */
  129. child_init /* child initialization function */
  130. };
  131. /*
  132. * Module initialization function callee in each child separately
  133. */
  134. static int child_init(int rank)
  135. {
  136. db_fld_t lookup_uid_columns[] = {
  137. {.name = uid_col.s, DB_STR},
  138. {.name = flags_col.s, DB_BITMAP},
  139. {.name = NULL}
  140. };
  141. db_fld_t lookup_uid_match[] = {
  142. {.name = username_col.s, DB_STR},
  143. {.name = did_col.s, DB_STR},
  144. {.name = scheme_col.s, DB_STR},
  145. {.name = NULL}
  146. };
  147. if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
  148. return 0; /* do nothing for the main or tcp_main processes */
  149. db = db_ctx("uri_db");
  150. if (db == NULL) {
  151. ERR("Error while initializing database layer\n");
  152. return -1;
  153. }
  154. if (db_add_db(db, db_url.s) < 0) goto error;
  155. if (db_connect(db) < 0) goto error;
  156. lookup_uid_cmd = db_cmd(DB_GET, db, uri_table.s, lookup_uid_columns, lookup_uid_match, NULL);
  157. if (lookup_uid_cmd == NULL) {
  158. ERR("Error while building db query to load global attributes\n");
  159. goto error;
  160. }
  161. return 0;
  162. error:
  163. if (lookup_uid_cmd) db_cmd_free(lookup_uid_cmd);
  164. if (db) db_ctx_free(db);
  165. return -1;
  166. }
  167. static void destroy(void)
  168. {
  169. if (lookup_uid_cmd) db_cmd_free(lookup_uid_cmd);
  170. if (db) db_ctx_free(db);
  171. }
  172. /*
  173. * Lookup UID from uri table. If store parameter is non-zero then
  174. * store the UID in an attribute.
  175. * The function returns 1 if UID was found, -1 if not or on an error
  176. */
  177. static int lookup_uid(struct sip_msg* msg, long id, int store)
  178. {
  179. struct to_body* from, *to;
  180. struct sip_uri puri;
  181. str did, uid;
  182. db_res_t* res;
  183. db_rec_t* rec;
  184. int flag, ret;
  185. int_str avp_name, avp_val;
  186. flag=0; /*warning fix*/
  187. did.s = 0; did.len = 0;
  188. if (id == USE_FROM) {
  189. get_from_did(&did, msg);
  190. flag = SRDB_IS_FROM;
  191. if (parse_from_header(msg) < 0) {
  192. LOG(L_ERR, "uri_db:lookup_uid: Error while parsing From header\n");
  193. return -1;
  194. }
  195. from = get_from(msg);
  196. if (!from) {
  197. LOG(L_ERR, "uri_db:lookup_uid: Unable to get From username\n");
  198. return -1;
  199. }
  200. if (parse_uri(from->uri.s, from->uri.len, &puri) < 0) {
  201. LOG(L_ERR, "uri_db:lookup_uid: Error while parsing From URI\n");
  202. return -1;
  203. }
  204. lookup_uid_cmd->match[0].v.lstr = puri.user;
  205. uri_type_to_str(puri.type, &(lookup_uid_cmd->match[2].v.lstr));
  206. } else if (id == USE_TO) {
  207. get_to_did(&did, msg);
  208. if (!msg->to) {
  209. if (parse_headers( msg, HDR_TO_F, 0 )==-1) {
  210. ERR("unable to parse To header\n");
  211. return -1;
  212. }
  213. }
  214. to = get_to(msg);
  215. if (!to) {
  216. LOG(L_ERR, "uri_db:lookup_uid: Unable to get To username\n");
  217. return -1;
  218. }
  219. if (parse_uri(to->uri.s, to->uri.len, &puri) < 0) {
  220. LOG(L_ERR, "uri_db:lookup_uid: Error while parsing To URI\n");
  221. return -1;
  222. }
  223. lookup_uid_cmd->match[0].v.lstr = puri.user;
  224. uri_type_to_str(puri.type, &(lookup_uid_cmd->match[2].v.lstr));
  225. flag = SRDB_IS_TO;
  226. } else {
  227. get_to_did(&did, msg);
  228. flag = SRDB_IS_TO;
  229. if (parse_sip_msg_uri(msg) < 0) return -1;
  230. lookup_uid_cmd->match[0].v.lstr = msg->parsed_uri.user;
  231. uri_type_to_str(msg->parsed_uri.type, &(lookup_uid_cmd->match[2].v.lstr));
  232. }
  233. if (did.s && did.len) {
  234. lookup_uid_cmd->match[1].v.lstr = did;
  235. } else {
  236. LOG(L_DBG, "uri_db:lookup_uid: DID not found, using default value\n");
  237. lookup_uid_cmd->match[1].v.lstr = default_did;
  238. }
  239. if (db_exec(&res, lookup_uid_cmd) < 0) {
  240. LOG(L_ERR, "uri_db:lookup_uid: Error while executing database query\n");
  241. return -1;
  242. }
  243. rec = db_first(res);
  244. while(rec) {
  245. if (rec->fld[0].flags & DB_NULL ||
  246. rec->fld[1].flags & DB_NULL) {
  247. LOG(L_ERR, "uri_db:lookup_uid: Bogus line in %s table\n", uri_table.s);
  248. goto skip;
  249. }
  250. if ((rec->fld[1].v.int4 & SRDB_DISABLED)) goto skip; /* Skip disabled entries */
  251. if ((rec->fld[1].v.int4 & SRDB_LOAD_SER) == 0) goto skip; /* Not for SER */
  252. if ((rec->fld[1].v.int4 & flag) == 0) goto skip; /* Not allowed in the header we are interested in */
  253. goto found;
  254. skip:
  255. rec = db_next(res);
  256. }
  257. ret = -1; /* Not found -> not allowed */
  258. goto freeres;
  259. found:
  260. if (store) {
  261. uid = rec->fld[0].v.lstr;
  262. if (id == USE_FROM) {
  263. set_from_uid(&uid);
  264. } else {
  265. set_to_uid(&uid);
  266. if (id == USE_RURI) {
  267. /* store as str|int avp if alias is canonical or not (1,0) */
  268. if ((rec->fld[1].v.int4 & SRDB_CANON) != 0) {
  269. avp_name.s = canonical_avp;
  270. avp_val.s = canonical_avp_val;
  271. add_avp(AVP_CLASS_USER | AVP_TRACK_TO | AVP_NAME_STR | AVP_VAL_STR, avp_name, avp_val);
  272. }
  273. }
  274. }
  275. }
  276. ret = 1;
  277. freeres:
  278. db_res_free(res);
  279. return ret;
  280. }
  281. static int check_uri(struct sip_msg* msg, char* s1, char* s2)
  282. {
  283. return lookup_uid(msg, (long)s1, 0);
  284. }
  285. static int lookup_user(struct sip_msg* msg, char* s1, char* s2)
  286. {
  287. return lookup_uid(msg, (long)s1, 1);
  288. }
  289. static int lookup_user_2(struct sip_msg* msg, char* attr, char* select)
  290. {
  291. db_res_t* res;
  292. db_rec_t* rec;
  293. str uri, did, uid;
  294. struct sip_uri puri;
  295. avp_ident_t* avp;
  296. int_str avp_val;
  297. int flag, ret;
  298. avp = &((fparam_t*)attr)->v.avp;
  299. if (!avp) {
  300. ERR("lookup_user: Invalid parameter 1, attribute name expected\n");
  301. return -1;
  302. }
  303. if (avp->flags & AVP_TRACK_TO) {
  304. flag = SRDB_IS_TO;
  305. } else {
  306. flag = SRDB_IS_FROM;
  307. }
  308. if (get_str_fparam(&uri, msg, (fparam_t*)select) != 0) {
  309. ERR("lookup_user: Unable to get SIP URI from %s\n", ((fparam_t*)select)->orig);
  310. return -1;
  311. }
  312. if (parse_uri(uri.s, uri.len, &puri) < 0) {
  313. ERR("Error while parsing URI '%.*s'\n", uri.len, ZSW(uri.s));
  314. return -1;
  315. }
  316. if (puri.host.len) {
  317. /* domain name is present */
  318. if (dm_get_did(&did, &puri.host) < 0) {
  319. DBG("Cannot lookup DID for domain '%.*s', using default value\n", puri.host.len, ZSW(puri.host.s));
  320. did = default_did;
  321. }
  322. } else {
  323. /* domain name is missing -- can be caused by Tel: URI */
  324. DBG("There is no domain name, using default value\n");
  325. did = default_did;
  326. }
  327. /* don't lookup users with empty username -- wasted DB time */
  328. if (puri.user.len==0) {
  329. return -1;
  330. }
  331. lookup_uid_cmd->match[0].v.lstr = puri.user;
  332. lookup_uid_cmd->match[1].v.lstr = did;
  333. uri_type_to_str(puri.type, &(lookup_uid_cmd->match[2].v.lstr));
  334. if (db_exec(&res, lookup_uid_cmd) < 0) {
  335. LOG(L_ERR, "lookup_user: Error in db_query\n");
  336. return -1;
  337. }
  338. rec = db_first(res);
  339. while(rec) {
  340. if (rec->fld[0].flags & DB_NULL ||
  341. rec->fld[1].flags & DB_NULL) {
  342. LOG(L_ERR, "lookup_user: Bogus line in %s table\n", uri_table.s);
  343. goto skip;
  344. }
  345. if ((rec->fld[1].v.int4 & SRDB_DISABLED)) goto skip; /* Skip disabled entries */
  346. if ((rec->fld[1].v.int4 & SRDB_LOAD_SER) == 0) goto skip; /* Not for SER */
  347. if ((rec->fld[1].v.int4 & flag) == 0) goto skip; /* Not allowed in the header we are interested in */
  348. goto found;
  349. skip:
  350. rec = db_next(res);
  351. }
  352. DBG("lookup_user: UID not found for '%.*s'\n", uri.len, ZSW(uri.s));
  353. ret = -1;
  354. goto freeres;
  355. found:
  356. uid = rec->fld[0].v.lstr;
  357. avp_val.s = uid;
  358. if (add_avp(avp->flags | AVP_VAL_STR, avp->name, avp_val) < 0) {
  359. ERR("lookup_user: Error while creating attribute\n");
  360. ret = -1;
  361. } else {
  362. ret = 1;
  363. }
  364. freeres:
  365. db_res_free(res);
  366. return ret;
  367. }
  368. static int header_fixup(void** param, int param_no)
  369. {
  370. long id = 0;
  371. if (param_no == 1) {
  372. if (!strcasecmp(*param, "Request-URI")) {
  373. id = USE_RURI;
  374. } else if (!strcasecmp(*param, "From")) {
  375. id = USE_FROM;
  376. } else if (!strcasecmp(*param, "To")) {
  377. id = USE_TO;
  378. } else {
  379. LOG(L_ERR, "uri_db:header_fixup Unknown parameter\n");
  380. return -1;
  381. }
  382. }
  383. pkg_free(*param);
  384. *param=(void*)id;
  385. return 0;
  386. }
  387. static int lookup_user_fixup(void** param, int param_no)
  388. {
  389. if (param_no == 1) {
  390. if (fix_param(FPARAM_AVP, param) != 0) {
  391. ERR("lookup_user: Invalid parameter 1, attribute expected\n");
  392. return -1;
  393. }
  394. dm_get_did = (domain_get_did_t)find_export("get_did", 0, 0);
  395. if (!dm_get_did) {
  396. ERR("lookup_user: Could not find domain module\n");
  397. return -1;
  398. }
  399. return 0;
  400. } else {
  401. return fixup_var_str_12(param, 2);
  402. }
  403. }