diff --git a/src/mod/xml_int/mod_xml_radius/.gitignore b/src/mod/xml_int/mod_xml_radius/.gitignore new file mode 100644 index 0000000000..bb7ad3d288 --- /dev/null +++ b/src/mod/xml_int/mod_xml_radius/.gitignore @@ -0,0 +1 @@ +freeradius-client* \ No newline at end of file diff --git a/src/mod/xml_int/mod_xml_radius/00_dialpla_auth.xml b/src/mod/xml_int/mod_xml_radius/00_dialpla_auth.xml new file mode 100644 index 0000000000..d4c74539a1 --- /dev/null +++ b/src/mod/xml_int/mod_xml_radius/00_dialpla_auth.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mod/xml_int/mod_xml_radius/Makefile b/src/mod/xml_int/mod_xml_radius/Makefile new file mode 100644 index 0000000000..63542dff47 --- /dev/null +++ b/src/mod/xml_int/mod_xml_radius/Makefile @@ -0,0 +1,26 @@ +RADCLIENT_VERSION=1.1.6 +RADCLIENT=freeradius-client-$(RADCLIENT_VERSION) +RADCLIENT_DIR=$(switch_srcdir)/libs/$(RADCLIENT) +RADCLIENT_BUILDDIR=$(switch_builddir)/libs/$(RADCLIENT) +RADCLIENT_LIBDIR=$(RADCLIENT_BUILDDIR)/lib +RADCLIENT_LA=${RADCLIENT_LIBDIR}/libfreeradius-client.la + +LOCAL_CFLAGS=-I$(RADCLIENT_DIR)/include +LOCAL_LIBADD=$(RADCLIENT_LA) + +BASE=../../../.. +include $(BASE)/build/modmake.rules + +$(RADCLIENT_DIR): + $(GETLIB) $(RADCLIENT).tar.gz + +$(RADCLIENT_BUILDDIR)/Makefile: $(RADCLIENT_DIR) + mkdir -p $(RADCLIENT_BUILDDIR) + cd $(RADCLIENT_BUILDDIR) && $(DEFAULT_VARS) $(RADCLIENT_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(RADCLIENT_DIR) + $(TOUCH_TARGET) + +$(RADCLIENT_LA): $(RADCLIENT_BUILDDIR)/Makefile + cd $(RADCLIENT_BUILDDIR) && CFLAGS="$(CFLAGS)" $(MAKE) + $(TOUCH_TARGET) + + diff --git a/src/mod/xml_int/mod_xml_radius/dictionaries/dictionary b/src/mod/xml_int/mod_xml_radius/dictionaries/dictionary new file mode 100644 index 0000000000..431d92c544 --- /dev/null +++ b/src/mod/xml_int/mod_xml_radius/dictionaries/dictionary @@ -0,0 +1,244 @@ +# +# Updated 97/06/13 to livingston-radius-2.01 miquels@cistron.nl +# +# This file contains dictionary translations for parsing +# requests and generating responses. All transactions are +# composed of Attribute/Value Pairs. The value of each attribute +# is specified as one of 4 data types. Valid data types are: +# +# string - 0-253 octets +# ipaddr - 4 octets in network byte order +# integer - 32 bit value in big endian order (high byte first) +# date - 32 bit value in big endian order - seconds since +# 00:00:00 GMT, Jan. 1, 1970 +# +# Enumerated values are stored in the user file with dictionary +# VALUE translations for easy administration. +# +# Example: +# +# ATTRIBUTE VALUE +# --------------- ----- +# Framed-Protocol = PPP +# 7 = 1 (integer encoding) +# + +# +# Following are the proper new names. Use these. +# +$INCLUDE /usr/local/src/freeswitch/src/mod/xml_int/mod_xml_radius/dictionaries/dictionary.cisco +$INCLUDE /usr/local/src/freeswitch/src/mod/xml_int/mod_xml_radius/dictionaries/dictionary.rfc5090 + +ATTRIBUTE User-Name 1 string +ATTRIBUTE Password 2 string +ATTRIBUTE CHAP-Password 3 string +ATTRIBUTE NAS-IP-Address 4 ipaddr +ATTRIBUTE NAS-Port-Id 5 integer +ATTRIBUTE Service-Type 6 integer +ATTRIBUTE Framed-Protocol 7 integer +ATTRIBUTE Framed-IP-Address 8 ipaddr +ATTRIBUTE Framed-IP-Netmask 9 ipaddr +ATTRIBUTE Framed-Routing 10 integer +ATTRIBUTE Filter-Id 11 string +ATTRIBUTE Framed-MTU 12 integer +ATTRIBUTE Framed-Compression 13 integer +ATTRIBUTE Login-IP-Host 14 ipaddr +ATTRIBUTE Login-Service 15 integer +ATTRIBUTE Login-TCP-Port 16 integer +ATTRIBUTE Reply-Message 18 string +ATTRIBUTE Callback-Number 19 string +ATTRIBUTE Callback-Id 20 string +ATTRIBUTE Framed-Route 22 string +ATTRIBUTE Framed-IPX-Network 23 ipaddr +ATTRIBUTE State 24 string +ATTRIBUTE Class 25 string +ATTRIBUTE Vendor-Specific 26 string +ATTRIBUTE Session-Timeout 27 integer +ATTRIBUTE Idle-Timeout 28 integer +ATTRIBUTE Termination-Action 29 integer +ATTRIBUTE Called-Station-Id 30 string +ATTRIBUTE Calling-Station-Id 31 string +ATTRIBUTE NAS-Identifier 32 string +ATTRIBUTE Proxy-State 33 string +ATTRIBUTE Login-LAT-Service 34 string +ATTRIBUTE Login-LAT-Node 35 string +ATTRIBUTE Login-LAT-Group 36 string +ATTRIBUTE Framed-AppleTalk-Link 37 integer +ATTRIBUTE Framed-AppleTalk-Network 38 integer +ATTRIBUTE Framed-AppleTalk-Zone 39 string +ATTRIBUTE Acct-Status-Type 40 integer +ATTRIBUTE Acct-Delay-Time 41 integer +ATTRIBUTE Acct-Input-Octets 42 integer +ATTRIBUTE Acct-Output-Octets 43 integer +ATTRIBUTE Acct-Session-Id 44 string +ATTRIBUTE Acct-Authentic 45 integer +ATTRIBUTE Acct-Session-Time 46 integer +ATTRIBUTE Acct-Input-Packets 47 integer +ATTRIBUTE Acct-Output-Packets 48 integer +ATTRIBUTE Acct-Terminate-Cause 49 integer +ATTRIBUTE Acct-Multi-Session-Id 50 string +ATTRIBUTE Acct-Link-Count 51 integer +ATTRIBUTE Event-Timestamp 55 integer +ATTRIBUTE CHAP-Challenge 60 string +ATTRIBUTE NAS-Port-Type 61 integer +ATTRIBUTE Port-Limit 62 integer +ATTRIBUTE Login-LAT-Port 63 integer +ATTRIBUTE Connect-Info 77 string + +# +# RFC3162 IPv6 attributes +# +ATTRIBUTE NAS-IPv6-Address 95 string +ATTRIBUTE Framed-Interface-Id 96 string +ATTRIBUTE Framed-IPv6-Prefix 97 string +ATTRIBUTE Login-IPv6-Host 98 string +ATTRIBUTE Framed-IPv6-Route 99 string +ATTRIBUTE Framed-IPv6-Pool 100 string + +# +# Experimental Non Protocol Attributes used by Cistron-Radiusd +# +ATTRIBUTE Huntgroup-Name 221 string +ATTRIBUTE User-Category 1029 string +ATTRIBUTE Group-Name 1030 string +ATTRIBUTE Simultaneous-Use 1034 integer +ATTRIBUTE Strip-User-Name 1035 integer +ATTRIBUTE Fall-Through 1036 integer +ATTRIBUTE Add-Port-To-IP-Address 1037 integer +ATTRIBUTE Exec-Program 1038 string +ATTRIBUTE Exec-Program-Wait 1039 string +ATTRIBUTE Hint 1040 string + +# +# Non-Protocol Attributes +# These attributes are used internally by the server +# +ATTRIBUTE Expiration 21 date +ATTRIBUTE Auth-Type 1000 integer +ATTRIBUTE Menu 1001 string +ATTRIBUTE Termination-Menu 1002 string +ATTRIBUTE Prefix 1003 string +ATTRIBUTE Suffix 1004 string +ATTRIBUTE Group 1005 string +ATTRIBUTE Crypt-Password 1006 string +ATTRIBUTE Connect-Rate 1007 integer + +# +# Integer Translations +# + +# User Types + +VALUE Service-Type Login-User 1 +VALUE Service-Type Framed-User 2 +VALUE Service-Type Callback-Login-User 3 +VALUE Service-Type Callback-Framed-User 4 +VALUE Service-Type Outbound-User 5 +VALUE Service-Type Administrative-User 6 +VALUE Service-Type NAS-Prompt-User 7 + +# Framed Protocols + +VALUE Framed-Protocol PPP 1 +VALUE Framed-Protocol SLIP 2 + +# Framed Routing Values + +VALUE Framed-Routing None 0 +VALUE Framed-Routing Broadcast 1 +VALUE Framed-Routing Listen 2 +VALUE Framed-Routing Broadcast-Listen 3 + +# Framed Compression Types + +VALUE Framed-Compression None 0 +VALUE Framed-Compression Van-Jacobson-TCP-IP 1 + +# Login Services + +VALUE Login-Service Telnet 0 +VALUE Login-Service Rlogin 1 +VALUE Login-Service TCP-Clear 2 +VALUE Login-Service PortMaster 3 + +# Status Types + +VALUE Acct-Status-Type Start 1 +VALUE Acct-Status-Type Stop 2 +VALUE Acct-Status-Type Alive 3 +VALUE Acct-Status-Type Accounting-On 7 +VALUE Acct-Status-Type Accounting-Off 8 + +# Authentication Types + +VALUE Acct-Authentic RADIUS 1 +VALUE Acct-Authentic Local 2 +VALUE Acct-Authentic PowerLink128 100 + +# Termination Options + +VALUE Termination-Action Default 0 +VALUE Termination-Action RADIUS-Request 1 + +# NAS Port Types, available in 3.3.1 and later + +VALUE NAS-Port-Type Async 0 +VALUE NAS-Port-Type Sync 1 +VALUE NAS-Port-Type ISDN 2 +VALUE NAS-Port-Type ISDN-V120 3 +VALUE NAS-Port-Type ISDN-V110 4 + +# Acct Terminate Causes, available in 3.3.2 and later + +VALUE Acct-Terminate-Cause User-Request 1 +VALUE Acct-Terminate-Cause Lost-Carrier 2 +VALUE Acct-Terminate-Cause Lost-Service 3 +VALUE Acct-Terminate-Cause Idle-Timeout 4 +VALUE Acct-Terminate-Cause Session-Timeout 5 +VALUE Acct-Terminate-Cause Admin-Reset 6 +VALUE Acct-Terminate-Cause Admin-Reboot 7 +VALUE Acct-Terminate-Cause Port-Error 8 +VALUE Acct-Terminate-Cause NAS-Error 9 +VALUE Acct-Terminate-Cause NAS-Request 10 +VALUE Acct-Terminate-Cause NAS-Reboot 11 +VALUE Acct-Terminate-Cause Port-Unneeded 12 +VALUE Acct-Terminate-Cause Port-Preempted 13 +VALUE Acct-Terminate-Cause Port-Suspended 14 +VALUE Acct-Terminate-Cause Service-Unavailable 15 +VALUE Acct-Terminate-Cause Callback 16 +VALUE Acct-Terminate-Cause User-Error 17 +VALUE Acct-Terminate-Cause Host-Request 18 + +# +# Non-Protocol Integer Translations +# + +VALUE Auth-Type Local 0 +VALUE Auth-Type System 1 +VALUE Auth-Type SecurID 2 +VALUE Auth-Type Crypt-Local 3 +VALUE Auth-Type Reject 4 + +# +# Cistron extensions +# +VALUE Auth-Type Pam 253 +VALUE Auth-Type Accept 254 + +# +# Experimental Non-Protocol Integer Translations for Cistron-Radiusd +# +VALUE Fall-Through No 0 +VALUE Fall-Through Yes 1 +VALUE Add-Port-To-IP-Address No 0 +VALUE Add-Port-To-IP-Address Yes 1 + +# +# Configuration Values +# uncomment these two lines to turn account expiration on +# + +#VALUE Server-Config Password-Expiration 30 +#VALUE Server-Config Password-Warning 5 + + diff --git a/src/mod/xml_int/mod_xml_radius/dictionaries/dictionary.cisco b/src/mod/xml_int/mod_xml_radius/dictionaries/dictionary.cisco new file mode 100644 index 0000000000..b61c9d27cc --- /dev/null +++ b/src/mod/xml_int/mod_xml_radius/dictionaries/dictionary.cisco @@ -0,0 +1,161 @@ +# -*- text -*- +# +# dictionary.cisco +# +# Accounting VSAs originally by +# "Marcelo M. Sosa Lugones" +# +# Version: $Id$ +# +# For documentation on Cisco RADIUS attributes, see: +# +# http://www.cisco.com/univercd/cc/td/doc/product/access/acs_serv/vapp_dev/vsaig3.htm +# +# For general documentation on Cisco RADIUS configuration, see: +# +# http://www.cisco.com/en/US/partner/tech/tk583/tk547/tsd_technology_support_sub-protocol_home.html +# + +VENDOR Cisco 9 + +# +# Standard attribute +# +#BEGIN-VENDOR Cisco + +ATTRIBUTE Cisco-AVPair 1 string vendor=Cisco +ATTRIBUTE Cisco-NAS-Port 2 string vendor=Cisco + +# +# T.37 Store-and-Forward attributes. +# +ATTRIBUTE Cisco-Fax-Account-Id-Origin 3 string vendor=Cisco +ATTRIBUTE Cisco-Fax-Msg-Id 4 string vendor=Cisco +ATTRIBUTE Cisco-Fax-Pages 5 string vendor=Cisco +ATTRIBUTE Cisco-Fax-Coverpage-Flag 6 string vendor=Cisco +ATTRIBUTE Cisco-Fax-Modem-Time 7 string vendor=Cisco +ATTRIBUTE Cisco-Fax-Connect-Speed 8 string vendor=Cisco +ATTRIBUTE Cisco-Fax-Recipient-Count 9 string vendor=Cisco +ATTRIBUTE Cisco-Fax-Process-Abort-Flag 10 string vendor=Cisco +ATTRIBUTE Cisco-Fax-Dsn-Address 11 string vendor=Cisco +ATTRIBUTE Cisco-Fax-Dsn-Flag 12 string vendor=Cisco +ATTRIBUTE Cisco-Fax-Mdn-Address 13 string vendor=Cisco +ATTRIBUTE Cisco-Fax-Mdn-Flag 14 string vendor=Cisco +ATTRIBUTE Cisco-Fax-Auth-Status 15 string vendor=Cisco +ATTRIBUTE Cisco-Email-Server-Address 16 string vendor=Cisco +ATTRIBUTE Cisco-Email-Server-Ack-Flag 17 string vendor=Cisco +ATTRIBUTE Cisco-Gateway-Id 18 string vendor=Cisco +ATTRIBUTE Cisco-Call-Type 19 string vendor=Cisco +ATTRIBUTE Cisco-Port-Used 20 string vendor=Cisco +ATTRIBUTE Cisco-Abort-Cause 21 string vendor=Cisco + +# +# Voice over IP attributes. +# +ATTRIBUTE h323-remote-address 23 string vendor=Cisco +ATTRIBUTE h323-conf-id 24 string vendor=Cisco +ATTRIBUTE h323-setup-time 25 string vendor=Cisco +ATTRIBUTE h323-call-origin 26 string vendor=Cisco +ATTRIBUTE h323-call-type 27 string vendor=Cisco +ATTRIBUTE h323-connect-time 28 string vendor=Cisco +ATTRIBUTE h323-disconnect-time 29 string vendor=Cisco +ATTRIBUTE h323-disconnect-cause 30 string vendor=Cisco +ATTRIBUTE h323-voice-quality 31 string vendor=Cisco +ATTRIBUTE h323-gw-id 33 string vendor=Cisco +ATTRIBUTE h323-incoming-conf-id 35 string vendor=Cisco + +ATTRIBUTE Cisco-Policy-Up 37 string vendor=Cisco +ATTRIBUTE Cisco-Policy-Down 38 string vendor=Cisco + +ATTRIBUTE sip-conf-id 100 string vendor=Cisco +ATTRIBUTE h323-credit-amount 101 string vendor=Cisco +ATTRIBUTE h323-credit-time 102 string vendor=Cisco +ATTRIBUTE h323-return-code 103 string vendor=Cisco +ATTRIBUTE h323-prompt-id 104 string vendor=Cisco +ATTRIBUTE h323-time-and-day 105 string vendor=Cisco +ATTRIBUTE h323-redirect-number 106 string vendor=Cisco +ATTRIBUTE h323-preferred-lang 107 string vendor=Cisco +ATTRIBUTE h323-redirect-ip-address 108 string vendor=Cisco +ATTRIBUTE h323-billing-model 109 string vendor=Cisco +ATTRIBUTE h323-currency 110 string vendor=Cisco +ATTRIBUTE subscriber 111 string vendor=Cisco +ATTRIBUTE gw-rxd-cdn 112 string vendor=Cisco +ATTRIBUTE gw-final-xlated-cdn 113 string vendor=Cisco +ATTRIBUTE remote-media-address 114 string vendor=Cisco +ATTRIBUTE release-source 115 string vendor=Cisco +ATTRIBUTE gw-rxd-cgn 116 string vendor=Cisco +ATTRIBUTE gw-final-xlated-cgn 117 string vendor=Cisco + +# SIP Attributes +ATTRIBUTE call-id 141 string vendor=Cisco +ATTRIBUTE session-protocol 142 string vendor=Cisco +ATTRIBUTE method 143 string vendor=Cisco +ATTRIBUTE prev-hop-via 144 string vendor=Cisco +ATTRIBUTE prev-hop-ip 145 string vendor=Cisco +ATTRIBUTE incoming-req-uri 146 string vendor=Cisco +ATTRIBUTE outgoing-req-uri 147 string vendor=Cisco +ATTRIBUTE next-hop-ip 148 string vendor=Cisco +ATTRIBUTE next-hop-dn 149 string vendor=Cisco +ATTRIBUTE sip-hdr 150 string vendor=Cisco + +# +# Extra attributes sent by the Cisco, if you configure +# "radius-server vsa accounting" (requires IOS11.2+). +# +ATTRIBUTE Cisco-Multilink-ID 187 integer vendor=Cisco +ATTRIBUTE Cisco-Num-In-Multilink 188 integer vendor=Cisco +ATTRIBUTE Cisco-Pre-Input-Octets 190 integer vendor=Cisco +ATTRIBUTE Cisco-Pre-Output-Octets 191 integer vendor=Cisco +ATTRIBUTE Cisco-Pre-Input-Packets 192 integer vendor=Cisco +ATTRIBUTE Cisco-Pre-Output-Packets 193 integer vendor=Cisco +ATTRIBUTE Cisco-Maximum-Time 194 integer vendor=Cisco +ATTRIBUTE Cisco-Disconnect-Cause 195 integer vendor=Cisco +ATTRIBUTE Cisco-Data-Rate 197 integer vendor=Cisco +ATTRIBUTE Cisco-PreSession-Time 198 integer vendor=Cisco +ATTRIBUTE Cisco-PW-Lifetime 208 integer vendor=Cisco +ATTRIBUTE Cisco-IP-Direct 209 integer vendor=Cisco +ATTRIBUTE Cisco-PPP-VJ-Slot-Comp 210 integer vendor=Cisco +ATTRIBUTE Cisco-PPP-Async-Map 212 integer vendor=Cisco +ATTRIBUTE Cisco-IP-Pool-Definition 217 string vendor=Cisco +ATTRIBUTE Cisco-Assign-IP-Pool 218 integer vendor=Cisco +ATTRIBUTE Cisco-Route-IP 228 integer vendor=Cisco +ATTRIBUTE Cisco-Link-Compression 233 integer vendor=Cisco +ATTRIBUTE Cisco-Target-Util 234 integer vendor=Cisco +ATTRIBUTE Cisco-Maximum-Channels 235 integer vendor=Cisco +ATTRIBUTE Cisco-Data-Filter 242 integer vendor=Cisco +ATTRIBUTE Cisco-Call-Filter 243 integer vendor=Cisco +ATTRIBUTE Cisco-Idle-Limit 244 integer vendor=Cisco +ATTRIBUTE Cisco-Subscriber-Password 249 string vendor=Cisco +ATTRIBUTE Cisco-Account-Info 250 string vendor=Cisco +ATTRIBUTE Cisco-Service-Info 251 string vendor=Cisco +ATTRIBUTE Cisco-Command-Code 252 string vendor=Cisco +ATTRIBUTE Cisco-Control-Info 253 string vendor=Cisco +ATTRIBUTE Cisco-Xmit-Rate 255 integer vendor=Cisco + +VALUE Cisco-Disconnect-Cause Unknown 2 +VALUE Cisco-Disconnect-Cause CLID-Authentication-Failure 4 +VALUE Cisco-Disconnect-Cause No-Carrier 10 +VALUE Cisco-Disconnect-Cause Lost-Carrier 11 +VALUE Cisco-Disconnect-Cause No-Detected-Result-Codes 12 +VALUE Cisco-Disconnect-Cause User-Ends-Session 20 +VALUE Cisco-Disconnect-Cause Idle-Timeout 21 +VALUE Cisco-Disconnect-Cause Exit-Telnet-Session 22 +VALUE Cisco-Disconnect-Cause No-Remote-IP-Addr 23 +VALUE Cisco-Disconnect-Cause Exit-Raw-TCP 24 +VALUE Cisco-Disconnect-Cause Password-Fail 25 +VALUE Cisco-Disconnect-Cause Raw-TCP-Disabled 26 +VALUE Cisco-Disconnect-Cause Control-C-Detected 27 +VALUE Cisco-Disconnect-Cause EXEC-Program-Destroyed 28 +VALUE Cisco-Disconnect-Cause Timeout-PPP-LCP 40 +VALUE Cisco-Disconnect-Cause Failed-PPP-LCP-Negotiation 41 +VALUE Cisco-Disconnect-Cause Failed-PPP-PAP-Auth-Fail 42 +VALUE Cisco-Disconnect-Cause Failed-PPP-CHAP-Auth 43 +VALUE Cisco-Disconnect-Cause Failed-PPP-Remote-Auth 44 +VALUE Cisco-Disconnect-Cause PPP-Remote-Terminate 45 +VALUE Cisco-Disconnect-Cause PPP-Closed-Event 46 +VALUE Cisco-Disconnect-Cause Session-Timeout 100 +VALUE Cisco-Disconnect-Cause Session-Failed-Security 101 +VALUE Cisco-Disconnect-Cause Session-End-Callback 102 +VALUE Cisco-Disconnect-Cause Invalid-Protocol 120 + +#END-VENDOR Cisco diff --git a/src/mod/xml_int/mod_xml_radius/dictionaries/dictionary.rfc5090 b/src/mod/xml_int/mod_xml_radius/dictionaries/dictionary.rfc5090 new file mode 100644 index 0000000000..4feda43628 --- /dev/null +++ b/src/mod/xml_int/mod_xml_radius/dictionaries/dictionary.rfc5090 @@ -0,0 +1,27 @@ +# -*- text -*- +# +# Attributes and values defined in RFC 5090. +# http://www.ietf.org/rfc/rfc5090.txt +# +# $Id$ +# +ATTRIBUTE Digest-Response 103 string +ATTRIBUTE Digest-Realm 104 string +ATTRIBUTE Digest-Nonce 105 string +ATTRIBUTE Digest-Response-Auth 106 string +ATTRIBUTE Digest-Nextnonce 107 string +ATTRIBUTE Digest-Method 108 string +ATTRIBUTE Digest-URI 109 string +ATTRIBUTE Digest-Qop 110 string +ATTRIBUTE Digest-Algorithm 111 string +ATTRIBUTE Digest-Entity-Body-Hash 112 string +ATTRIBUTE Digest-CNonce 113 string +ATTRIBUTE Digest-Nonce-Count 114 string +ATTRIBUTE Digest-Username 115 string +ATTRIBUTE Digest-Opaque 116 string +ATTRIBUTE Digest-Auth-Param 117 string +ATTRIBUTE Digest-AKA-Auts 118 string +ATTRIBUTE Digest-Domain 119 string +ATTRIBUTE Digest-Stale 120 string +ATTRIBUTE Digest-HA1 121 string +ATTRIBUTE SIP-AOR 122 string diff --git a/src/mod/xml_int/mod_xml_radius/mod_xml_radius.c b/src/mod/xml_int/mod_xml_radius/mod_xml_radius.c new file mode 100644 index 0000000000..28fd56eca6 --- /dev/null +++ b/src/mod/xml_int/mod_xml_radius/mod_xml_radius.c @@ -0,0 +1,824 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2012, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * William King + * + * mod_xml_radius.c -- Radius authentication and authorization + * + */ +#include +#include + +static struct { + switch_memory_pool_t *pool; + switch_xml_t auth_invite_configs; + switch_xml_t auth_app_configs; + switch_xml_t acct_start_configs; + switch_xml_t acct_end_configs; + /* xml read write lock */ +} globals = {0}; + +SWITCH_MODULE_LOAD_FUNCTION(mod_xml_radius_load); +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_radius_shutdown); +SWITCH_MODULE_DEFINITION(mod_xml_radius, mod_xml_radius_load, mod_xml_radius_shutdown, NULL); + +static int GLOBAL_DEBUG = 0; + +switch_status_t mod_xml_radius_new_handle(rc_handle **new_handle, switch_xml_t xml) { + switch_xml_t server, param; + + *new_handle = rc_new(); + + if ( *new_handle == NULL ) { + goto err; + } + + *new_handle = rc_config_init(*new_handle); + + if ( *new_handle == NULL ) { + goto err; + } + + if (rc_add_config(*new_handle, "auth_order", "radius", "mod_radius_cdr.c", 0) != 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error adding auth_order\n"); + goto err; + } + + if ((server = switch_xml_child(xml, "connection")) == NULL ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'connection' section in config file.\n"); + goto err; + } + + for (param = switch_xml_child(server, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + char *val = (char *) switch_xml_attr_soft(param, "value"); + + if ( GLOBAL_DEBUG ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Attempting to add param '%s' with value '%s' \n", var, val); + } + + if (strncmp(var, "dictionary", 10) == 0) { + rc_read_dictionary(*new_handle, val); + } else if (rc_add_config(*new_handle, var, val, "mod_xml_radius", 0) != 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error adding param '%s' with value '%s' \n", var, val); + goto err; + } + } + + return SWITCH_STATUS_SUCCESS; + + err: + if ( *new_handle ) { + rc_destroy( *new_handle ); + *new_handle = NULL; + } + return SWITCH_STATUS_GENERR; +} + +switch_status_t do_config() +{ + char *conf = "xml_radius.conf"; + switch_xml_t xml, cfg, tmp, server; + int serv, timeout, deadtime, retries, dict, seq; + /* TODO: + 1. read new auth_invite_configs + 2. Create replacement xml and vas objects + 3. Get the write lock. + 4. Replace xml and vas objects + 5. unlock and return. + */ + + if (!(xml = switch_xml_open_cfg(conf, &cfg, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", conf); + goto err; + } + + serv = timeout = deadtime = retries = dict = seq = 0; + if ((tmp = switch_xml_dup(switch_xml_child(cfg, "auth_invite"))) != NULL ) { + if ( (server = switch_xml_child(xml, "connection")) != NULL) { + for (param = switch_xml_child(server, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + if ( strncmp(var, "authserver", 10) == 0 ) { + serv = 1; + } else if ( strncmp(var, "radius_timeout", 14) == 0 ) { + timeout = 1; + } else if ( strncmp(var, "radius_deadtime", 15) == 0 ) { + deadtime = 1; + } else if ( strncmp(var, "radius_retries", 14) == 0 ) { + retries = 1; + } else if ( strncmp(var, "dictionary", 10) == 0 ) { + dict = 1; + } else if ( strncmp(var, "seqfile", 7) == 0 ) { + seq = 1; + } + } + + if ( serv && timeout && deadtime && retries && dict && seq ) { + globals.auth_invite_configs = tmp; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing a require section for radius connections\n"); + goto err; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'connection' section for auth_invite\n"); + goto err; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Could not find 'auth_invite' section in config file.\n"); + } + + if ((globals.auth_app_configs = switch_xml_dup(switch_xml_child(cfg, "auth_app"))) == NULL ) { + if ( (server = switch_xml_child(xml, "connection")) != NULL) { + for (param = switch_xml_child(server, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + if ( strncmp(var, "authserver", 10) == 0 ) { + serv = 1; + } else if ( strncmp(var, "radius_timeout", 14) == 0 ) { + timeout = 1; + } else if ( strncmp(var, "radius_deadtime", 15) == 0 ) { + deadtime = 1; + } else if ( strncmp(var, "radius_retries", 14) == 0 ) { + retries = 1; + } else if ( strncmp(var, "dictionary", 10) == 0 ) { + dict = 1; + } else if ( strncmp(var, "seqfile", 7) == 0 ) { + seq = 1; + } + } + + if ( serv && timeout && deadtime && retries && dict && seq ) { + globals.auth_invite_configs = tmp; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing a require section for radius connections\n"); + goto err; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'connection' section for auth_app\n"); + goto err; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Could not find 'auth_app' section in config file.\n"); + } + + if ((globals.acct_start_configs = switch_xml_dup(switch_xml_child(cfg, "acct_start"))) == NULL ) { + if ( (server = switch_xml_child(xml, "connection")) != NULL) { + for (param = switch_xml_child(server, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + if ( strncmp(var, "acctserver", 10) == 0 ) { + serv = 1; + } else if ( strncmp(var, "radius_timeout", 14) == 0 ) { + timeout = 1; + } else if ( strncmp(var, "radius_deadtime", 15) == 0 ) { + deadtime = 1; + } else if ( strncmp(var, "radius_retries", 14) == 0 ) { + retries = 1; + } else if ( strncmp(var, "dictionary", 10) == 0 ) { + dict = 1; + } else if ( strncmp(var, "seqfile", 7) == 0 ) { + seq = 1; + } + } + + if ( serv && timeout && deadtime && retries && dict && seq ) { + globals.auth_invite_configs = tmp; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing a require section for radius connections\n"); + goto err; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'connection' section for acct_start\n"); + goto err; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Could not find 'acct_start' section in config file.\n"); + } + + if ((globals.acct_end_configs = switch_xml_dup(switch_xml_child(cfg, "acct_end"))) == NULL ) { + if ( (server = switch_xml_child(xml, "connection")) != NULL) { + for (param = switch_xml_child(server, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + if ( strncmp(var, "acctserver", 10) == 0 ) { + serv = 1; + } else if ( strncmp(var, "radius_timeout", 14) == 0 ) { + timeout = 1; + } else if ( strncmp(var, "radius_deadtime", 15) == 0 ) { + deadtime = 1; + } else if ( strncmp(var, "radius_retries", 14) == 0 ) { + retries = 1; + } else if ( strncmp(var, "dictionary", 10) == 0 ) { + dict = 1; + } else if ( strncmp(var, "seqfile", 7) == 0 ) { + seq = 1; + } + } + + if ( serv && timeout && deadtime && retries && dict && seq ) { + globals.auth_invite_configs = tmp; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing a require section for radius connections\n"); + goto err; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'connection' section for acct_end\n"); + goto err; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Could not find 'acct_end' section in config file.\n"); + } + + if ( xml ) { + switch_xml_free(xml); + } + + return SWITCH_STATUS_SUCCESS; + + err: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Configuration error\n"); + if ( xml ) { + switch_xml_free(xml); + } + + return SWITCH_STATUS_GENERR; +} + +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) +{ + switch_xml_t param; + + if ( (param = switch_xml_child(fields, "param")) == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to locate a param under the fields section\n"); + goto err; + } + + for (; param; param = param->next) { + DICT_ATTR *attribute = NULL; + DICT_VENDOR *vendor = NULL; + int attr_num = 0, vend_num = 0; + void *av_value = NULL; + + char *var = (char *) switch_xml_attr(param, "name"); + char *vend = (char *) switch_xml_attr(param, "vendor"); + char *variable = (char *) switch_xml_attr(param, "variable"); + char *format = (char *) switch_xml_attr(param, "format"); + + attribute = rc_dict_findattr(handle, var); + + if ( attribute == NULL ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Could not locate attribute '%s' in the configured dictionary\n", var); + goto err; + } + + if ( GLOBAL_DEBUG ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: dict attr '%s' value '%d' type '%d'\n", + attribute->name, attribute->value, attribute->type); + } + + attr_num = attribute->value; + + if ( vend ) { + vendor = rc_dict_findvend(handle, vend); + + if ( vendor == NULL ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Could not locate vendor '%s' in the configured dictionary %p\n", + vend, vend); + goto err; + } + + if ( GLOBAL_DEBUG ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: dict vend name '%s' vendorpec '%d'\n", + vendor->vendorname, vendor->vendorpec); + } + + vend_num = vendor->vendorpec; + } + + if ( var ) { + if ( session ) { + switch_channel_t *channel = switch_core_session_get_channel(session); + + /* Accounting only */ + if ( strncmp( var, "h323-setup-time", 15) == 0 ) { + switch_caller_profile_t *profile = switch_channel_get_caller_profile(channel); + switch_time_t time = profile->times->created; + switch_time_exp_t tm; + + switch_time_exp_lt(&tm, time); + av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, + tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600); + + if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n"); + goto err; + } + } else if ( strncmp( var, "h323-connect-time", 17) == 0 ) { + switch_caller_profile_t *profile = switch_channel_get_caller_profile(channel); + switch_time_t time = profile->times->answered; + switch_time_exp_t tm; + + switch_time_exp_lt(&tm, time); + + av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, + tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600); + + if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n"); + goto err; + } + } else if ( strncmp( var, "h323-disconnect-time", 20) == 0 ) { + switch_caller_profile_t *profile = switch_channel_get_caller_profile(channel); + switch_time_t time = profile->times->hungup; + switch_time_exp_t tm; + + switch_time_exp_lt(&tm, time); + + av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, + tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600); + + if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n"); + goto err; + } + } else if ( strncmp( var, "h323-disconnect-cause", 21) == 0 ) { + switch_call_cause_t cause = switch_channel_get_cause(channel); + av_value = switch_mprintf("h323-disconnect-cause=%x", cause); + if (rc_avpair_add(handle, send, 30, av_value, -1, 9) == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add disconnect cause \n"); + goto err; + } + + } else { + if ( attribute->type == 0 ) { + av_value = switch_mprintf(format, switch_channel_get_variable(channel, variable)); + if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option with val '%s' to handle\n", (char *) av_value); + goto err; + } + } else if ( attribute->type == 1 ) { + int number = atoi(switch_channel_get_variable(channel, variable)); + + if (rc_avpair_add(handle, send, attr_num, &number, -1, vend_num) == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option with value '%d' to handle\n", number); + goto err; + } + } + } + } else if ( params ) { + /* Auth only */ + char *tmp = switch_event_get_header(params, variable); + + if ( GLOBAL_DEBUG ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: param var '%s' val: %s\n", variable, tmp); + } + + if ( tmp == NULL ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Unable to locate '%s' on the event\n", variable); + goto err; + } + + av_value = switch_mprintf(format, tmp); + if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n"); + goto err; + } + } else { + goto err; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: all params must have a name attribute\n"); + goto err; + } + if ( av_value != NULL ) { + free(av_value); + } + } + + return SWITCH_STATUS_SUCCESS; + err: + return SWITCH_STATUS_GENERR; + +} + +/* 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_connect_test) +{ + int result = 0; + VALUE_PAIR *send = NULL, *recv = NULL; + char msg[512 * 10 + 1] = {0}; + uint32_t service = PW_AUTHENTICATE_ONLY; + rc_handle *new_handle = NULL; + switch_xml_t fields; + + if ( GLOBAL_DEBUG ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting connection test\n"); + } + + mod_xml_radius_new_handle(&new_handle, globals.auth_invite_configs); + + if ((fields = switch_xml_child(globals.auth_invite_configs, "fields")) == NULL ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'fields' section in config file.\n"); + goto err; + } + + if ( mod_xml_radius_add_params(NULL, NULL, new_handle, &send, fields) !=SWITCH_STATUS_SUCCESS ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to add params to rc_handle\n"); + goto err; + } + + if (rc_avpair_add(new_handle, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n"); + return SWITCH_STATUS_SUCCESS; + } + + result = rc_auth(new_handle, 0, send, &recv, msg); + + if ( GLOBAL_DEBUG ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: result(RC=%d) %s \n", result, msg); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: finished connection test\n"); + } + + err: + if ( recv ) { + rc_avpair_free(recv); + recv = NULL; + } + rc_destroy(new_handle); + + return SWITCH_STATUS_SUCCESS; +} + +switch_xml_t mod_xml_radius_auth_invite(switch_event_t *params) { + int result = 0, param_idx = 0; + VALUE_PAIR *send = NULL, *recv = NULL, *service_vp = NULL; + char msg[512 * 10 + 1] = {0}; + uint32_t service = PW_AUTHENTICATE_ONLY; + rc_handle *new_handle = NULL; + switch_xml_t fields, xml, dir, dom, usr, vars, var; + char name[512], value[512], *strtmp; + + if (GLOBAL_DEBUG ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting invite authentication\n"); + } + + mod_xml_radius_new_handle(&new_handle, globals.auth_invite_configs); + + if ( new_handle == NULL ) { + goto err; + } + + if ((fields = switch_xml_child(globals.auth_invite_configs, "fields")) == NULL ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'fields' section in config file.\n"); + goto err; + } + + if ( mod_xml_radius_add_params(NULL, params, new_handle, &send, fields) != SWITCH_STATUS_SUCCESS ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to add params to rc_handle\n"); + goto err; + } + + if (rc_avpair_add(new_handle, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n"); + goto err; + } + + result = rc_auth(new_handle, 0, send, &recv, msg); + + if ( GLOBAL_DEBUG ){ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: result(RC=%d) %s \n", result, msg); + } + + if ( result != 0 ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Failed to authenticate\n"); + goto err; + } + + xml = switch_xml_new("document"); + switch_xml_set_attr_d(xml, "type", "freeswitch/xml"); + dir = switch_xml_add_child_d(xml, "section", 0); + switch_xml_set_attr_d(dir, "name", "directory"); + dom = switch_xml_add_child_d(dir, "domain", 0); + switch_xml_set_attr_d(dom, "name", switch_event_get_header(params, "domain")); + usr = switch_xml_add_child_d(dom, "user", 0); + vars = switch_xml_add_child_d(usr, "variables", 0); + + switch_xml_set_attr_d(usr, "id", switch_event_get_header(params, "user")); + + service_vp = recv; + while (service_vp != NULL) { + rc_avpair_tostr(new_handle, service_vp, name, 512, value, 512); + if ( GLOBAL_DEBUG ) + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "\tattribute (%s)[%s] found in radius packet\n", name, value); + var = switch_xml_add_child_d(vars, "variable", param_idx++); + strtmp = strdup(name); + switch_xml_set_attr_d(var, "name", strtmp); + free(strtmp); + strtmp = strdup(value); + switch_xml_set_attr_d(var, "value", strtmp); + free(strtmp); + service_vp = service_vp->next; + } + + if ( GLOBAL_DEBUG ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "XML: %s \n", switch_xml_toxml(xml, 1)); + } + + rc_avpair_free(recv); + rc_destroy(new_handle); + return xml; + err: + if ( recv ) { + rc_avpair_free(recv); + recv = NULL; + } + if ( new_handle ) { + rc_destroy(new_handle); + new_handle = NULL; + } + + return NULL; +} + +static switch_xml_t 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) +{ + char *event_buf = NULL; + switch_xml_t xml = NULL; + char *auth_method = switch_event_get_header(params,"sip_auth_method"); + + + if ( GLOBAL_DEBUG ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting authentication\n"); + switch_event_serialize(params, &event_buf, SWITCH_TRUE); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Event: %s \n", event_buf); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Section: %s \nTag: %s\nKey_name: %s\nKey_value: %s\n", + section, tag_name, key_name, key_value); + } + + if ( auth_method == NULL) { + return NULL; + } + + if ( strncmp( "INVITE", auth_method, 6) == 0) { + xml = mod_xml_radius_auth_invite(params); + } else { + xml = NULL; + } + + return xml; +} + +switch_status_t mod_xml_radius_accounting_start(switch_core_session_t *session){ + VALUE_PAIR *send = NULL; + uint32_t service = PW_STATUS_START; + rc_handle *new_handle = NULL; + switch_xml_t fields; + + if (GLOBAL_DEBUG ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting accounting start\n"); + } + + mod_xml_radius_new_handle(&new_handle, globals.acct_start_configs); + + if ((fields = switch_xml_child(globals.acct_start_configs, "fields")) == NULL ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'fields' section in config file.\n"); + goto end; + } + + if ( mod_xml_radius_add_params(session, NULL, new_handle, &send, fields) != SWITCH_STATUS_SUCCESS ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to add params to rc_handle\n"); + goto end; + } + + if (rc_avpair_add(new_handle, &send, PW_ACCT_STATUS_TYPE, &service, -1, 0) == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n"); + goto end; + } + + if (rc_acct(new_handle, 0, send) == OK_RC) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "mod_xml_radius: Accounting Start success\n"); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Accounting Start failed\n"); + } + + end: + rc_destroy(new_handle); + + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t mod_xml_radius_accounting_end(switch_core_session_t *session){ + VALUE_PAIR *send = NULL; + uint32_t service = PW_STATUS_STOP; + rc_handle *new_handle = NULL; + switch_xml_t fields; + + if (GLOBAL_DEBUG ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting accounting stop\n"); + switch_core_session_execute_application(session, "info", NULL); + } + + mod_xml_radius_new_handle(&new_handle, globals.acct_end_configs); + + if ((fields = switch_xml_child(globals.acct_end_configs, "fields")) == NULL ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'fields' section in config file.\n"); + goto end; + } + + if ( mod_xml_radius_add_params(session, NULL, new_handle, &send, fields) != SWITCH_STATUS_SUCCESS ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to add params to rc_handle\n"); + goto end; + } + + if (rc_avpair_add(new_handle, &send, PW_ACCT_STATUS_TYPE, &service, -1, 0) == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n"); + goto end; + } + + if (rc_acct(new_handle, 0, send) == OK_RC) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "mod_xml_radius: Accounting Stop success\n"); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Accounting Stop failed\n"); + } + + end: + rc_destroy(new_handle); + + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_STANDARD_APP(radius_auth_handle) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + + int result = 0; + VALUE_PAIR *send = NULL, *recv = NULL, *service_vp = NULL; + char msg[512 * 10 + 1] = {0}; + uint32_t service = PW_AUTHENTICATE_ONLY; + rc_handle *new_handle = NULL; + switch_xml_t fields; + char name[512], value[512]; + + if (GLOBAL_DEBUG ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting app authentication\n"); + } + + mod_xml_radius_new_handle(&new_handle, globals.auth_app_configs); + + if ( new_handle == NULL ) { + goto err; + } + + if ((fields = switch_xml_child(globals.auth_app_configs, "fields")) == NULL ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'fields' section in config file.\n"); + goto err; + } + + if ( mod_xml_radius_add_params(session, NULL, new_handle, &send, fields) != SWITCH_STATUS_SUCCESS ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to add params to rc_handle\n"); + goto err; + } + + if (rc_avpair_add(new_handle, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n"); + goto err; + } + + result = rc_auth(new_handle, 0, send, &recv, msg); + + if ( GLOBAL_DEBUG ){ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: result(RC=%d) %s \n", result, msg); + } + + switch_channel_set_variable(channel, "radius_auth_result", switch_mprintf("%d",result)); + + if ( result != 0 ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Failed to authenticate\n"); + goto err; + } + + + service_vp = recv; + while (service_vp != NULL) { + rc_avpair_tostr(new_handle, service_vp, name, 512, value, 512); + if ( GLOBAL_DEBUG ) + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "\tattribute (%s)[%s] found in radius packet\n", name, value); + + switch_channel_set_variable(channel, name, value); + service_vp = service_vp->next; + } + + rc_avpair_free(recv); + rc_destroy(new_handle); + return; + err: + if ( recv ) { + rc_avpair_free(recv); + recv = NULL; + } + if ( new_handle ) { + rc_destroy(new_handle); + new_handle = NULL; + } + + return; +} + +static const switch_state_handler_table_t state_handlers = { + /*.on_init */ NULL, + /*.on_routing */ mod_xml_radius_accounting_start, + /*.on_execute */ NULL, + /*.on_hangup */ NULL, + /*.on_exchange_media */ NULL, + /*.on_soft_execute */ NULL, + /*.on_consume_media */ NULL, + /*.on_hibernate */ NULL, + /*.on_reset */ NULL, + /*.on_park */ NULL, + /*.on_reporting */ mod_xml_radius_accounting_end +}; + + +/* switch_status_t name (switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */ +SWITCH_MODULE_LOAD_FUNCTION(mod_xml_radius_load) +{ + switch_api_interface_t *mod_xml_radius_api_interface; + switch_status_t status = SWITCH_STATUS_SUCCESS; + switch_application_interface_t *app_interface; + + /* connect my internal structure to the blank pointer passed to me */ + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + + memset(&globals, 0, sizeof(globals)); + globals.pool = pool; + + if ( GLOBAL_DEBUG != 0 ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: loading\n"); + } + + if ( (status = do_config()) != SWITCH_STATUS_SUCCESS ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Failed to load configs\n"); + return SWITCH_STATUS_TERM; + } + + if ( globals.auth_invite_configs ) { + status = switch_xml_bind_search_function(mod_xml_radius_directory_search, switch_xml_parse_section_string("directory"), NULL); + } + + SWITCH_ADD_API(mod_xml_radius_api_interface, "xml_radius_connect_test", "mod_xml_radius connection test", mod_xml_radius_connect_test, NULL); + + switch_core_add_state_handler(&state_handlers); + + SWITCH_ADD_APP(app_interface, "radius_auth", NULL, NULL, radius_auth_handle, "radius_auth", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + + /* indicate that the module should continue to be loaded */ + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_radius_shutdown) +{ + switch_core_remove_state_handler(&state_handlers); + switch_xml_unbind_search_function_ptr(mod_xml_radius_directory_search); + + if ( globals.auth_invite_configs ) { + switch_xml_free(globals.auth_invite_configs); + } + return SWITCH_STATUS_SUCCESS; +} + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */ diff --git a/src/mod/xml_int/mod_xml_radius/xml_radius.conf.xml b/src/mod/xml_int/mod_xml_radius/xml_radius.conf.xml new file mode 100644 index 0000000000..3340cf17b4 --- /dev/null +++ b/src/mod/xml_int/mod_xml_radius/xml_radius.conf.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +