1 /*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * William King <william.king@quentustech.com>
27 *
28 * mod_xml_radius.c -- Radius authentication and authorization
29 *
30 */
31 #include <switch.h>
32 #include <freeradius-client.h>
33
34 static struct {
35 switch_memory_pool_t *pool;
36 switch_xml_t auth_invite_configs;
37 switch_xml_t auth_reg_configs;
38 switch_xml_t auth_app_configs;
39 switch_xml_t acct_start_configs;
40 switch_xml_t acct_end_configs;
41 /* xml read write lock */
42 } globals = {0};
43
44 SWITCH_MODULE_LOAD_FUNCTION(mod_xml_radius_load);
45 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_radius_shutdown);
46 SWITCH_MODULE_DEFINITION(mod_xml_radius, mod_xml_radius_load, mod_xml_radius_shutdown, NULL);
47
48 int GLOBAL_DEBUG = 0;
49 /*
50 * Time format 0:
51 * 20:16:33.479 UTC Thu May 02 2013
52 *
53 * Time format 1:
54 * 2013-05-03T00:53:26.139798+0400
55 *
56 */
57 int GLOBAL_TIME_FORMAT = 0;
58 char *GLOBAL_TIME_ZONE = "UTC";
59 static char radattrdays[7][4] = {
60 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
61 };
62 static char radattrmonths[12][4] = {
63 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
64 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
65 };
66
mod_xml_radius_new_handle(rc_handle ** new_handle,switch_xml_t xml)67 switch_status_t mod_xml_radius_new_handle(rc_handle **new_handle, switch_xml_t xml) {
68 switch_xml_t server, param;
69
70 if ( (*new_handle = rc_new()) == NULL ) {
71 goto err;
72 }
73
74 if ( rc_config_init(*new_handle) == NULL ) {
75 *new_handle = NULL;
76 goto err;
77 }
78
79 if (rc_add_config(*new_handle, "auth_order", "radius", "mod_radius_cdr.c", 0) != 0) {
80 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error adding auth_order\n");
81 goto err;
82 }
83
84 if ((server = switch_xml_child(xml, "connection")) == NULL ) {
85 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'connection' section in config file.\n");
86 goto err;
87 }
88
89 for (param = switch_xml_child(server, "param"); param; param = param->next) {
90 char *var = (char *) switch_xml_attr_soft(param, "name");
91 char *val = (char *) switch_xml_attr_soft(param, "value");
92
93 if ( GLOBAL_DEBUG ) {
94 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Attempting to add param '%s' with value '%s' \n", var, val);
95 }
96
97 if (strncmp(var, "dictionary", 10) == 0) {
98 if ( rc_read_dictionary(*new_handle, val) != 0) {
99 goto err;
100 }
101 } else if (rc_add_config(*new_handle, var, val, "mod_xml_radius", 0) != 0) {
102 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error adding param '%s' with value '%s' \n", var, val);
103 goto err;
104 }
105 }
106
107 return SWITCH_STATUS_SUCCESS;
108
109 err:
110 if ( *new_handle ) {
111 rc_destroy( *new_handle );
112 *new_handle = NULL;
113 }
114 return SWITCH_STATUS_GENERR;
115 }
116
do_config()117 switch_status_t do_config()
118 {
119 char *conf = "xml_radius.conf";
120 switch_xml_t xml, cfg, tmp, server, param;
121 int serv, timeout, deadtime, retries, dict, seq;
122
123 /* TODO:
124 1. Fix read/write lock on configs
125 a. read new configs
126 b. Create replacement xml and vas objects
127 c. Get the write lock.
128 d. Replace xml and vas objects
129 e. unlock and return.
130 2. Don't manually check for proper configs. Use the function in the client library
131 3. Add api that would reload configs
132 */
133
134 if (!(xml = switch_xml_open_cfg(conf, &cfg, NULL))) {
135 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", conf);
136 goto err;
137 }
138
139 serv = timeout = deadtime = retries = dict = seq = 0;
140 if ((tmp = switch_xml_dup(switch_xml_child(cfg, "auth_invite"))) != NULL ) {
141 if ( (server = switch_xml_child(tmp, "connection")) != NULL) {
142 for (param = switch_xml_child(server, "param"); param; param = param->next) {
143 char *var = (char *) switch_xml_attr_soft(param, "name");
144 if ( strncmp(var, "authserver", 10) == 0 ) {
145 serv = 1;
146 } else if ( strncmp(var, "radius_timeout", 14) == 0 ) {
147 timeout = 1;
148 } else if ( strncmp(var, "radius_deadtime", 15) == 0 ) {
149 deadtime = 1;
150 } else if ( strncmp(var, "radius_retries", 14) == 0 ) {
151 retries = 1;
152 } else if ( strncmp(var, "dictionary", 10) == 0 ) {
153 dict = 1;
154 } else if ( strncmp(var, "seqfile", 7) == 0 ) {
155 seq = 1;
156 }
157 }
158
159 if ( serv && timeout && deadtime && retries && dict && seq ) {
160 globals.auth_invite_configs = tmp;
161 } else {
162 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing a require section for radius connections\n");
163 goto err;
164 }
165 } else {
166 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'connection' section for auth_invite\n");
167 goto err;
168 }
169 } else {
170 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Could not find 'auth_invite' section in config file.\n");
171 }
172
173 serv = timeout = deadtime = retries = dict = seq = 0;
174 if ((tmp = switch_xml_dup(switch_xml_child(cfg, "auth_reg"))) != NULL ) {
175 if ( (server = switch_xml_child(tmp, "connection")) != NULL) {
176 for (param = switch_xml_child(server, "param"); param; param = param->next) {
177 char *var = (char *) switch_xml_attr_soft(param, "name");
178 if ( strncmp(var, "authserver", 10) == 0 ) {
179 serv = 1;
180 } else if ( strncmp(var, "radius_timeout", 14) == 0 ) {
181 timeout = 1;
182 } else if ( strncmp(var, "radius_deadtime", 15) == 0 ) {
183 deadtime = 1;
184 } else if ( strncmp(var, "radius_retries", 14) == 0 ) {
185 retries = 1;
186 } else if ( strncmp(var, "dictionary", 10) == 0 ) {
187 dict = 1;
188 } else if ( strncmp(var, "seqfile", 7) == 0 ) {
189 seq = 1;
190 }
191 }
192
193 if ( serv && timeout && deadtime && retries && dict && seq ) {
194 globals.auth_reg_configs = tmp;
195 } else {
196 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing a require section for radius connections\n");
197 goto err;
198 }
199 } else {
200 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'connection' section for auth_invite\n");
201 goto err;
202 }
203 } else {
204 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Could not find 'auth_reg' section in config file.\n");
205 }
206
207 if ((tmp = switch_xml_child(cfg, "global")) != NULL ) {
208 for (param = switch_xml_child(tmp, "param"); param; param = param->next) {
209 char *name = (char *) switch_xml_attr_soft(param, "name");
210 char *value = (char *) switch_xml_attr_soft(param, "value");
211 if ( strncmp(name, "time_format", 11) == 0 && value != NULL ) {
212 GLOBAL_TIME_FORMAT = atoi(value);
213 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Time format changed to %d\n", GLOBAL_TIME_FORMAT);
214 }
215 if ( strncmp(name, "time_zone", 9) == 0 && value != NULL ) {
216 GLOBAL_TIME_ZONE = value;
217 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Time zone changed to %s\n", GLOBAL_TIME_ZONE);
218 }
219 if ( strncmp(name, "debug", 5) == 0 && value != NULL ) {
220 GLOBAL_DEBUG = atoi(value);
221 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Debug changed to %d\n", GLOBAL_DEBUG);
222 }
223 }
224 }
225
226 serv = timeout = deadtime = retries = dict = seq = 0;
227 if ((tmp = switch_xml_dup(switch_xml_child(cfg, "auth_app"))) != NULL ) {
228 if ( (server = switch_xml_child(tmp, "connection")) != NULL) {
229 for (param = switch_xml_child(server, "param"); param; param = param->next) {
230 char *var = (char *) switch_xml_attr_soft(param, "name");
231 if ( strncmp(var, "authserver", 10) == 0 ) {
232 serv = 1;
233 } else if ( strncmp(var, "radius_timeout", 14) == 0 ) {
234 timeout = 1;
235 } else if ( strncmp(var, "radius_deadtime", 15) == 0 ) {
236 deadtime = 1;
237 } else if ( strncmp(var, "radius_retries", 14) == 0 ) {
238 retries = 1;
239 } else if ( strncmp(var, "dictionary", 10) == 0 ) {
240 dict = 1;
241 } else if ( strncmp(var, "seqfile", 7) == 0 ) {
242 seq = 1;
243 }
244 }
245
246 if ( serv && timeout && deadtime && retries && dict && seq ) {
247 globals.auth_app_configs = tmp;
248 } else {
249 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing a require section for radius connections\n");
250 goto err;
251 }
252 } else {
253 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'connection' section for auth_app\n");
254 goto err;
255 }
256 } else {
257 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Could not find 'auth_app' section in config file.\n");
258 }
259
260 serv = timeout = deadtime = retries = dict = seq = 0;
261 if (( tmp = switch_xml_dup(switch_xml_child(cfg, "acct_start"))) != NULL ) {
262 if ( (server = switch_xml_child(tmp, "connection")) != NULL) {
263 for (param = switch_xml_child(server, "param"); param; param = param->next) {
264 char *var = (char *) switch_xml_attr_soft(param, "name");
265 if ( strncmp(var, "acctserver", 10) == 0 ) {
266 serv = 1;
267 } else if ( strncmp(var, "radius_timeout", 14) == 0 ) {
268 timeout = 1;
269 } else if ( strncmp(var, "radius_deadtime", 15) == 0 ) {
270 deadtime = 1;
271 } else if ( strncmp(var, "radius_retries", 14) == 0 ) {
272 retries = 1;
273 } else if ( strncmp(var, "dictionary", 10) == 0 ) {
274 dict = 1;
275 } else if ( strncmp(var, "seqfile", 7) == 0 ) {
276 seq = 1;
277 }
278 }
279
280 if ( serv && timeout && deadtime && retries && dict && seq ) {
281 globals.acct_start_configs = tmp;
282 } else {
283 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing a require section for radius connections\n");
284 goto err;
285 }
286 } else {
287 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'connection' section for acct_start\n");
288 goto err;
289 }
290 } else {
291 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Could not find 'acct_start' section in config file.\n");
292 }
293
294 serv = timeout = deadtime = retries = dict = seq = 0;
295 if (( tmp = switch_xml_dup(switch_xml_child(cfg, "acct_end"))) != NULL ) {
296 if ( (server = switch_xml_child(tmp, "connection")) != NULL) {
297 for (param = switch_xml_child(server, "param"); param; param = param->next) {
298 char *var = (char *) switch_xml_attr_soft(param, "name");
299 if ( strncmp(var, "acctserver", 10) == 0 ) {
300 serv = 1;
301 } else if ( strncmp(var, "radius_timeout", 14) == 0 ) {
302 timeout = 1;
303 } else if ( strncmp(var, "radius_deadtime", 15) == 0 ) {
304 deadtime = 1;
305 } else if ( strncmp(var, "radius_retries", 14) == 0 ) {
306 retries = 1;
307 } else if ( strncmp(var, "dictionary", 10) == 0 ) {
308 dict = 1;
309 } else if ( strncmp(var, "seqfile", 7) == 0 ) {
310 seq = 1;
311 }
312 }
313
314 if ( serv && timeout && deadtime && retries && dict && seq ) {
315 globals.acct_end_configs = tmp;
316 } else {
317 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing a require section for radius connections\n");
318 goto err;
319 }
320 } else {
321 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'connection' section for acct_end\n");
322 goto err;
323 }
324 } else {
325 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Could not find 'acct_end' section in config file.\n");
326 }
327
328 if ( xml ) {
329 switch_xml_free(xml);
330 xml = NULL;
331 }
332
333 return SWITCH_STATUS_SUCCESS;
334
335 err:
336 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Configuration error\n");
337 if ( xml ) {
338 switch_xml_free(xml);
339 xml = NULL;
340 }
341
342 return SWITCH_STATUS_GENERR;
343 }
344
mod_xml_radius_add_params(switch_core_session_t * session,switch_event_t * params,rc_handle * handle,VALUE_PAIR ** send,switch_xml_t fields)345 switch_status_t mod_xml_radius_add_params(switch_core_session_t *session, switch_event_t *params, rc_handle *handle, VALUE_PAIR **send, switch_xml_t fields)
346 {
347 switch_xml_t param;
348 void *av_value = NULL;
349
350 if ( (param = switch_xml_child(fields, "param")) == NULL) {
351 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to locate a param under the fields section\n");
352 goto err;
353 }
354
355 for (; param; param = param->next) {
356 DICT_ATTR *attribute = NULL;
357 DICT_VENDOR *vendor = NULL;
358 int attr_num = 0, vend_num = 0;
359
360 char *var = (char *) switch_xml_attr(param, "name");
361 char *vend = (char *) switch_xml_attr(param, "vendor");
362 char *variable = (char *) switch_xml_attr(param, "variable");
363 char *variable_secondary = (char *) switch_xml_attr(param, "variable_secondary");
364 char *val_default = (char *) switch_xml_attr(param, "default");
365 char *skip_if_set = (char *) switch_xml_attr(param, "skip_if_set");
366 char *format = (char *) switch_xml_attr(param, "format");
367 char *other_leg = (char *) switch_xml_attr(param, "other_leg");
368 char *regex = (char *) switch_xml_attr(param, "regex");
369
370 attribute = rc_dict_findattr(handle, var);
371
372 if ( attribute == NULL ) {
373 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Could not locate attribute '%s' in the configured dictionary\n", var);
374 goto err;
375 }
376
377 if ( GLOBAL_DEBUG ) {
378 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: dict attr '%s' value '%d' type '%d'\n",
379 attribute->name, attribute->value, attribute->type);
380 }
381
382 attr_num = attribute->value;
383
384 if ( vend ) {
385 vendor = rc_dict_findvend(handle, vend);
386
387 if ( vendor == NULL ) {
388 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Could not locate vendor '%s' in the configured dictionary %p\n",
389 vend, vend);
390 goto err;
391 }
392
393 if ( GLOBAL_DEBUG ) {
394 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: dict vend name '%s' vendorpec '%d'\n",
395 vendor->vendorname, vendor->vendorpec);
396 }
397
398 vend_num = vendor->vendorpec;
399 }
400
401 if ( var ) {
402 if ( session ) {
403 switch_channel_t *channel = switch_core_session_get_channel(session);
404 if ( skip_if_set && switch_channel_get_variable(channel, skip_if_set) ) {
405 goto end_loop;
406 }
407
408 /* Accounting only */
409 if ( strncmp( var, "h323-setup-time", 15) == 0 ) {
410 switch_caller_profile_t *profile = switch_channel_get_caller_profile(channel);
411 switch_time_t time = profile->times->created;
412 switch_time_exp_t tm;
413
414 if ( !time ) {
415 goto end_loop;
416 }
417
418 switch_time_exp_lt(&tm, time);
419
420 if ( GLOBAL_TIME_FORMAT == 1 ) {
421 av_value = switch_mprintf("%02u:%02u:%02u.%03u %s %s %s %02u %04u",
422 tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec/1000,
423 GLOBAL_TIME_ZONE, radattrdays[tm.tm_wday], radattrmonths[tm.tm_mon],
424 tm.tm_mday, tm.tm_year + 1900);
425 } else {
426 av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
427 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
428 tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec,
429 tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
430 }
431
432 if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) {
433 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
434 goto err;
435 }
436 if ( GLOBAL_DEBUG ) {
437 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: value: %s\n", (char *) av_value);
438 }
439 } else if ( strncmp( var, "h323-connect-time", 17) == 0 ) {
440 switch_caller_profile_t *profile = switch_channel_get_caller_profile(channel);
441 switch_time_t time = profile->times->answered;
442 switch_time_exp_t tm;
443
444 if ( !time ) {
445 goto end_loop;
446 }
447
448 switch_time_exp_lt(&tm, time);
449
450 if ( GLOBAL_TIME_FORMAT == 1 ) {
451 av_value = switch_mprintf("%02u:%02u:%02u.%03u %s %s %s %02u %04u",
452 tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec/1000,
453 GLOBAL_TIME_ZONE, radattrdays[tm.tm_wday], radattrmonths[tm.tm_mon],
454 tm.tm_mday, tm.tm_year + 1900);
455 } else {
456 av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
457 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
458 tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec,
459 tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
460 }
461
462 if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) {
463 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
464 goto err;
465 }
466 if ( GLOBAL_DEBUG ) {
467 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: value: %s\n", (char *) av_value);
468 }
469 } else if ( strncmp( var, "h323-disconnect-time", 20) == 0 ) {
470 switch_caller_profile_t *profile = switch_channel_get_caller_profile(channel);
471 switch_time_t time = profile->times->hungup;
472 switch_time_exp_t tm;
473
474 if ( !time ) {
475 if ( variable_secondary != NULL && strncmp(variable_secondary, "now", 3) == 0 ) {
476 time = switch_time_now();
477 } else {
478 goto end_loop;
479 }
480 }
481
482 switch_time_exp_lt(&tm, time);
483
484 if ( GLOBAL_TIME_FORMAT == 1 ) {
485 av_value = switch_mprintf("%02u:%02u:%02u.%03u %s %s %s %02u %04u",
486 tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec/1000,
487 GLOBAL_TIME_ZONE, radattrdays[tm.tm_wday], radattrmonths[tm.tm_mon],
488 tm.tm_mday, tm.tm_year + 1900);
489 } else {
490 av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
491 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
492 tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec,
493 tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
494 }
495
496 if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) {
497 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
498 goto err;
499 }
500 if ( GLOBAL_DEBUG ) {
501 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: value: %s\n", (char *) av_value);
502 }
503 } else if ( strncmp( var, "h323-disconnect-cause", 21) == 0 ) {
504 switch_call_cause_t cause = switch_channel_get_cause(channel);
505 av_value = switch_mprintf("h323-disconnect-cause=%x", cause);
506 if (rc_avpair_add(handle, send, 30, av_value, -1, 9) == NULL) {
507 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add disconnect cause \n");
508 goto err;
509 }
510
511 } else {
512 if ( format == NULL ) {
513 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing format attribute for %s variable\n", variable);
514 goto err;
515 }
516
517 if ( attribute->type == 0 ) {
518 const char *val = NULL;
519
520 if ( other_leg ) {
521 val = switch_channel_get_variable_partner(channel, variable);
522 if ( val == NULL && variable_secondary != NULL) {
523 val = switch_channel_get_variable_partner(channel, variable_secondary);
524 }
525 } else {
526 val = switch_channel_get_variable(channel, variable);
527 if ( val == NULL && variable_secondary != NULL) {
528 val = switch_channel_get_variable(channel, variable_secondary);
529 }
530 }
531
532 if ( regex && val ) {
533 switch_regex_t *re = NULL;
534 int ovector[30];
535 int proceed;
536 char replace[1024] = "";
537 proceed = 0;
538 proceed = switch_regex_perform(val, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0]));
539 if ( proceed > 0 ) {
540 switch_regex_copy_substring(val, ovector, proceed, proceed - 1, replace, sizeof(replace));
541 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "original value: %s, regex: %s, result: %s\n", val, regex, replace);
542 val = replace;
543 }
544 else {
545 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "original value: %s, regex: %s, result: nomatch, value left intact\n", val, regex);
546 }
547 switch_regex_safe_free(re);
548 }
549
550 if ( val == NULL && val_default != NULL) {
551 av_value = switch_mprintf(format, val_default);
552 } else {
553 av_value = switch_mprintf(format, val);
554 }
555
556 if ( GLOBAL_DEBUG ) {
557 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: value: %s\n", (char *) av_value);
558 }
559
560 if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) {
561 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
562 "mod_xml_radius: failed to add option with val '%s' to handle\n", (char *) av_value);
563 goto err;
564 }
565 } else if ( attribute->type == 1 ) {
566 const char *data = switch_channel_get_variable(channel, variable);
567 int number = 0;
568
569 if ( data ) {
570 number = atoi(data);
571 }
572
573 if (rc_avpair_add(handle, send, attr_num, &number, -1, vend_num) == NULL) {
574 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
575 "mod_xml_radius: failed to add option with value '%d' to handle\n", number);
576 goto err;
577 }
578 }
579 }
580 } else if ( params ) {
581 /* Auth only */
582 char *tmp = switch_event_get_header(params, variable);
583
584 if ( GLOBAL_DEBUG ) {
585 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: param var '%s' val: %s\n", variable, tmp);
586 }
587
588 if ( tmp == NULL ) {
589 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Unable to locate '%s' on the event\n", variable);
590 goto err;
591 }
592
593 av_value = switch_mprintf(format, tmp);
594 if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) {
595 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
596 goto err;
597 }
598 } else {
599 goto err;
600 }
601 } else {
602 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: all params must have a name attribute\n");
603 goto err;
604 }
605
606 end_loop:
607 if ( av_value != NULL ) {
608 free(av_value);
609 av_value = NULL;
610 }
611 }
612
613 return SWITCH_STATUS_SUCCESS;
614 err:
615 if ( av_value != NULL ) {
616 free(av_value);
617 av_value = NULL;
618 }
619 return SWITCH_STATUS_GENERR;
620
621 }
622
623 /* static switch_status_t name (_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream) */
SWITCH_STANDARD_API(mod_xml_radius_debug_api)624 SWITCH_STANDARD_API(mod_xml_radius_debug_api)
625 {
626 if ( !strncmp(cmd, "on", 2) ) {
627 GLOBAL_DEBUG = 1;
628 } else if ( !strncmp(cmd, "off", 3)){
629 GLOBAL_DEBUG = 0;
630 } else {
631 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Valid options are [yes|no]\n" );
632 }
633
634 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "debug is %s\n", (GLOBAL_DEBUG ? "on" : "off") );
635 return SWITCH_STATUS_SUCCESS;
636 }
637
mod_xml_radius_auth_invite(switch_event_t * params)638 switch_xml_t mod_xml_radius_auth_invite(switch_event_t *params) {
639 int result = 0, param_idx = 0;
640 VALUE_PAIR *send = NULL, *recv = NULL, *service_vp = NULL;
641 char msg[512 * 10 + 1] = {0};
642 uint32_t service = PW_AUTHENTICATE_ONLY;
643 rc_handle *new_handle = NULL;
644 switch_xml_t fields, xml, dir, dom, usr, vars, var;
645 char name[512], value[512], *strtmp;
646
647 if (GLOBAL_DEBUG ) {
648 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting invite authentication\n");
649 }
650
651 if ( mod_xml_radius_new_handle(&new_handle, globals.auth_invite_configs) != SWITCH_STATUS_SUCCESS ) {
652 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load radius handle for digest invite authentication\n");
653 goto err;
654 }
655
656 if ( new_handle == NULL ) {
657 goto err;
658 }
659
660 if ((fields = switch_xml_child(globals.auth_invite_configs, "fields")) == NULL ) {
661 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'fields' section in config file.\n");
662 goto err;
663 }
664
665 if ( mod_xml_radius_add_params(NULL, params, new_handle, &send, fields) != SWITCH_STATUS_SUCCESS ) {
666 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to add params to rc_handle\n");
667 goto err;
668 }
669
670 if (rc_avpair_add(new_handle, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL) {
671 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
672 goto err;
673 }
674
675 result = rc_auth(new_handle, 0, send, &recv, msg);
676
677 if ( GLOBAL_DEBUG ){
678 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: result(RC=%d) %s \n", result, msg);
679 }
680
681 if ( result != 0 ) {
682 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Failed to authenticate\n");
683 goto err;
684 }
685
686 xml = switch_xml_new("document");
687 switch_xml_set_attr_d(xml, "type", "freeswitch/xml");
688 dir = switch_xml_add_child_d(xml, "section", 0);
689 switch_xml_set_attr_d(dir, "name", "directory");
690 dom = switch_xml_add_child_d(dir, "domain", 0);
691 switch_xml_set_attr_d(dom, "name", switch_event_get_header(params, "domain"));
692 usr = switch_xml_add_child_d(dom, "user", 0);
693 vars = switch_xml_add_child_d(usr, "variables", 0);
694
695 switch_xml_set_attr_d(usr, "id", switch_event_get_header(params, "user"));
696
697 var = switch_xml_add_child_d(vars, "variable", param_idx++);
698 switch_xml_set_attr_d(var, "name", "radius_auth_result");
699 switch_xml_set_attr_d(var, "value", "0");
700
701 service_vp = recv;
702 while (service_vp != NULL) {
703 rc_avpair_tostr(new_handle, service_vp, name, 512, value, 512);
704 if ( GLOBAL_DEBUG )
705 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "\tattribute (%s)[%s] found in radius packet\n", name, value);
706 var = switch_xml_add_child_d(vars, "variable", param_idx++);
707 strtmp = strdup(name);
708 switch_xml_set_attr_d(var, "name", strtmp);
709 free(strtmp);
710 strtmp = strdup(value);
711 switch_xml_set_attr_d(var, "value", strtmp);
712 free(strtmp);
713 service_vp = service_vp->next;
714 }
715
716 if ( GLOBAL_DEBUG ) {
717 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "XML: %s \n", switch_xml_toxml(xml, 1));
718 }
719
720 if ( recv ) {
721 rc_avpair_free(recv);
722 recv = NULL;
723 }
724 if ( send ) {
725 rc_avpair_free(send);
726 send = NULL;
727 }
728 if ( new_handle ) {
729 rc_destroy(new_handle);
730 new_handle = NULL;
731 }
732 return xml;
733 err:
734 if ( recv ) {
735 rc_avpair_free(recv);
736 recv = NULL;
737 }
738 if ( send ) {
739 rc_avpair_free(send);
740 send = NULL;
741 }
742 if ( new_handle ) {
743 rc_destroy(new_handle);
744 new_handle = NULL;
745 }
746
747 return NULL;
748 }
749
mod_xml_radius_auth_reg(switch_event_t * params)750 switch_xml_t mod_xml_radius_auth_reg(switch_event_t *params) {
751 int result = 0, param_idx = 0;
752 VALUE_PAIR *send = NULL, *recv = NULL, *service_vp = NULL;
753 char msg[512 * 10 + 1] = {0};
754 uint32_t service = PW_AUTHENTICATE_ONLY;
755 rc_handle *new_handle = NULL;
756 switch_xml_t fields, xml, dir, dom, usr, vars, var;
757 char name[512], value[512], *strtmp;
758
759 if (GLOBAL_DEBUG ) {
760 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting registration authentication\n");
761 }
762
763 if ( mod_xml_radius_new_handle(&new_handle, globals.auth_reg_configs) != SWITCH_STATUS_SUCCESS ) {
764 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load radius handle for registration authentication\n");
765 goto err;
766 }
767
768 if ( new_handle == NULL ) {
769 goto err;
770 }
771
772 if ((fields = switch_xml_child(globals.auth_reg_configs, "fields")) == NULL ) {
773 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'fields' section in config file.\n");
774 goto err;
775 }
776
777 if ( mod_xml_radius_add_params(NULL, params, new_handle, &send, fields) != SWITCH_STATUS_SUCCESS ) {
778 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to add params to rc_handle\n");
779 goto err;
780 }
781
782 if (rc_avpair_add(new_handle, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL) {
783 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
784 goto err;
785 }
786
787 result = rc_auth(new_handle, 0, send, &recv, msg);
788
789 if ( GLOBAL_DEBUG ){
790 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: result(RC=%d) %s \n", result, msg);
791 }
792
793 if ( result != 0 ) {
794 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Failed to authenticate\n");
795 goto err;
796 }
797
798 xml = switch_xml_new("document");
799 switch_xml_set_attr_d(xml, "type", "freeswitch/xml");
800 dir = switch_xml_add_child_d(xml, "section", 0);
801 switch_xml_set_attr_d(dir, "name", "directory");
802 dom = switch_xml_add_child_d(dir, "domain", 0);
803 switch_xml_set_attr_d(dom, "name", switch_event_get_header(params, "domain"));
804 usr = switch_xml_add_child_d(dom, "user", 0);
805 vars = switch_xml_add_child_d(usr, "variables", 0);
806
807 switch_xml_set_attr_d(usr, "id", switch_event_get_header(params, "user"));
808
809 service_vp = recv;
810 while (service_vp != NULL) {
811 rc_avpair_tostr(new_handle, service_vp, name, 512, value, 512);
812 if ( GLOBAL_DEBUG )
813 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "\tattribute (%s)[%s] found in radius packet\n", name, value);
814 var = switch_xml_add_child_d(vars, "variable", param_idx++);
815 strtmp = strdup(name);
816 switch_xml_set_attr_d(var, "name", strtmp);
817 free(strtmp);
818 strtmp = strdup(value);
819 switch_xml_set_attr_d(var, "value", strtmp);
820 free(strtmp);
821 service_vp = service_vp->next;
822 }
823
824 if ( GLOBAL_DEBUG ) {
825 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "XML: %s \n", switch_xml_toxml(xml, 1));
826 }
827
828 if ( recv ) {
829 rc_avpair_free(recv);
830 recv = NULL;
831 }
832 if ( send ) {
833 rc_avpair_free(send);
834 send = NULL;
835 }
836 if ( new_handle ) {
837 rc_destroy(new_handle);
838 new_handle = NULL;
839 }
840
841 return xml;
842 err:
843 if ( recv ) {
844 rc_avpair_free(recv);
845 recv = NULL;
846 }
847 if ( send ) {
848 rc_avpair_free(send);
849 send = NULL;
850 }
851 if ( new_handle ) {
852 rc_destroy(new_handle);
853 new_handle = NULL;
854 }
855
856 return NULL;
857 }
858
mod_xml_radius_directory_search(const char * section,const char * tag_name,const char * key_name,const char * key_value,switch_event_t * params,void * user_data)859 static switch_xml_t mod_xml_radius_directory_search(const char *section, const char *tag_name, const char *key_name, const char *key_value,
860 switch_event_t *params, void *user_data)
861 {
862 char *event_buf = NULL;
863 switch_xml_t xml = NULL;
864 char *auth_method = switch_event_get_header(params,"sip_auth_method");
865
866
867 if ( GLOBAL_DEBUG ) {
868 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting authentication\n");
869 switch_event_serialize(params, &event_buf, SWITCH_TRUE);
870 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Event: %s \n", event_buf);
871 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "\nSection: %s \nTag: %s\nKey_name: %s\nKey_value: %s\n",
872 section, tag_name, key_name, key_value);
873 }
874
875 if ( auth_method == NULL) {
876 return NULL;
877 }
878
879 if ( strncmp( "INVITE", auth_method, 6) == 0) {
880 xml = mod_xml_radius_auth_invite(params);
881 } else if ( strncmp( "REGISTER", auth_method, 8) == 0) {
882 xml = mod_xml_radius_auth_reg(params);
883 } else {
884 xml = NULL;
885 }
886
887 return xml;
888 }
889
mod_xml_radius_check_conditions(switch_channel_t * channel,switch_xml_t conditions)890 switch_status_t mod_xml_radius_check_conditions(switch_channel_t *channel, switch_xml_t conditions) {
891 switch_xml_t condition, param;
892 char *channel_var = NULL;
893 const char *channel_val = NULL;
894 char *regex = NULL;
895 char *anti = NULL;
896 int all_matched = 1;
897 int result = 0;
898
899 if ( (condition = switch_xml_child(conditions, "condition")) == NULL) {
900 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to locate a condition under the conditions section\n");
901 return SWITCH_STATUS_FALSE;
902 }
903
904 for (; condition; condition = condition->next) {
905
906 if ( (param = switch_xml_child(condition, "param")) == NULL) {
907 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to locate a param under this condition\n");
908 return SWITCH_STATUS_FALSE;
909 }
910
911 all_matched = 1;
912 for (; param && all_matched; param = param->next) {
913 channel_var = (char *) switch_xml_attr(param, "var");
914 regex = (char *) switch_xml_attr(param, "regex");
915 anti = (char *) switch_xml_attr(param, "anti");
916
917 if ( channel_var == NULL || regex == NULL ) {
918 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Improperly constructed mod_radius condition: %s %s\n", channel_var, regex);
919 continue;
920 }
921
922 if ( ( channel_val = switch_channel_get_variable(channel, channel_var) ) == NULL ) {
923 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
924 "Improperly constructed mod_radius condition, no such channel variable: %s %s\n", channel_var, regex);
925 continue;
926 }
927
928 result = ( switch_regex_match( channel_val, regex) != SWITCH_STATUS_SUCCESS);
929 if (( anti == NULL && result ) || ( anti != NULL && !result ) ){
930 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Didn't match: %s == %s \n", switch_channel_get_variable(channel, channel_var), regex);
931 all_matched = 0;
932 } else {
933 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Result of %s match: %s == %s \n",
934 anti, switch_channel_get_variable(channel, channel_var), regex);
935 }
936 }
937
938 if ( all_matched ) {
939 return SWITCH_STATUS_SUCCESS;
940 }
941 }
942
943 return SWITCH_STATUS_FALSE;
944 }
945
mod_xml_radius_accounting_start(switch_core_session_t * session)946 switch_status_t mod_xml_radius_accounting_start(switch_core_session_t *session){
947 VALUE_PAIR *send = NULL;
948 uint32_t service = PW_STATUS_START;
949 rc_handle *new_handle = NULL;
950 switch_xml_t fields, conditions;
951 switch_channel_t *channel = switch_core_session_get_channel(session);
952
953 if (GLOBAL_DEBUG ) {
954 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting accounting start\n");
955 switch_core_session_execute_application(session, "info", NULL);
956 }
957
958 /* If there are conditions defined, and none of them pass, then skip this accounting */
959 if ((conditions = switch_xml_child(globals.acct_start_configs, "conditions")) != NULL &&
960 mod_xml_radius_check_conditions(channel, conditions) != SWITCH_STATUS_SUCCESS ) {
961 goto end;
962 }
963
964 if ( mod_xml_radius_new_handle(&new_handle, globals.acct_start_configs) != SWITCH_STATUS_SUCCESS || new_handle == NULL ) {
965 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new accounting_start handle for call: %s\n",
966 switch_channel_get_variable(channel, "uuid"));
967 goto end;
968 }
969
970 if ((fields = switch_xml_child(globals.acct_start_configs, "fields")) == NULL ) {
971 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'fields' section in config file.\n");
972 goto end;
973 }
974
975 if ( mod_xml_radius_add_params(session, NULL, new_handle, &send, fields) != SWITCH_STATUS_SUCCESS ) {
976 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to add params to rc_handle\n");
977 goto end;
978 }
979
980 if (rc_avpair_add(new_handle, &send, PW_ACCT_STATUS_TYPE, &service, -1, 0) == NULL) {
981 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
982 goto end;
983 }
984
985 if (rc_acct(new_handle, 0, send) == OK_RC) {
986 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "mod_xml_radius: Accounting Start success\n");
987 } else {
988 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Accounting Start failed\n");
989 }
990
991 end:
992 if ( send ) {
993 rc_avpair_free(send);
994 send = NULL;
995 }
996 if ( new_handle ) {
997 rc_destroy(new_handle);
998 new_handle = NULL;
999 }
1000
1001 return SWITCH_STATUS_SUCCESS;
1002 }
1003
mod_xml_radius_accounting_end(switch_core_session_t * session)1004 switch_status_t mod_xml_radius_accounting_end(switch_core_session_t *session){
1005 VALUE_PAIR *send = NULL;
1006 uint32_t service = PW_STATUS_STOP;
1007 rc_handle *new_handle = NULL;
1008 switch_xml_t fields = NULL, conditions = NULL;
1009 switch_channel_t *channel = switch_core_session_get_channel(session);
1010
1011 if (GLOBAL_DEBUG ) {
1012 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting accounting stop\n");
1013 switch_core_session_execute_application(session, "info", NULL);
1014 }
1015
1016 /* If there are conditions defined, and none of them pass, then skip this accounting */
1017 if ((conditions = switch_xml_child(globals.acct_end_configs, "conditions")) != NULL &&
1018 mod_xml_radius_check_conditions(channel, conditions) != SWITCH_STATUS_SUCCESS ) {
1019 goto end;
1020 }
1021
1022 if ( mod_xml_radius_new_handle(&new_handle, globals.acct_end_configs) != SWITCH_STATUS_SUCCESS || new_handle == NULL ) {
1023 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new accounting_end handle for call: %s\n",
1024 switch_channel_get_variable(channel, "uuid"));
1025 goto end;
1026 }
1027
1028 if ((fields = switch_xml_child(globals.acct_end_configs, "fields")) == NULL ) {
1029 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'fields' section in config file.\n");
1030 goto end;
1031 }
1032
1033 if ( mod_xml_radius_add_params(session, NULL, new_handle, &send, fields) != SWITCH_STATUS_SUCCESS ) {
1034 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to add params to rc_handle\n");
1035 goto end;
1036 }
1037
1038 if (rc_avpair_add(new_handle, &send, PW_ACCT_STATUS_TYPE, &service, -1, 0) == NULL) {
1039 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
1040 goto end;
1041 }
1042
1043 if (rc_acct(new_handle, 0, send) == OK_RC) {
1044 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "mod_xml_radius: Accounting Stop success\n");
1045 } else {
1046 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Accounting Stop failed\n");
1047 }
1048
1049 end:
1050 if ( send ) {
1051 rc_avpair_free(send);
1052 send = NULL;
1053 }
1054 if ( new_handle) {
1055 rc_destroy(new_handle);
1056 new_handle = NULL;
1057 }
1058
1059 return SWITCH_STATUS_SUCCESS;
1060 }
1061
SWITCH_STANDARD_APP(radius_auth_handle)1062 SWITCH_STANDARD_APP(radius_auth_handle)
1063 {
1064 switch_channel_t *channel = switch_core_session_get_channel(session);
1065 int result = 0;
1066 VALUE_PAIR *send = NULL, *recv = NULL, *service_vp = NULL;
1067 char msg[512 * 10 + 1] = {0};
1068 uint32_t service = PW_AUTHENTICATE_ONLY;
1069 rc_handle *new_handle = NULL;
1070 switch_xml_t fields;
1071 char name[512], value[512], *temp = NULL;
1072
1073 if (GLOBAL_DEBUG ) {
1074 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting app authentication\n");
1075 }
1076
1077 if ( mod_xml_radius_new_handle(&new_handle, globals.auth_app_configs) != SWITCH_STATUS_SUCCESS || new_handle == NULL ) {
1078 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new authentication handle for call: %s\n",
1079 switch_channel_get_variable(channel, "uuid"));
1080 goto err;
1081 }
1082
1083 if ((fields = switch_xml_child(globals.auth_app_configs, "fields")) == NULL ) {
1084 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'fields' section in config file.\n");
1085 goto err;
1086 }
1087
1088 if ( mod_xml_radius_add_params(session, NULL, new_handle, &send, fields) != SWITCH_STATUS_SUCCESS ) {
1089 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to add params to rc_handle\n");
1090 goto err;
1091 }
1092
1093 if (rc_avpair_add(new_handle, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL) {
1094 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
1095 goto err;
1096 }
1097
1098 result = rc_auth(new_handle, 0, send, &recv, msg);
1099
1100 if ( GLOBAL_DEBUG ){
1101 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: result(RC=%d) %s \n", result, msg);
1102 }
1103 temp = switch_mprintf("%d",result);
1104 switch_channel_set_variable(channel, "radius_auth_result", temp);
1105 free(temp);
1106 temp = NULL;
1107
1108 if ( result != 0 ) {
1109 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Failed to authenticate, authentication result: %d \n", result);
1110 goto err;
1111 }
1112
1113
1114 service_vp = recv;
1115 while (service_vp != NULL) {
1116 rc_avpair_tostr(new_handle, service_vp, name, 512, value, 512);
1117 if ( GLOBAL_DEBUG )
1118 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "\tattribute (%s)[%s] found in radius packet\n", name, value);
1119
1120 switch_channel_set_variable(channel, name, value);
1121 service_vp = service_vp->next;
1122 }
1123
1124 if ( recv ) {
1125 rc_avpair_free(recv);
1126 recv = NULL;
1127 }
1128 if ( send ) {
1129 rc_avpair_free(send);
1130 send = NULL;
1131 }
1132 if ( new_handle ) {
1133 rc_destroy(new_handle);
1134 new_handle = NULL;
1135 }
1136
1137 return;
1138 err:
1139 if ( recv ) {
1140 rc_avpair_free(recv);
1141 recv = NULL;
1142 }
1143 if ( send ) {
1144 rc_avpair_free(send);
1145 send = NULL;
1146 }
1147 if ( new_handle ) {
1148 rc_destroy(new_handle);
1149 new_handle = NULL;
1150 }
1151 return;
1152 }
1153
1154 static const switch_state_handler_table_t state_handlers = {
1155 /*.on_init */ NULL,
1156 /*.on_routing */ mod_xml_radius_accounting_start,
1157 /*.on_execute */ NULL,
1158 /*.on_hangup */ NULL,
1159 /*.on_exchange_media */ NULL,
1160 /*.on_soft_execute */ NULL,
1161 /*.on_consume_media */ NULL,
1162 /*.on_hibernate */ NULL,
1163 /*.on_reset */ NULL,
1164 /*.on_park */ NULL,
1165 /*.on_reporting */ mod_xml_radius_accounting_end
1166 };
1167
1168
1169 /* switch_status_t name (switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
SWITCH_MODULE_LOAD_FUNCTION(mod_xml_radius_load)1170 SWITCH_MODULE_LOAD_FUNCTION(mod_xml_radius_load)
1171 {
1172 switch_api_interface_t *mod_xml_radius_api_interface;
1173 switch_status_t status = SWITCH_STATUS_SUCCESS;
1174 switch_application_interface_t *app_interface;
1175
1176 /* connect my internal structure to the blank pointer passed to me */
1177 *module_interface = switch_loadable_module_create_module_interface(pool, modname);
1178
1179 memset(&globals, 0, sizeof(globals));
1180 globals.pool = pool;
1181
1182 if ( GLOBAL_DEBUG != 0 ) {
1183 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: loading\n");
1184 }
1185
1186 if ( (status = do_config()) != SWITCH_STATUS_SUCCESS ) {
1187 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Failed to load configs\n");
1188 return SWITCH_STATUS_TERM;
1189 }
1190
1191 if ( globals.auth_invite_configs && globals.auth_reg_configs ) {
1192 status = switch_xml_bind_search_function(mod_xml_radius_directory_search, switch_xml_parse_section_string("directory"), NULL);
1193 }
1194
1195 SWITCH_ADD_API(mod_xml_radius_api_interface, "xml_radius_debug", "mod_xml_radius toggle debug", mod_xml_radius_debug_api, NULL);
1196
1197 switch_core_add_state_handler(&state_handlers);
1198
1199 SWITCH_ADD_APP(app_interface, "radius_auth", NULL, NULL, radius_auth_handle, "radius_auth", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
1200
1201 /* indicate that the module should continue to be loaded */
1202 return SWITCH_STATUS_SUCCESS;
1203 }
1204
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_radius_shutdown)1205 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_radius_shutdown)
1206 {
1207 switch_core_remove_state_handler(&state_handlers);
1208 switch_xml_unbind_search_function_ptr(mod_xml_radius_directory_search);
1209
1210 if ( globals.auth_invite_configs ) {
1211 switch_xml_free(globals.auth_invite_configs);
1212 }
1213 if ( globals.auth_reg_configs ) {
1214 switch_xml_free(globals.auth_reg_configs);
1215 }
1216 if ( globals.auth_app_configs ) {
1217 switch_xml_free(globals.auth_app_configs);
1218 }
1219 if ( globals.acct_start_configs ) {
1220 switch_xml_free(globals.acct_start_configs);
1221 }
1222 if ( globals.acct_end_configs ) {
1223 switch_xml_free(globals.acct_end_configs);
1224 }
1225 return SWITCH_STATUS_SUCCESS;
1226 }
1227
1228 /* For Emacs:
1229 * Local Variables:
1230 * mode:c
1231 * indent-tabs-mode:t
1232 * tab-width:4
1233 * c-basic-offset:4
1234 * End:
1235 * For VIM:
1236 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
1237 */
1238