1 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,698 +0,0 @@ |
1 |
-/* |
|
2 |
- * $Id$ |
|
3 |
- * |
|
4 |
- * Copyright (C) 2007 1&1 Internet AG |
|
5 |
- * |
|
6 |
- * This file is part of Kamailio, a free SIP server. |
|
7 |
- * |
|
8 |
- * Kamailio is free software; you can redistribute it and/or modify |
|
9 |
- * it under the terms of the GNU General Public License as published by |
|
10 |
- * the Free Software Foundation; either version 2 of the License, or |
|
11 |
- * (at your option) any later version |
|
12 |
- * |
|
13 |
- * Kamailio is distributed in the hope that it will be useful, |
|
14 |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15 |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
16 |
- * GNU General Public License for more details. |
|
17 |
- * |
|
18 |
- * You should have received a copy of the GNU General Public License |
|
19 |
- * along with this program; if not, write to the Free Software |
|
20 |
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
21 |
- */ |
|
22 |
- |
|
23 |
-/*! |
|
24 |
- * \file |
|
25 |
- * \brief USERBLACKLIST :: module definitions |
|
26 |
- * \ingroup userblacklist |
|
27 |
- * - Module: \ref userblacklist |
|
28 |
- */ |
|
29 |
- |
|
30 |
-/*! |
|
31 |
- * \defgroup userblacklist USERBLACKLIST :: The Kamailio userblacklist Module |
|
32 |
- * |
|
33 |
- * The userblacklist module allows Kamailio to handle blacklists on a per user basis. |
|
34 |
- * This information is stored in a database table, which is queried to decide if the |
|
35 |
- * number (more exactly, the request URI user) is blacklisted or not. |
|
36 |
- * An additional functionality that this module provides is the ability to handle |
|
37 |
- * global blacklists. This lists are loaded on startup into memory, thus providing a |
|
38 |
- * better performance then in the userblacklist case. |
|
39 |
- */ |
|
40 |
- |
|
41 |
-#include <string.h> |
|
42 |
- |
|
43 |
-#include "../../parser/parse_uri.h" |
|
44 |
-#include "../../mem/shm_mem.h" |
|
45 |
-#include "../../sr_module.h" |
|
46 |
-#include "../../lib/kmi/mi.h" |
|
47 |
-#include "../../mem/mem.h" |
|
48 |
-#include "../../usr_avp.h" |
|
49 |
-#include "../../locking.h" |
|
50 |
-#include "../../error.h" |
|
51 |
-#include "../../ut.h" |
|
52 |
-#include "../../mod_fix.h" |
|
53 |
- |
|
54 |
-#include "../../lib/trie/dtrie.h" |
|
55 |
-#include "db.h" |
|
56 |
-#include "db_userblacklist.h" |
|
57 |
- |
|
58 |
-MODULE_VERSION |
|
59 |
- |
|
60 |
- |
|
61 |
-#define MAXNUMBERLEN 31 |
|
62 |
- |
|
63 |
- |
|
64 |
-typedef struct _avp_check |
|
65 |
-{ |
|
66 |
- int avp_flags; |
|
67 |
- int_str avp_name; |
|
68 |
-} avp_check_t; |
|
69 |
- |
|
70 |
- |
|
71 |
-struct check_blacklist_fs_t { |
|
72 |
- struct dtrie_node_t *dtrie_root; |
|
73 |
-}; |
|
74 |
- |
|
75 |
-str userblacklist_db_url = str_init(DEFAULT_RODB_URL); |
|
76 |
-int use_domain = 0; |
|
77 |
-int match_mode = 10; /* numeric */ |
|
78 |
-static struct dtrie_node_t *gnode = NULL; |
|
79 |
- |
|
80 |
-/* ---- fixup functions: */ |
|
81 |
-static int check_blacklist_fixup(void** param, int param_no); |
|
82 |
-static int check_user_blacklist_fixup(void** param, int param_no); |
|
83 |
-static int check_globalblacklist_fixup(void** param, int param_no); |
|
84 |
- |
|
85 |
-/* ---- exported commands: */ |
|
86 |
-static int check_user_blacklist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4); |
|
87 |
-static int check_user_whitelist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4); |
|
88 |
-static int check_user_blacklist2(struct sip_msg *msg, char* str1, char* str2); |
|
89 |
-static int check_user_whitelist2(struct sip_msg *msg, char* str1, char* str2); |
|
90 |
-static int check_user_blacklist3(struct sip_msg *msg, char* str1, char* str2, char* str3); |
|
91 |
-static int check_user_whitelist3(struct sip_msg *msg, char* str1, char* str2, char* str3); |
|
92 |
-static int check_blacklist(struct sip_msg *msg, struct check_blacklist_fs_t *arg1); |
|
93 |
-static int check_globalblacklist(struct sip_msg *msg); |
|
94 |
- |
|
95 |
- |
|
96 |
-/* ---- module init functions: */ |
|
97 |
-static int mod_init(void); |
|
98 |
-static int child_init(int rank); |
|
99 |
-static int mi_child_init(void); |
|
100 |
-static void mod_destroy(void); |
|
101 |
- |
|
102 |
-/* --- fifo functions */ |
|
103 |
-struct mi_root * mi_reload_blacklist(struct mi_root* cmd, void* param); /* usage: kamctl fifo reload_blacklist */ |
|
104 |
- |
|
105 |
- |
|
106 |
-static cmd_export_t cmds[]={ |
|
107 |
- { "check_user_blacklist", (cmd_function)check_user_blacklist2, 2, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE }, |
|
108 |
- { "check_user_whitelist", (cmd_function)check_user_whitelist2, 2, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE }, |
|
109 |
- { "check_user_blacklist", (cmd_function)check_user_blacklist3, 3, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE }, |
|
110 |
- { "check_user_whitelist", (cmd_function)check_user_whitelist3, 3, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE }, |
|
111 |
- { "check_user_blacklist", (cmd_function)check_user_blacklist, 4, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE }, |
|
112 |
- { "check_user_whitelist", (cmd_function)check_user_whitelist, 4, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE }, |
|
113 |
- { "check_blacklist", (cmd_function)check_blacklist, 1, check_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE }, |
|
114 |
- { "check_blacklist", (cmd_function)check_globalblacklist, 0, check_globalblacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE }, |
|
115 |
- { 0, 0, 0, 0, 0, 0} |
|
116 |
-}; |
|
117 |
- |
|
118 |
- |
|
119 |
-static param_export_t params[] = { |
|
120 |
- userblacklist_DB_URL |
|
121 |
- userblacklist_DB_TABLE |
|
122 |
- globalblacklist_DB_TABLE |
|
123 |
- userblacklist_DB_COLS |
|
124 |
- globalblacklist_DB_COLS |
|
125 |
- { "use_domain", INT_PARAM, &use_domain }, |
|
126 |
- { "match_mode", INT_PARAM, &match_mode}, |
|
127 |
- { 0, 0, 0} |
|
128 |
-}; |
|
129 |
- |
|
130 |
- |
|
131 |
-/* Exported MI functions */ |
|
132 |
-static mi_export_t mi_cmds[] = { |
|
133 |
- { "reload_blacklist", mi_reload_blacklist, MI_NO_INPUT_FLAG, 0, mi_child_init }, |
|
134 |
- { 0, 0, 0, 0, 0} |
|
135 |
-}; |
|
136 |
- |
|
137 |
- |
|
138 |
-struct module_exports exports= { |
|
139 |
- "userblacklist", |
|
140 |
- DEFAULT_DLFLAGS, |
|
141 |
- cmds, |
|
142 |
- params, |
|
143 |
- 0, |
|
144 |
- mi_cmds, |
|
145 |
- 0, |
|
146 |
- 0, |
|
147 |
- mod_init, |
|
148 |
- 0, |
|
149 |
- mod_destroy, |
|
150 |
- child_init |
|
151 |
-}; |
|
152 |
- |
|
153 |
- |
|
154 |
-struct source_t { |
|
155 |
- struct source_t *next; |
|
156 |
- /** prefixes to be used are stored in this table */ |
|
157 |
- char *table; |
|
158 |
- /** d-tree structure: will be built from data in database */ |
|
159 |
- struct dtrie_node_t *dtrie_root; |
|
160 |
-}; |
|
161 |
- |
|
162 |
- |
|
163 |
-struct source_list_t { |
|
164 |
- struct source_t *head; |
|
165 |
-}; |
|
166 |
- |
|
167 |
- |
|
168 |
-static gen_lock_t *lock = NULL; |
|
169 |
-static struct source_list_t *sources = NULL; |
|
170 |
-static struct dtrie_node_t *dtrie_root; |
|
171 |
- |
|
172 |
- |
|
173 |
-static int check_user_blacklist_fixup(void** param, int param_no) |
|
174 |
-{ |
|
175 |
- pv_elem_t *model=NULL; |
|
176 |
- str s; |
|
177 |
- |
|
178 |
- /* convert to str */ |
|
179 |
- s.s = (char*)*param; |
|
180 |
- s.len = strlen(s.s); |
|
181 |
- |
|
182 |
- if (param_no > 0 && param_no <= 4) { |
|
183 |
- if(s.len == 0 && param_no != 4) { |
|
184 |
- LM_ERR("no parameter %d\n", param_no); |
|
185 |
- return E_UNSPEC; |
|
186 |
- } |
|
187 |
- |
|
188 |
- if(pv_parse_format(&s, &model) < 0 || !model) { |
|
189 |
- LM_ERR("wrong format [%.*s] for parameter %d\n", s.len, s.s, param_no); |
|
190 |
- return E_UNSPEC; |
|
191 |
- } |
|
192 |
- |
|
193 |
- if(model->spec==NULL || model->spec->getf==NULL) { |
|
194 |
- if(param_no == 1) { |
|
195 |
- if(str2int(&s, (unsigned int*)&model->spec->pvp.pvn.u.isname.name.n) != 0) { |
|
196 |
- LM_ERR("wrong value [%.*s] for parameter %d\n", s.len, s.s, param_no); |
|
197 |
- return E_UNSPEC; |
|
198 |
- } |
|
199 |
- } else { |
|
200 |
- if(param_no == 2 || param_no == 3) { |
|
201 |
- LM_ERR("wrong value [%.*s] for parameter %d\n", s.len, s.s, param_no); |
|
202 |
- return E_UNSPEC; |
|
203 |
- } else { |
|
204 |
- // only a string |
|
205 |
- return 0; |
|
206 |
- } |
|
207 |
- } |
|
208 |
- } |
|
209 |
- *param = (void*)model; |
|
210 |
- } else { |
|
211 |
- LM_ERR("wrong number of parameters\n"); |
|
212 |
- } |
|
213 |
- |
|
214 |
- return 0; |
|
215 |
-} |
|
216 |
- |
|
217 |
- |
|
218 |
-static int check_user_list(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4, int listtype) |
|
219 |
-{ |
|
220 |
- str user = { .len = 0, .s = NULL }; |
|
221 |
- str domain = { .len = 0, .s = NULL}; |
|
222 |
- str table = { .len = 0, .s = NULL}; |
|
223 |
- str number = { .len = 0, .s = NULL}; |
|
224 |
- |
|
225 |
- void **nodeflags; |
|
226 |
- char *ptr; |
|
227 |
- char req_number[MAXNUMBERLEN+1]; |
|
228 |
- |
|
229 |
- /* user */ |
|
230 |
- if(((pv_elem_p)str1)->spec!=NULL && ((pv_elem_p)str1)->spec->getf!=NULL) { |
|
231 |
- if(pv_printf_s(msg, (pv_elem_p)str1, &user) != 0) { |
|
232 |
- LM_ERR("cannot print user pseudo-variable\n"); |
|
233 |
- return -1; |
|
234 |
- } |
|
235 |
- } |
|
236 |
- /* domain */ |
|
237 |
- if(((pv_elem_p)str2)->spec!=NULL && ((pv_elem_p)str2)->spec->getf) { |
|
238 |
- if(pv_printf_s(msg, (pv_elem_p)str2, &domain) != 0) { |
|
239 |
- LM_ERR("cannot print domain pseudo-variable\n"); |
|
240 |
- return -1; |
|
241 |
- } |
|
242 |
- } |
|
243 |
- /* source number */ |
|
244 |
- if(str3 != NULL && ((pv_elem_p)str3)->spec!=NULL && ((pv_elem_p)str3)->spec->getf!=NULL) { |
|
245 |
- if(pv_printf_s(msg, (pv_elem_p)str3, &number) != 0) { |
|
246 |
- LM_ERR("cannot print number pseudo-variable\n"); |
|
247 |
- return -1; |
|
248 |
- } |
|
249 |
- } |
|
250 |
- /* table name */ |
|
251 |
- if(str4 != NULL && strlen(str4) > 0) { |
|
252 |
- /* string */ |
|
253 |
- table.s=str4; |
|
254 |
- table.len=strlen(str4); |
|
255 |
- } else { |
|
256 |
- /* use default table name */ |
|
257 |
- table.len=userblacklist_table.len; |
|
258 |
- table.s=userblacklist_table.s; |
|
259 |
- } |
|
260 |
- |
|
261 |
- if (msg->first_line.type != SIP_REQUEST) { |
|
262 |
- LM_ERR("SIP msg is not a request\n"); |
|
263 |
- return -1; |
|
264 |
- } |
|
265 |
- |
|
266 |
- if(number.s == NULL) { |
|
267 |
- /* use R-URI */ |
|
268 |
- if ((parse_sip_msg_uri(msg) < 0) || (!msg->parsed_uri.user.s) || (msg->parsed_uri.user.len > MAXNUMBERLEN)) { |
|
269 |
- LM_ERR("cannot parse msg URI\n"); |
|
270 |
- return -1; |
|
271 |
- } |
|
272 |
- strncpy(req_number, msg->parsed_uri.user.s, msg->parsed_uri.user.len); |
|
273 |
- req_number[msg->parsed_uri.user.len] = '\0'; |
|
274 |
- } else { |
|
275 |
- if (number.len > MAXNUMBERLEN) { |
|
276 |
- LM_ERR("number to long\n"); |
|
277 |
- return -1; |
|
278 |
- } |
|
279 |
- strncpy(req_number, number.s, number.len); |
|
280 |
- req_number[number.len] = '\0'; |
|
281 |
- } |
|
282 |
- |
|
283 |
- LM_DBG("check entry %s for user %.*s on domain %.*s in table %.*s\n", req_number, |
|
284 |
- user.len, user.s, domain.len, domain.s, table.len, table.s); |
|
285 |
- if (db_build_userbl_tree(&user, &domain, &table, dtrie_root, use_domain) < 0) { |
|
286 |
- LM_ERR("cannot build d-tree\n"); |
|
287 |
- return -1; |
|
288 |
- } |
|
289 |
- |
|
290 |
- ptr = req_number; |
|
291 |
- /* Skip over non-digits. */ |
|
292 |
- while (match_mode == 10 && strlen(ptr) > 0 && !isdigit(*ptr)) { |
|
293 |
- ptr = ptr + 1; |
|
294 |
- } |
|
295 |
- |
|
296 |
- nodeflags = dtrie_longest_match(dtrie_root, ptr, strlen(ptr), NULL, match_mode); |
|
297 |
- if (nodeflags) { |
|
298 |
- if (*nodeflags == (void *)MARK_WHITELIST) { |
|
299 |
- /* LM_ERR("whitelisted"); */ |
|
300 |
- return 1; /* found, but is whitelisted */ |
|
301 |
- } |
|
302 |
- } else { |
|
303 |
- if(!listtype) { |
|
304 |
- /* LM_ERR("not found return 1"); */ |
|
305 |
- return 1; /* not found is ok */ |
|
306 |
- } else { |
|
307 |
- /* LM_ERR("not found return -1"); */ |
|
308 |
- return -1; /* not found is not ok */ |
|
309 |
- } |
|
310 |
- } |
|
311 |
- LM_DBG("entry %s is blacklisted\n", req_number); |
|
312 |
- return -1; |
|
313 |
-} |
|
314 |
- |
|
315 |
- |
|
316 |
-static int check_user_whitelist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4) |
|
317 |
-{ |
|
318 |
- return check_user_list(msg, str1, str2, str3, str4, 1); |
|
319 |
-} |
|
320 |
- |
|
321 |
- |
|
322 |
-static int check_user_blacklist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4) |
|
323 |
-{ |
|
324 |
- return check_user_list(msg, str1, str2, str3, str4, 0); |
|
325 |
-} |
|
326 |
- |
|
327 |
-static int check_user_whitelist2(struct sip_msg *msg, char* str1, char* str2) |
|
328 |
-{ |
|
329 |
- return check_user_list(msg, str1, str2, NULL, NULL, 1); |
|
330 |
-} |
|
331 |
- |
|
332 |
- |
|
333 |
-static int check_user_blacklist2(struct sip_msg *msg, char* str1, char* str2) |
|
334 |
-{ |
|
335 |
- return check_user_list(msg, str1, str2, NULL, NULL, 0); |
|
336 |
-} |
|
337 |
- |
|
338 |
-static int check_user_whitelist3(struct sip_msg *msg, char* str1, char* str2, char* str3) |
|
339 |
-{ |
|
340 |
- return check_user_list(msg, str1, str2, str3, NULL, 1); |
|
341 |
-} |
|
342 |
- |
|
343 |
- |
|
344 |
-static int check_user_blacklist3(struct sip_msg *msg, char* str1, char* str2, char* str3) |
|
345 |
-{ |
|
346 |
- return check_user_list(msg, str1, str2, str3, NULL, 0); |
|
347 |
-} |
|
348 |
- |
|
349 |
- |
|
350 |
-/** |
|
351 |
- * Finds d-tree root for given table. |
|
352 |
- * \return pointer to d-tree root on success, NULL otherwise |
|
353 |
- */ |
|
354 |
-static struct dtrie_node_t *table2dt(const char *table) |
|
355 |
-{ |
|
356 |
- struct source_t *src = sources->head; |
|
357 |
- while (src) { |
|
358 |
- if (strcmp(table, src->table) == 0) return src->dtrie_root; |
|
359 |
- src = src->next; |
|
360 |
- } |
|
361 |
- |
|
362 |
- LM_ERR("invalid table '%s'.\n", table); |
|
363 |
- return NULL; |
|
364 |
-} |
|
365 |
- |
|
366 |
- |
|
367 |
-/** |
|
368 |
- * Adds a new table to the list, if the table is |
|
369 |
- * already present, nothing will be done. |
|
370 |
- * \return zero on success, negative on errors |
|
371 |
- */ |
|
372 |
-static int add_source(const char *table) |
|
373 |
-{ |
|
374 |
- /* check if the table is already present */ |
|
375 |
- struct source_t *src = sources->head; |
|
376 |
- while (src) { |
|
377 |
- if (strcmp(table, src->table) == 0) return 0; |
|
378 |
- src = src->next; |
|
379 |
- } |
|
380 |
- |
|
381 |
- src = shm_malloc(sizeof(struct source_t)); |
|
382 |
- if (!src) { |
|
383 |
- SHM_MEM_ERROR; |
|
384 |
- return -1; |
|
385 |
- } |
|
386 |
- memset(src, 0, sizeof(struct source_t)); |
|
387 |
- |
|
388 |
- src->next = sources->head; |
|
389 |
- sources->head = src; |
|
390 |
- |
|
391 |
- src->table = shm_malloc(strlen(table)+1); |
|
392 |
- if (!src->table) { |
|
393 |
- SHM_MEM_ERROR; |
|
394 |
- shm_free(src); |
|
395 |
- return -1; |
|
396 |
- } |
|
397 |
- strcpy(src->table, table); |
|
398 |
- LM_DBG("add table %s", table); |
|
399 |
- |
|
400 |
- src->dtrie_root = dtrie_init(match_mode); |
|
401 |
- |
|
402 |
- if (src->dtrie_root == NULL) { |
|
403 |
- LM_ERR("could not initialize data"); |
|
404 |
- return -1; |
|
405 |
- } |
|
406 |
- |
|
407 |
- return 0; |
|
408 |
-} |
|
409 |
- |
|
410 |
- |
|
411 |
-static int check_globalblacklist_fixup(void** param, int param_no) |
|
412 |
-{ |
|
413 |
- char * table = globalblacklist_table.s; |
|
414 |
- if(param_no > 0){ |
|
415 |
- LM_ERR("Wrong number of parameters\n"); |
|
416 |
- return -1; |
|
417 |
- } |
|
418 |
- |
|
419 |
- if (!table) { |
|
420 |
- LM_ERR("no table name\n"); |
|
421 |
- return -1; |
|
422 |
- } |
|
423 |
- /* try to add the table */ |
|
424 |
- if (add_source(table) != 0) { |
|
425 |
- LM_ERR("could not add table"); |
|
426 |
- return -1; |
|
427 |
- } |
|
428 |
- |
|
429 |
- gnode = table2dt(table); |
|
430 |
- if (!gnode) { |
|
431 |
- LM_ERR("invalid table '%s'\n", table); |
|
432 |
- return -1; |
|
433 |
- } |
|
434 |
- |
|
435 |
- return 0; |
|
436 |
-} |
|
437 |
- |
|
438 |
-static int check_globalblacklist(struct sip_msg* msg) |
|
439 |
-{ |
|
440 |
- static struct check_blacklist_fs_t* arg = NULL; |
|
441 |
- if(!arg){ |
|
442 |
- arg = pkg_malloc(sizeof(struct check_blacklist_fs_t)); |
|
443 |
- if (!arg) { |
|
444 |
- PKG_MEM_ERROR; |
|
445 |
- return -1; |
|
446 |
- } |
|
447 |
- memset(arg, 0, sizeof(struct check_blacklist_fs_t)); |
|
448 |
- arg->dtrie_root = gnode; |
|
449 |
- } |
|
450 |
- return check_blacklist(msg, arg); |
|
451 |
-} |
|
452 |
- |
|
453 |
-static int check_blacklist_fixup(void **arg, int arg_no) |
|
454 |
-{ |
|
455 |
- char *table = (char *)(*arg); |
|
456 |
- struct dtrie_node_t *node = NULL; |
|
457 |
- struct check_blacklist_fs_t *new_arg; |
|
458 |
- |
|
459 |
- if (arg_no != 1) { |
|
460 |
- LM_ERR("wrong number of parameters\n"); |
|
461 |
- return -1; |
|
462 |
- } |
|
463 |
- |
|
464 |
- if (!table) { |
|
465 |
- LM_ERR("no table name\n"); |
|
466 |
- return -1; |
|
467 |
- } |
|
468 |
- /* try to add the table */ |
|
469 |
- if (add_source(table) != 0) { |
|
470 |
- LM_ERR("could not add table"); |
|
471 |
- return -1; |
|
472 |
- } |
|
473 |
- |
|
474 |
- /* get the node that belongs to the table */ |
|
475 |
- node = table2dt(table); |
|
476 |
- if (!node) { |
|
477 |
- LM_ERR("invalid table '%s'\n", table); |
|
478 |
- return -1; |
|
479 |
- } |
|
480 |
- |
|
481 |
- new_arg = pkg_malloc(sizeof(struct check_blacklist_fs_t)); |
|
482 |
- if (!new_arg) { |
|
483 |
- PKG_MEM_ERROR; |
|
484 |
- return -1; |
|
485 |
- } |
|
486 |
- memset(new_arg, 0, sizeof(struct check_blacklist_fs_t)); |
|
487 |
- new_arg->dtrie_root = node; |
|
488 |
- *arg=(void*)new_arg; |
|
489 |
- |
|
490 |
- return 0; |
|
491 |
-} |
|
492 |
- |
|
493 |
- |
|
494 |
-static int check_blacklist(struct sip_msg *msg, struct check_blacklist_fs_t *arg1) |
|
495 |
-{ |
|
496 |
- void **nodeflags; |
|
497 |
- char *ptr; |
|
498 |
- char req_number[MAXNUMBERLEN+1]; |
|
499 |
- int ret = -1; |
|
500 |
- |
|
501 |
- if (msg->first_line.type != SIP_REQUEST) { |
|
502 |
- LM_ERR("SIP msg is not a request\n"); |
|
503 |
- return -1; |
|
504 |
- } |
|
505 |
- |
|
506 |
- if ((parse_sip_msg_uri(msg) < 0) || (!msg->parsed_uri.user.s) || (msg->parsed_uri.user.len > MAXNUMBERLEN)) { |
|
507 |
- LM_ERR("cannot parse msg URI\n"); |
|
508 |
- return -1; |
|
509 |
- } |
|
510 |
- strncpy(req_number, msg->parsed_uri.user.s, msg->parsed_uri.user.len); |
|
511 |
- req_number[msg->parsed_uri.user.len] = '\0'; |
|
512 |
- |
|
513 |
- ptr = req_number; |
|
514 |
- /* Skip over non-digits. */ |
|
515 |
- while (match_mode == 10 && strlen(ptr) > 0 && !isdigit(*ptr)) { |
|
516 |
- ptr = ptr + 1; |
|
517 |
- } |
|
518 |
- |
|
519 |
- LM_DBG("check entry %s\n", req_number); |
|
520 |
- |
|
521 |
- /* avoids dirty reads when updating d-tree */ |
|
522 |
- lock_get(lock); |
|
523 |
- nodeflags = dtrie_longest_match(arg1->dtrie_root, ptr, strlen(ptr), NULL, match_mode); |
|
524 |
- if (nodeflags) { |
|
525 |
- if (*nodeflags == (void *)MARK_WHITELIST) { |
|
526 |
- /* LM_DBG("whitelisted"); */ |
|
527 |
- ret = 1; /* found, but is whitelisted */ |
|
528 |
- } |
|
529 |
- } |
|
530 |
- else { |
|
531 |
- /* LM_ERR("not found"); */ |
|
532 |
- ret = 1; /* not found is ok */ |
|
533 |
- } |
|
534 |
- lock_release(lock); |
|
535 |
- |
|
536 |
- LM_DBG("entry %s is blacklisted\n", req_number); |
|
537 |
- return ret; |
|
538 |
-} |
|
539 |
- |
|
540 |
- |
|
541 |
-/** |
|
542 |
- * Fills the d-tree for all configured and prepared sources. |
|
543 |
- * \return 0 on success, -1 otherwise |
|
544 |
- */ |
|
545 |
-static int reload_sources(void) |
|
546 |
-{ |
|
547 |
- int result = 0; |
|
548 |
- str tmp; |
|
549 |
- struct source_t *src; |
|
550 |
- int n; |
|
551 |
- |
|
552 |
- /* critical section start: avoids dirty reads when updating d-tree */ |
|
553 |
- lock_get(lock); |
|
554 |
- |
|
555 |
- src = sources->head; |
|
556 |
- while (src) { |
|
557 |
- tmp.s = src->table; |
|
558 |
- tmp.len = strlen(src->table); |
|
559 |
- n = db_reload_source(&tmp, src->dtrie_root); |
|
560 |
- if (n < 0) { |
|
561 |
- LM_ERR("cannot reload source from '%.*s'\n", tmp.len, tmp.s); |
|
562 |
- result = -1; |
|
563 |
- break; |
|
564 |
- } |
|
565 |
- LM_INFO("got %d entries from '%.*s'\n", n, tmp.len, tmp.s); |
|
566 |
- src = src->next; |
|
567 |
- } |
|
568 |
- |
|
569 |
- /* critical section end */ |
|
570 |
- lock_release(lock); |
|
571 |
- |
|
572 |
- return result; |
|
573 |
-} |
|
574 |
- |
|
575 |
- |
|
576 |
-static int init_source_list(void) |
|
577 |
-{ |
|
578 |
- sources = shm_malloc(sizeof(struct source_list_t)); |
|
579 |
- if (!sources) { |
|
580 |
- SHM_MEM_ERROR; |
|
581 |
- return -1; |
|
582 |
- } |
|
583 |
- sources->head = NULL; |
|
584 |
- return 0; |
|
585 |
-} |
|
586 |
- |
|
587 |
- |
|
588 |
-static void destroy_source_list(void) |
|
589 |
-{ |
|
590 |
- if (sources) { |
|
591 |
- while (sources->head) { |
|
592 |
- struct source_t *src = sources->head; |
|
593 |
- sources->head = src->next; |
|
594 |
- |
|
595 |
- if (src->table) shm_free(src->table); |
|
596 |
- dtrie_destroy(&(src->dtrie_root), NULL, match_mode); |
|
597 |
- shm_free(src); |
|
598 |
- } |
|
599 |
- |
|
600 |
- shm_free(sources); |
|
601 |
- sources = NULL; |
|
602 |
- } |
|
603 |
-} |
|
604 |
- |
|
605 |
- |
|
606 |
-static int init_shmlock(void) |
|
607 |
-{ |
|
608 |
- lock = lock_alloc(); |
|
609 |
- if (!lock) { |
|
610 |
- LM_CRIT("cannot allocate memory for lock.\n"); |
|
611 |
- return -1; |
|
612 |
- } |
|
613 |
- if (lock_init(lock) == 0) { |
|
614 |
- LM_CRIT("cannot initialize lock.\n"); |
|
615 |
- return -1; |
|
616 |
- } |
|
617 |
- |
|
618 |
- return 0; |
|
619 |
-} |
|
620 |
- |
|
621 |
- |
|
622 |
-static void destroy_shmlock(void) |
|
623 |
-{ |
|
624 |
- if (lock) { |
|
625 |
- lock_destroy(lock); |
|
626 |
- lock_dealloc((void *)lock); |
|
627 |
- lock = NULL; |
|
628 |
- } |
|
629 |
-} |
|
630 |
- |
|
631 |
- |
|
632 |
-struct mi_root * mi_reload_blacklist(struct mi_root* cmd, void* param) |
|
633 |
-{ |
|
634 |
- struct mi_root * tmp = NULL; |
|
635 |
- if(reload_sources() == 0) { |
|
636 |
- tmp = init_mi_tree( 200, MI_OK_S, MI_OK_LEN); |
|
637 |
- } else { |
|
638 |
- tmp = init_mi_tree( 500, "cannot reload blacklist", 21); |
|
639 |
- } |
|
640 |
- |
|
641 |
- return tmp; |
|
642 |
-} |
|
643 |
- |
|
644 |
- |
|
645 |
-static int mod_init(void) |
|
646 |
-{ |
|
647 |
- if(register_mi_mod(exports.name, mi_cmds)!=0) |
|
648 |
- { |
|
649 |
- LM_ERR("failed to register MI commands\n"); |
|
650 |
- return -1; |
|
651 |
- } |
|
652 |
- |
|
653 |
- userblacklist_db_vars(); |
|
654 |
- |
|
655 |
- if (userblacklist_db_init() != 0) return -1; |
|
656 |
- if (init_shmlock() != 0) return -1; |
|
657 |
- if (init_source_list() != 0) return -1; |
|
658 |
- return 0; |
|
659 |
-} |
|
660 |
- |
|
661 |
- |
|
662 |
-static int child_init(int rank) |
|
663 |
-{ |
|
664 |
- if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN) |
|
665 |
- return 0; /* do nothing for the main process */ |
|
666 |
- |
|
667 |
- return mi_child_init(); |
|
668 |
-} |
|
669 |
- |
|
670 |
- |
|
671 |
-static int userblacklist_child_initialized = 0; |
|
672 |
- |
|
673 |
-static int mi_child_init(void) |
|
674 |
-{ |
|
675 |
- if(userblacklist_child_initialized) |
|
676 |
- return 0; |
|
677 |
- if (userblacklist_db_open() != 0) return -1; |
|
678 |
- dtrie_root=dtrie_init(match_mode); |
|
679 |
- if (dtrie_root == NULL) { |
|
680 |
- LM_ERR("could not initialize data"); |
|
681 |
- return -1; |
|
682 |
- } |
|
683 |
- /* because we've added new sources during the fixup */ |
|
684 |
- if (reload_sources() != 0) return -1; |
|
685 |
- |
|
686 |
- userblacklist_child_initialized = 1; |
|
687 |
- |
|
688 |
- return 0; |
|
689 |
-} |
|
690 |
- |
|
691 |
- |
|
692 |
-static void mod_destroy(void) |
|
693 |
-{ |
|
694 |
- destroy_source_list(); |
|
695 |
- destroy_shmlock(); |
|
696 |
- userblacklist_db_close(); |
|
697 |
- dtrie_destroy(&dtrie_root, NULL, match_mode); |
|
698 |
-} |
- safety checks to detect dynamic vs static string parameters
... | ... |
@@ -190,9 +190,9 @@ static int check_user_blacklist_fixup(void** param, int param_no) |
190 | 190 |
return E_UNSPEC; |
191 | 191 |
} |
192 | 192 |
|
193 |
- if(!model->spec.getf) { |
|
193 |
+ if(model->spec==NULL || model->spec->getf==NULL) { |
|
194 | 194 |
if(param_no == 1) { |
195 |
- if(str2int(&s, (unsigned int*)&model->spec.pvp.pvn.u.isname.name.n) != 0) { |
|
195 |
+ if(str2int(&s, (unsigned int*)&model->spec->pvp.pvn.u.isname.name.n) != 0) { |
|
196 | 196 |
LM_ERR("wrong value [%.*s] for parameter %d\n", s.len, s.s, param_no); |
197 | 197 |
return E_UNSPEC; |
198 | 198 |
} |
... | ... |
@@ -227,21 +227,21 @@ static int check_user_list(struct sip_msg *msg, char* str1, char* str2, char* st |
227 | 227 |
char req_number[MAXNUMBERLEN+1]; |
228 | 228 |
|
229 | 229 |
/* user */ |
230 |
- if(((pv_elem_p)str1)->spec.getf) { |
|
230 |
+ if(((pv_elem_p)str1)->spec!=NULL && ((pv_elem_p)str1)->spec->getf!=NULL) { |
|
231 | 231 |
if(pv_printf_s(msg, (pv_elem_p)str1, &user) != 0) { |
232 | 232 |
LM_ERR("cannot print user pseudo-variable\n"); |
233 | 233 |
return -1; |
234 | 234 |
} |
235 | 235 |
} |
236 | 236 |
/* domain */ |
237 |
- if(((pv_elem_p)str2)->spec.getf) { |
|
237 |
+ if(((pv_elem_p)str2)->spec!=NULL && ((pv_elem_p)str2)->spec->getf) { |
|
238 | 238 |
if(pv_printf_s(msg, (pv_elem_p)str2, &domain) != 0) { |
239 | 239 |
LM_ERR("cannot print domain pseudo-variable\n"); |
240 | 240 |
return -1; |
241 | 241 |
} |
242 | 242 |
} |
243 | 243 |
/* source number */ |
244 |
- if(str3 != NULL && ((pv_elem_p)str3)->spec.getf) { |
|
244 |
+ if(str3 != NULL && ((pv_elem_p)str3)->spec!=NULL && ((pv_elem_p)str3)->spec->getf!=NULL) { |
|
245 | 245 |
if(pv_printf_s(msg, (pv_elem_p)str3, &number) != 0) { |
246 | 246 |
LM_ERR("cannot print number pseudo-variable\n"); |
247 | 247 |
return -1; |
... | ... |
@@ -289,7 +289,7 @@ static int check_user_list(struct sip_msg *msg, char* str1, char* str2, char* st |
289 | 289 |
|
290 | 290 |
ptr = req_number; |
291 | 291 |
/* Skip over non-digits. */ |
292 |
- while (strlen(ptr) > 0 && !isdigit(*ptr)) { |
|
292 |
+ while (match_mode == 10 && strlen(ptr) > 0 && !isdigit(*ptr)) { |
|
293 | 293 |
ptr = ptr + 1; |
294 | 294 |
} |
295 | 295 |
|
... | ... |
@@ -73,7 +73,8 @@ struct check_blacklist_fs_t { |
73 | 73 |
}; |
74 | 74 |
|
75 | 75 |
str userblacklist_db_url = str_init(DEFAULT_RODB_URL); |
76 |
-static int use_domain = 0; |
|
76 |
+int use_domain = 0; |
|
77 |
+int match_mode = 10; /* numeric */ |
|
77 | 78 |
static struct dtrie_node_t *gnode = NULL; |
78 | 79 |
|
79 | 80 |
/* ---- fixup functions: */ |
... | ... |
@@ -122,6 +123,7 @@ static param_export_t params[] = { |
122 | 123 |
userblacklist_DB_COLS |
123 | 124 |
globalblacklist_DB_COLS |
124 | 125 |
{ "use_domain", INT_PARAM, &use_domain }, |
126 |
+ { "match_mode", INT_PARAM, &match_mode}, |
|
125 | 127 |
{ 0, 0, 0} |
126 | 128 |
}; |
127 | 129 |
|
... | ... |
@@ -291,7 +293,7 @@ static int check_user_list(struct sip_msg *msg, char* str1, char* str2, char* st |
291 | 293 |
ptr = ptr + 1; |
292 | 294 |
} |
293 | 295 |
|
294 |
- nodeflags = dtrie_longest_match(dtrie_root, ptr, strlen(ptr), NULL, 10); |
|
296 |
+ nodeflags = dtrie_longest_match(dtrie_root, ptr, strlen(ptr), NULL, match_mode); |
|
295 | 297 |
if (nodeflags) { |
296 | 298 |
if (*nodeflags == (void *)MARK_WHITELIST) { |
297 | 299 |
/* LM_ERR("whitelisted"); */ |
... | ... |
@@ -395,7 +397,7 @@ static int add_source(const char *table) |
395 | 397 |
strcpy(src->table, table); |
396 | 398 |
LM_DBG("add table %s", table); |
397 | 399 |
|
398 |
- src->dtrie_root = dtrie_init(10); |
|
400 |
+ src->dtrie_root = dtrie_init(match_mode); |
|
399 | 401 |
|
400 | 402 |
if (src->dtrie_root == NULL) { |
401 | 403 |
LM_ERR("could not initialize data"); |
... | ... |
@@ -510,15 +512,15 @@ static int check_blacklist(struct sip_msg *msg, struct check_blacklist_fs_t *arg |
510 | 512 |
|
511 | 513 |
ptr = req_number; |
512 | 514 |
/* Skip over non-digits. */ |
513 |
- while (strlen(ptr) > 0 && !isdigit(*ptr)) { |
|
514 |
- ptr = ptr + 1; |
|
515 |
+ while (match_mode == 10 && strlen(ptr) > 0 && !isdigit(*ptr)) { |
|
516 |
+ ptr = ptr + 1; |
|
515 | 517 |
} |
516 | 518 |
|
517 | 519 |
LM_DBG("check entry %s\n", req_number); |
518 | 520 |
|
519 | 521 |
/* avoids dirty reads when updating d-tree */ |
520 | 522 |
lock_get(lock); |
521 |
- nodeflags = dtrie_longest_match(arg1->dtrie_root, ptr, strlen(ptr), NULL, 10); |
|
523 |
+ nodeflags = dtrie_longest_match(arg1->dtrie_root, ptr, strlen(ptr), NULL, match_mode); |
|
522 | 524 |
if (nodeflags) { |
523 | 525 |
if (*nodeflags == (void *)MARK_WHITELIST) { |
524 | 526 |
/* LM_DBG("whitelisted"); */ |
... | ... |
@@ -591,7 +593,7 @@ static void destroy_source_list(void) |
591 | 593 |
sources->head = src->next; |
592 | 594 |
|
593 | 595 |
if (src->table) shm_free(src->table); |
594 |
- dtrie_destroy(&(src->dtrie_root), NULL, 10); |
|
596 |
+ dtrie_destroy(&(src->dtrie_root), NULL, match_mode); |
|
595 | 597 |
shm_free(src); |
596 | 598 |
} |
597 | 599 |
|
... | ... |
@@ -673,7 +675,7 @@ static int mi_child_init(void) |
673 | 675 |
if(userblacklist_child_initialized) |
674 | 676 |
return 0; |
675 | 677 |
if (userblacklist_db_open() != 0) return -1; |
676 |
- dtrie_root=dtrie_init(10); |
|
678 |
+ dtrie_root=dtrie_init(match_mode); |
|
677 | 679 |
if (dtrie_root == NULL) { |
678 | 680 |
LM_ERR("could not initialize data"); |
679 | 681 |
return -1; |
... | ... |
@@ -692,5 +694,5 @@ static void mod_destroy(void) |
692 | 694 |
destroy_source_list(); |
693 | 695 |
destroy_shmlock(); |
694 | 696 |
userblacklist_db_close(); |
695 |
- dtrie_destroy(&dtrie_root, NULL, 10); |
|
697 |
+ dtrie_destroy(&dtrie_root, NULL, match_mode); |
|
696 | 698 |
} |
- safety check for cases when xmlrpc module is used to run mi commands
... | ... |
@@ -662,21 +662,16 @@ static int child_init(int rank) |
662 | 662 |
if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN) |
663 | 663 |
return 0; /* do nothing for the main process */ |
664 | 664 |
|
665 |
- if (userblacklist_db_open() != 0) return -1; |
|
666 |
- dtrie_root=dtrie_init(10); |
|
667 |
- if (dtrie_root == NULL) { |
|
668 |
- LM_ERR("could not initialize data"); |
|
669 |
- return -1; |
|
670 |
- } |
|
671 |
- /* because we've added new sources during the fixup */ |
|
672 |
- if (reload_sources() != 0) return -1; |
|
673 |
- |
|
674 |
- return 0; |
|
665 |
+ return mi_child_init(); |
|
675 | 666 |
} |
676 | 667 |
|
677 | 668 |
|
669 |
+static int userblacklist_child_initialized = 0; |
|
670 |
+ |
|
678 | 671 |
static int mi_child_init(void) |
679 | 672 |
{ |
673 |
+ if(userblacklist_child_initialized) |
|
674 |
+ return 0; |
|
680 | 675 |
if (userblacklist_db_open() != 0) return -1; |
681 | 676 |
dtrie_root=dtrie_init(10); |
682 | 677 |
if (dtrie_root == NULL) { |
... | ... |
@@ -686,6 +681,8 @@ static int mi_child_init(void) |
686 | 681 |
/* because we've added new sources during the fixup */ |
687 | 682 |
if (reload_sources() != 0) return -1; |
688 | 683 |
|
684 |
+ userblacklist_child_initialized = 1; |
|
685 |
+ |
|
689 | 686 |
return 0; |
690 | 687 |
} |
691 | 688 |
|
Globalblacklist_table parameter was not used at all in the userblacklist module, the check_blacklist funtion always needing
one parameters and the db table. This is not mandatory anymore, as the check_blacklist function with no parameters will use
the globalblacklist_table
... | ... |
@@ -74,10 +74,12 @@ struct check_blacklist_fs_t { |
74 | 74 |
|
75 | 75 |
str userblacklist_db_url = str_init(DEFAULT_RODB_URL); |
76 | 76 |
static int use_domain = 0; |
77 |
+static struct dtrie_node_t *gnode = NULL; |
|
77 | 78 |
|
78 | 79 |
/* ---- fixup functions: */ |
79 | 80 |
static int check_blacklist_fixup(void** param, int param_no); |
80 | 81 |
static int check_user_blacklist_fixup(void** param, int param_no); |
82 |
+static int check_globalblacklist_fixup(void** param, int param_no); |
|
81 | 83 |
|
82 | 84 |
/* ---- exported commands: */ |
83 | 85 |
static int check_user_blacklist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4); |
... | ... |
@@ -87,6 +89,8 @@ static int check_user_whitelist2(struct sip_msg *msg, char* str1, char* str2); |
87 | 89 |
static int check_user_blacklist3(struct sip_msg *msg, char* str1, char* str2, char* str3); |
88 | 90 |
static int check_user_whitelist3(struct sip_msg *msg, char* str1, char* str2, char* str3); |
89 | 91 |
static int check_blacklist(struct sip_msg *msg, struct check_blacklist_fs_t *arg1); |
92 |
+static int check_globalblacklist(struct sip_msg *msg); |
|
93 |
+ |
|
90 | 94 |
|
91 | 95 |
/* ---- module init functions: */ |
92 | 96 |
static int mod_init(void); |
... | ... |
@@ -106,6 +110,7 @@ static cmd_export_t cmds[]={ |
106 | 110 |
{ "check_user_blacklist", (cmd_function)check_user_blacklist, 4, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE }, |
107 | 111 |
{ "check_user_whitelist", (cmd_function)check_user_whitelist, 4, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE }, |
108 | 112 |
{ "check_blacklist", (cmd_function)check_blacklist, 1, check_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE }, |
113 |
+ { "check_blacklist", (cmd_function)check_globalblacklist, 0, check_globalblacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE }, |
|
109 | 114 |
{ 0, 0, 0, 0, 0, 0} |
110 | 115 |
}; |
111 | 116 |
|
... | ... |
@@ -401,6 +406,48 @@ static int add_source(const char *table) |
401 | 406 |
} |
402 | 407 |
|
403 | 408 |
|
409 |
+static int check_globalblacklist_fixup(void** param, int param_no) |
|
410 |
+{ |
|
411 |
+ char * table = globalblacklist_table.s; |
|
412 |
+ if(param_no > 0){ |
|
413 |
+ LM_ERR("Wrong number of parameters\n"); |
|
414 |
+ return -1; |
|
415 |
+ } |
|
416 |
+ |
|
417 |
+ if (!table) { |
|