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