00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00041 #include <string.h>
00042
00043 #include "../../parser/parse_uri.h"
00044 #include "../../mem/shm_mem.h"
00045 #include "../../sr_module.h"
00046 #include "../../lib/kmi/mi.h"
00047 #include "../../mem/mem.h"
00048 #include "../../usr_avp.h"
00049 #include "../../locking.h"
00050 #include "../../error.h"
00051 #include "../../ut.h"
00052 #include "../../mod_fix.h"
00053
00054 #include "../../lib/trie/dtrie.h"
00055 #include "db.h"
00056 #include "db_userblacklist.h"
00057
00058 MODULE_VERSION
00059
00060
00061 #define MAXNUMBERLEN 31
00062
00063
00064 typedef struct _avp_check
00065 {
00066 int avp_flags;
00067 int_str avp_name;
00068 } avp_check_t;
00069
00070
00071 struct check_blacklist_fs_t {
00072 struct dtrie_node_t *dtrie_root;
00073 };
00074
00075 str userblacklist_db_url = str_init(DEFAULT_RODB_URL);
00076 int use_domain = 0;
00077 int match_mode = 10;
00078 static struct dtrie_node_t *gnode = NULL;
00079
00080
00081 static int check_blacklist_fixup(void** param, int param_no);
00082 static int check_user_blacklist_fixup(void** param, int param_no);
00083 static int check_globalblacklist_fixup(void** param, int param_no);
00084
00085
00086 static int check_user_blacklist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4);
00087 static int check_user_whitelist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4);
00088 static int check_user_blacklist2(struct sip_msg *msg, char* str1, char* str2);
00089 static int check_user_whitelist2(struct sip_msg *msg, char* str1, char* str2);
00090 static int check_user_blacklist3(struct sip_msg *msg, char* str1, char* str2, char* str3);
00091 static int check_user_whitelist3(struct sip_msg *msg, char* str1, char* str2, char* str3);
00092 static int check_blacklist(struct sip_msg *msg, struct check_blacklist_fs_t *arg1);
00093 static int check_globalblacklist(struct sip_msg *msg);
00094
00095
00096
00097 static int mod_init(void);
00098 static int child_init(int rank);
00099 static int mi_child_init(void);
00100 static void mod_destroy(void);
00101
00102
00103 struct mi_root * mi_reload_blacklist(struct mi_root* cmd, void* param);
00104
00105
00106 static cmd_export_t cmds[]={
00107 { "check_user_blacklist", (cmd_function)check_user_blacklist2, 2, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
00108 { "check_user_whitelist", (cmd_function)check_user_whitelist2, 2, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
00109 { "check_user_blacklist", (cmd_function)check_user_blacklist3, 3, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
00110 { "check_user_whitelist", (cmd_function)check_user_whitelist3, 3, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
00111 { "check_user_blacklist", (cmd_function)check_user_blacklist, 4, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
00112 { "check_user_whitelist", (cmd_function)check_user_whitelist, 4, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
00113 { "check_blacklist", (cmd_function)check_blacklist, 1, check_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
00114 { "check_blacklist", (cmd_function)check_globalblacklist, 0, check_globalblacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
00115 { 0, 0, 0, 0, 0, 0}
00116 };
00117
00118
00119 static param_export_t params[] = {
00120 userblacklist_DB_URL
00121 userblacklist_DB_TABLE
00122 globalblacklist_DB_TABLE
00123 userblacklist_DB_COLS
00124 globalblacklist_DB_COLS
00125 { "use_domain", INT_PARAM, &use_domain },
00126 { "match_mode", INT_PARAM, &match_mode},
00127 { 0, 0, 0}
00128 };
00129
00130
00131
00132 static mi_export_t mi_cmds[] = {
00133 { "reload_blacklist", mi_reload_blacklist, MI_NO_INPUT_FLAG, 0, mi_child_init },
00134 { 0, 0, 0, 0, 0}
00135 };
00136
00137
00138 struct module_exports exports= {
00139 "userblacklist",
00140 DEFAULT_DLFLAGS,
00141 cmds,
00142 params,
00143 0,
00144 mi_cmds,
00145 0,
00146 0,
00147 mod_init,
00148 0,
00149 mod_destroy,
00150 child_init
00151 };
00152
00153
00154 struct source_t {
00155 struct source_t *next;
00157 char *table;
00159 struct dtrie_node_t *dtrie_root;
00160 };
00161
00162
00163 struct source_list_t {
00164 struct source_t *head;
00165 };
00166
00167
00168 static gen_lock_t *lock = NULL;
00169 static struct source_list_t *sources = NULL;
00170 static struct dtrie_node_t *dtrie_root;
00171
00172
00173 static int check_user_blacklist_fixup(void** param, int param_no)
00174 {
00175 pv_elem_t *model=NULL;
00176 str s;
00177
00178
00179 s.s = (char*)*param;
00180 s.len = strlen(s.s);
00181
00182 if (param_no > 0 && param_no <= 4) {
00183 if(s.len == 0 && param_no != 4) {
00184 LM_ERR("no parameter %d\n", param_no);
00185 return E_UNSPEC;
00186 }
00187
00188 if(pv_parse_format(&s, &model) < 0 || !model) {
00189 LM_ERR("wrong format [%.*s] for parameter %d\n", s.len, s.s, param_no);
00190 return E_UNSPEC;
00191 }
00192
00193 if(!model->spec.getf) {
00194 if(param_no == 1) {
00195 if(str2int(&s, (unsigned int*)&model->spec.pvp.pvn.u.isname.name.n) != 0) {
00196 LM_ERR("wrong value [%.*s] for parameter %d\n", s.len, s.s, param_no);
00197 return E_UNSPEC;
00198 }
00199 } else {
00200 if(param_no == 2 || param_no == 3) {
00201 LM_ERR("wrong value [%.*s] for parameter %d\n", s.len, s.s, param_no);
00202 return E_UNSPEC;
00203 } else {
00204
00205 return 0;
00206 }
00207 }
00208 }
00209 *param = (void*)model;
00210 } else {
00211 LM_ERR("wrong number of parameters\n");
00212 }
00213
00214 return 0;
00215 }
00216
00217
00218 static int check_user_list(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4, int listtype)
00219 {
00220 str user = { .len = 0, .s = NULL };
00221 str domain = { .len = 0, .s = NULL};
00222 str table = { .len = 0, .s = NULL};
00223 str number = { .len = 0, .s = NULL};
00224
00225 void **nodeflags;
00226 char *ptr;
00227 char req_number[MAXNUMBERLEN+1];
00228
00229
00230 if(((pv_elem_p)str1)->spec.getf) {
00231 if(pv_printf_s(msg, (pv_elem_p)str1, &user) != 0) {
00232 LM_ERR("cannot print user pseudo-variable\n");
00233 return -1;
00234 }
00235 }
00236
00237 if(((pv_elem_p)str2)->spec.getf) {
00238 if(pv_printf_s(msg, (pv_elem_p)str2, &domain) != 0) {
00239 LM_ERR("cannot print domain pseudo-variable\n");
00240 return -1;
00241 }
00242 }
00243
00244 if(str3 != NULL && ((pv_elem_p)str3)->spec.getf) {
00245 if(pv_printf_s(msg, (pv_elem_p)str3, &number) != 0) {
00246 LM_ERR("cannot print number pseudo-variable\n");
00247 return -1;
00248 }
00249 }
00250
00251 if(str4 != NULL && strlen(str4) > 0) {
00252
00253 table.s=str4;
00254 table.len=strlen(str4);
00255 } else {
00256
00257 table.len=userblacklist_table.len;
00258 table.s=userblacklist_table.s;
00259 }
00260
00261 if (msg->first_line.type != SIP_REQUEST) {
00262 LM_ERR("SIP msg is not a request\n");
00263 return -1;
00264 }
00265
00266 if(number.s == NULL) {
00267
00268 if ((parse_sip_msg_uri(msg) < 0) || (!msg->parsed_uri.user.s) || (msg->parsed_uri.user.len > MAXNUMBERLEN)) {
00269 LM_ERR("cannot parse msg URI\n");
00270 return -1;
00271 }
00272 strncpy(req_number, msg->parsed_uri.user.s, msg->parsed_uri.user.len);
00273 req_number[msg->parsed_uri.user.len] = '\0';
00274 } else {
00275 if (number.len > MAXNUMBERLEN) {
00276 LM_ERR("number to long\n");
00277 return -1;
00278 }
00279 strncpy(req_number, number.s, number.len);
00280 req_number[number.len] = '\0';
00281 }
00282
00283 LM_DBG("check entry %s for user %.*s on domain %.*s in table %.*s\n", req_number,
00284 user.len, user.s, domain.len, domain.s, table.len, table.s);
00285 if (db_build_userbl_tree(&user, &domain, &table, dtrie_root, use_domain) < 0) {
00286 LM_ERR("cannot build d-tree\n");
00287 return -1;
00288 }
00289
00290 ptr = req_number;
00291
00292 while (match_mode == 10 && strlen(ptr) > 0 && !isdigit(*ptr)) {
00293 ptr = ptr + 1;
00294 }
00295
00296 nodeflags = dtrie_longest_match(dtrie_root, ptr, strlen(ptr), NULL, match_mode);
00297 if (nodeflags) {
00298 if (*nodeflags == (void *)MARK_WHITELIST) {
00299
00300 return 1;
00301 }
00302 } else {
00303 if(!listtype) {
00304
00305 return 1;
00306 } else {
00307
00308 return -1;
00309 }
00310 }
00311 LM_DBG("entry %s is blacklisted\n", req_number);
00312 return -1;
00313 }
00314
00315
00316 static int check_user_whitelist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4)
00317 {
00318 return check_user_list(msg, str1, str2, str3, str4, 1);
00319 }
00320
00321
00322 static int check_user_blacklist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4)
00323 {
00324 return check_user_list(msg, str1, str2, str3, str4, 0);
00325 }
00326
00327 static int check_user_whitelist2(struct sip_msg *msg, char* str1, char* str2)
00328 {
00329 return check_user_list(msg, str1, str2, NULL, NULL, 1);
00330 }
00331
00332
00333 static int check_user_blacklist2(struct sip_msg *msg, char* str1, char* str2)
00334 {
00335 return check_user_list(msg, str1, str2, NULL, NULL, 0);
00336 }
00337
00338 static int check_user_whitelist3(struct sip_msg *msg, char* str1, char* str2, char* str3)
00339 {
00340 return check_user_list(msg, str1, str2, str3, NULL, 1);
00341 }
00342
00343
00344 static int check_user_blacklist3(struct sip_msg *msg, char* str1, char* str2, char* str3)
00345 {
00346 return check_user_list(msg, str1, str2, str3, NULL, 0);
00347 }
00348
00349
00354 static struct dtrie_node_t *table2dt(const char *table)
00355 {
00356 struct source_t *src = sources->head;
00357 while (src) {
00358 if (strcmp(table, src->table) == 0) return src->dtrie_root;
00359 src = src->next;
00360 }
00361
00362 LM_ERR("invalid table '%s'.\n", table);
00363 return NULL;
00364 }
00365
00366
00372 static int add_source(const char *table)
00373 {
00374
00375 struct source_t *src = sources->head;
00376 while (src) {
00377 if (strcmp(table, src->table) == 0) return 0;
00378 src = src->next;
00379 }
00380
00381 src = shm_malloc(sizeof(struct source_t));
00382 if (!src) {
00383 SHM_MEM_ERROR;
00384 return -1;
00385 }
00386 memset(src, 0, sizeof(struct source_t));
00387
00388 src->next = sources->head;
00389 sources->head = src;
00390
00391 src->table = shm_malloc(strlen(table)+1);
00392 if (!src->table) {
00393 SHM_MEM_ERROR;
00394 shm_free(src);
00395 return -1;
00396 }
00397 strcpy(src->table, table);
00398 LM_DBG("add table %s", table);
00399
00400 src->dtrie_root = dtrie_init(match_mode);
00401
00402 if (src->dtrie_root == NULL) {
00403 LM_ERR("could not initialize data");
00404 return -1;
00405 }
00406
00407 return 0;
00408 }
00409
00410
00411 static int check_globalblacklist_fixup(void** param, int param_no)
00412 {
00413 char * table = globalblacklist_table.s;
00414 if(param_no > 0){
00415 LM_ERR("Wrong number of parameters\n");
00416 return -1;
00417 }
00418
00419 if (!table) {
00420 LM_ERR("no table name\n");
00421 return -1;
00422 }
00423
00424 if (add_source(table) != 0) {
00425 LM_ERR("could not add table");
00426 return -1;
00427 }
00428
00429 gnode = table2dt(table);
00430 if (!gnode) {
00431 LM_ERR("invalid table '%s'\n", table);
00432 return -1;
00433 }
00434
00435 return 0;
00436 }
00437
00438 static int check_globalblacklist(struct sip_msg* msg)
00439 {
00440 static struct check_blacklist_fs_t* arg = NULL;
00441 if(!arg){
00442 arg = pkg_malloc(sizeof(struct check_blacklist_fs_t));
00443 if (!arg) {
00444 PKG_MEM_ERROR;
00445 return -1;
00446 }
00447 memset(arg, 0, sizeof(struct check_blacklist_fs_t));
00448 arg->dtrie_root = gnode;
00449 }
00450 return check_blacklist(msg, arg);
00451 }
00452
00453 static int check_blacklist_fixup(void **arg, int arg_no)
00454 {
00455 char *table = (char *)(*arg);
00456 struct dtrie_node_t *node = NULL;
00457 struct check_blacklist_fs_t *new_arg;
00458
00459 if (arg_no != 1) {
00460 LM_ERR("wrong number of parameters\n");
00461 return -1;
00462 }
00463
00464 if (!table) {
00465 LM_ERR("no table name\n");
00466 return -1;
00467 }
00468
00469 if (add_source(table) != 0) {
00470 LM_ERR("could not add table");
00471 return -1;
00472 }
00473
00474
00475 node = table2dt(table);
00476 if (!node) {
00477 LM_ERR("invalid table '%s'\n", table);
00478 return -1;
00479 }
00480
00481 new_arg = pkg_malloc(sizeof(struct check_blacklist_fs_t));
00482 if (!new_arg) {
00483 PKG_MEM_ERROR;
00484 return -1;
00485 }
00486 memset(new_arg, 0, sizeof(struct check_blacklist_fs_t));
00487 new_arg->dtrie_root = node;
00488 *arg=(void*)new_arg;
00489
00490 return 0;
00491 }
00492
00493
00494 static int check_blacklist(struct sip_msg *msg, struct check_blacklist_fs_t *arg1)
00495 {
00496 void **nodeflags;
00497 char *ptr;
00498 char req_number[MAXNUMBERLEN+1];
00499 int ret = -1;
00500
00501 if (msg->first_line.type != SIP_REQUEST) {
00502 LM_ERR("SIP msg is not a request\n");
00503 return -1;
00504 }
00505
00506 if ((parse_sip_msg_uri(msg) < 0) || (!msg->parsed_uri.user.s) || (msg->parsed_uri.user.len > MAXNUMBERLEN)) {
00507 LM_ERR("cannot parse msg URI\n");
00508 return -1;
00509 }
00510 strncpy(req_number, msg->parsed_uri.user.s, msg->parsed_uri.user.len);
00511 req_number[msg->parsed_uri.user.len] = '\0';
00512
00513 ptr = req_number;
00514
00515 while (match_mode == 10 && strlen(ptr) > 0 && !isdigit(*ptr)) {
00516 ptr = ptr + 1;
00517 }
00518
00519 LM_DBG("check entry %s\n", req_number);
00520
00521
00522 lock_get(lock);
00523 nodeflags = dtrie_longest_match(arg1->dtrie_root, ptr, strlen(ptr), NULL, match_mode);
00524 if (nodeflags) {
00525 if (*nodeflags == (void *)MARK_WHITELIST) {
00526
00527 ret = 1;
00528 }
00529 }
00530 else {
00531
00532 ret = 1;
00533 }
00534 lock_release(lock);
00535
00536 LM_DBG("entry %s is blacklisted\n", req_number);
00537 return ret;
00538 }
00539
00540
00545 static int reload_sources(void)
00546 {
00547 int result = 0;
00548 str tmp;
00549 struct source_t *src;
00550 int n;
00551
00552
00553 lock_get(lock);
00554
00555 src = sources->head;
00556 while (src) {
00557 tmp.s = src->table;
00558 tmp.len = strlen(src->table);
00559 n = db_reload_source(&tmp, src->dtrie_root);
00560 if (n < 0) {
00561 LM_ERR("cannot reload source from '%.*s'\n", tmp.len, tmp.s);
00562 result = -1;
00563 break;
00564 }
00565 LM_INFO("got %d entries from '%.*s'\n", n, tmp.len, tmp.s);
00566 src = src->next;
00567 }
00568
00569
00570 lock_release(lock);
00571
00572 return result;
00573 }
00574
00575
00576 static int init_source_list(void)
00577 {
00578 sources = shm_malloc(sizeof(struct source_list_t));
00579 if (!sources) {
00580 SHM_MEM_ERROR;
00581 return -1;
00582 }
00583 sources->head = NULL;
00584 return 0;
00585 }
00586
00587
00588 static void destroy_source_list(void)
00589 {
00590 if (sources) {
00591 while (sources->head) {
00592 struct source_t *src = sources->head;
00593 sources->head = src->next;
00594
00595 if (src->table) shm_free(src->table);
00596 dtrie_destroy(&(src->dtrie_root), NULL, match_mode);
00597 shm_free(src);
00598 }
00599
00600 shm_free(sources);
00601 sources = NULL;
00602 }
00603 }
00604
00605
00606 static int init_shmlock(void)
00607 {
00608 lock = lock_alloc();
00609 if (!lock) {
00610 LM_CRIT("cannot allocate memory for lock.\n");
00611 return -1;
00612 }
00613 if (lock_init(lock) == 0) {
00614 LM_CRIT("cannot initialize lock.\n");
00615 return -1;
00616 }
00617
00618 return 0;
00619 }
00620
00621
00622 static void destroy_shmlock(void)
00623 {
00624 if (lock) {
00625 lock_destroy(lock);
00626 lock_dealloc((void *)lock);
00627 lock = NULL;
00628 }
00629 }
00630
00631
00632 struct mi_root * mi_reload_blacklist(struct mi_root* cmd, void* param)
00633 {
00634 struct mi_root * tmp = NULL;
00635 if(reload_sources() == 0) {
00636 tmp = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00637 } else {
00638 tmp = init_mi_tree( 500, "cannot reload blacklist", 21);
00639 }
00640
00641 return tmp;
00642 }
00643
00644
00645 static int mod_init(void)
00646 {
00647 if(register_mi_mod(exports.name, mi_cmds)!=0)
00648 {
00649 LM_ERR("failed to register MI commands\n");
00650 return -1;
00651 }
00652
00653 userblacklist_db_vars();
00654
00655 if (userblacklist_db_init() != 0) return -1;
00656 if (init_shmlock() != 0) return -1;
00657 if (init_source_list() != 0) return -1;
00658 return 0;
00659 }
00660
00661
00662 static int child_init(int rank)
00663 {
00664 if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
00665 return 0;
00666
00667 return mi_child_init();
00668 }
00669
00670
00671 static int userblacklist_child_initialized = 0;
00672
00673 static int mi_child_init(void)
00674 {
00675 if(userblacklist_child_initialized)
00676 return 0;
00677 if (userblacklist_db_open() != 0) return -1;
00678 dtrie_root=dtrie_init(match_mode);
00679 if (dtrie_root == NULL) {
00680 LM_ERR("could not initialize data");
00681 return -1;
00682 }
00683
00684 if (reload_sources() != 0) return -1;
00685
00686 userblacklist_child_initialized = 1;
00687
00688 return 0;
00689 }
00690
00691
00692 static void mod_destroy(void)
00693 {
00694 destroy_source_list();
00695 destroy_shmlock();
00696 userblacklist_db_close();
00697 dtrie_destroy(&dtrie_root, NULL, match_mode);
00698 }