From: jdegraeve Date: Tue, 7 Feb 2006 15:43:57 +0000 (+0000) Subject: Adding of DRAFT!!! files for NAS-IP and new radius_accounting_v2.inc. X-Git-Url: https://git.gsnw.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=218dc8fb73b543b3e11ce1e86a44967eb1f60f1e;p=m0n0chwall.git Adding of DRAFT!!! files for NAS-IP and new radius_accounting_v2.inc. git-svn-id: https://svn.m0n0.ch/wall/trunk@53 e36fee2c-cc09-0410-a7cc-ebac5c6737de --- diff --git a/captiveportal/radius_accounting_nas_ip.inc b/captiveportal/radius_accounting_nas_ip.inc new file mode 100644 index 0000000..720879a --- /dev/null +++ b/captiveportal/radius_accounting_nas_ip.inc @@ -0,0 +1,358 @@ + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + // This version of radius_accounting.inc has been modified by + // Rob Parker . Changes made include: + // * now sends Framed-IP-Address (client IP) + // * now sends Called-Station-ID (NAS IP) + // * now sends Calling-Station-ID (client IP) + + // This version of radius_accounting.inc has been modified by + // Jonathan De Graeve . Changes made include: + // - RFC2869 (Radius Extensions) + // * now sends Acct-Input-Gigawords + // * now sends Acct-Output-Gigawords + // * full implementation of nas-ip/nas_mac and called/calling-station ids + +*/ + +function RADIUS_ACCOUNTING_START($ruleno,$username,$sessionid,$radiusip,$radiusport,$radiuskey,$clientip,$clientmac) { + # $debug = 1 ; + global $config; + + exec("/bin/hostname", $nasHostname) ; + if(!$nasHostname[0]) + $nasHostname[0] = "m0n0wall" ; + + $fd = @fsockopen("udp://$radiusip",$radiusport,$errno,$errstr,3) ; + if(!$fd) + return 1 ; /* error return */ + + /* set 5 second timeout on socket i/o */ + stream_set_timeout($fd, 5) ; + + $nas_ip = get_nas_ip(); + $nas_ip_exp = explode(".",$nas_ip); + $nas_mac = get_interface_mac($config['interfaces']['wan']['if']); // This function is defined in radius_authentication.inc + $nas_port = $ruleno - 10000; + $ip_exp=explode(".",$clientip); + $radiusvendor = $config['captiveportal']['radiusvendor'] ? $config['captiveportal']['radiusvendor'] : null; + + switch($radiusvendor) { + + case 'cisco': + $calledstationid = $clientmac; + $callingstationid = $clientip; + break; + + default: + $calledstationid = $nas_mac; + $callingstationid = $clientmac; + break; + } + + if ($debug) + echo "
radius-port: $radiusport
radius-host: $radiusip
username: $username
\n"; + + /* Initialise rand function, make it more random */ + srand((double)microtime() * 1000000); + + $thisidentifier=rand()%256; + + $length=4+ // header + 16+ // auth code + 6+ // service type + 2+strlen($username)+ // username + 2+strlen($nasHostname[0])+ // nasIdentifier + 6+ // nasPort + 6+ // nasPortType + 6+ // Acct Status Type + 6+ // Acct RADIUS Authenticated + 2+strlen($sessionid)+ // Acct SessionID + 2+strlen($calledstationid)+ //Called-Station-ID + 2+strlen($callingstationid)+ //Calling-Station-ID + 6+ // nas-IP-Address + 6; // Framed-IP-Address + + // v v v v v v v v v 1 v + // Line # 1 2 3 4 5 6 7 8 9 0 E + $data=pack("CCCCNNNNCCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCa*CCa*CCCCCCCCCCCC", + 4,$thisidentifier,$length/256,$length%256, // header + 0,0,0,0, // authcode + 6,6,0,0,0,1, // service type + 1,2+strlen($username),$username, // username + 32,2+strlen($nasHostname[0]),$nasHostname[0], // nasIdentifier + 5,6,0,0,0,$nas_port, // nasPort + 61,6,0,0,0,15, // nasPortType = Ethernet + 40,6,0,0,0,1, // Acct Status Type = Start + 45,6,0,0,0,1, // Acct RADIUS Authenticated + 44,2+strlen($sessionid),$sessionid, // Acct Session ID + 30,2+strlen($calledstationid),$calledstationid, //Called-Station-ID + 31,2+strlen($callingstationid),$callingstationid, //Calling-Station-ID + 4,6,$nas_ip_exp[0],$nas_ip_exp[1],$nas_ip_exp[2],$nas_ip_exp[3], //nas-IP-Address + 8,6,$ip_exp[0],$ip_exp[1],$ip_exp[2],$ip_exp[3] //Framed-IP-Address + ); + + /* Generate Accounting Request Authenticator */ + $RA = md5($data.$radiuskey) ; + + // v v v v v v v v v 1 v + // Line # 1 2 3 4 5 6 7 8 9 0 E + $data=pack("CCCCH*CCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCa*CCa*CCCCCCCCCCCC", + 4,$thisidentifier,$length/256,$length%256, // header + $RA, // authcode + 6,6,0,0,0,1, // service type + 1,2+strlen($username),$username, // username + 32,2+strlen($nasHostname[0]),$nasHostname[0], // nasIdentifier + 5,6,0,0,0,$nas_port, // nasPort + 61,6,0,0,0,15, // nasPortType = Ethernet + 40,6,0,0,0,1, // Acct Status Type = Start + 45,6,0,0,0,1, // Acct RADIUS Authenticated + 44,2+strlen($sessionid),$sessionid, // Acct Session ID + 30,2+strlen($calledstationid),$calledstationid, //Called-Station-ID + 31,2+strlen($callingstationid),$callingstationid, //Calling-Station-ID + 4,6,$nas_ip_exp[0],$nas_ip_exp[1],$nas_ip_exp[2],$nas_ip_exp[3], //nas-IP-Address + 8,6,$ip_exp[0],$ip_exp[1],$ip_exp[2],$ip_exp[3] //Framed-IP-Address + ); + + if($debug) { + echo "username is $username with len " . strlen($username) ."\n" ; + echo "nasHostname is {$nasHostname[0]} with len " . strlen($nasHostname[0]) ."\n" ; + } + + $ret = fwrite($fd,$data) ; + if( !$ret || ($ret != $length) ) + return 1; /* error return */ + + if ($debug) + echo "
writing $length bytes
\n"; + + $readdata = fgets($fd,2) ; /* read 1 byte */ + $status = socket_get_status($fd) ; + fclose($fd) ; + + if($status['timed_out']) + $retvalue = 1 ; + else + $retvalue = ord($readdata) ; + + return $retvalue ; + // 5 -> Accounting-Response + // See RFC2866 for this. +} + +function RADIUS_ACCOUNTING_STOP($ruleno,$username,$sessionid,$start_time,$radiusip,$radiusport,$radiuskey,$clientip,$clientmac,$interimupdate=false, $radius_term_cause = 1) { + # $debug = 1 ; + global $config; + + exec("/bin/hostname", $nasHostname) ; + if(!$nasHostname[0]) + $nasHostname[0] = "quewall" ; + + $input_pkts = $input_bytes = $input_gigawords = $output_pkts = $output_bytes = $output_gigawords = 0 ; + + exec("/sbin/ipfw show {$ruleno}", $ipfw) ; + preg_match("/(\d+)\s+(\d+)\s+(\d+)\s+skipto/", $ipfw[0], $matches) ; + $input_pkts = $matches[2] ; + $input_bytes = remainder($matches[3]) ; + $input_gigawords = gigawords($matches[3]) ; + + unset($matches) ; + preg_match("/(\d+)\s+(\d+)\s+(\d+)\s+skipto/", $ipfw[1], $matches) ; + $output_pkts = $matches[2] ; + $output_bytes = remainder($matches[3]) ; + $output_gigawords = gigawords($matches[3]) ; + + $fd = @fsockopen("udp://$radiusip",$radiusport,$errno,$errstr,3) ; + if(!$fd) + return 1 ; /* error return */ + + /* set 5 second timeout on socket i/o */ + stream_set_timeout($fd, 5) ; + + $nas_ip = get_nas_ip(); + $nas_ip_exp = explode(".",$nas_ip); + $nas_port = $ruleno - 10000; + $nas_mac = get_interface_mac($config['interfaces']['wan']['if']); + $ip_exp=explode(".",$clientip); + $radiusvendor = $config['captiveportal']['radiusvendor'] ? $config['captiveportal']['radiusvendor'] : null; + + switch($radiusvendor) { + + case 'cisco': + $calledstationid = $clientmac; + $callingstationid = $clientip; + break; + + default: + $calledstationid = $nas_mac; + $callingstationid = $clientmac; + break; + } + + if ($debug) + echo "
radius-port: $radiusport
radius-host: $radiusip
username: $username
\n"; + + /* Initialise rand function, make it more random */ + srand((double)microtime() * 1000000); + + $thisidentifier=rand()%256; + + $length=4+ // header + 16+ // auth code + 6+ // service type + 2+strlen($username)+ // username + 2+strlen($nasHostname[0])+ // nasIdentifier + 6+ // nasPort + 6+ // nasPortType + 6+ // Acct Status Type + 6+ // Acct RADIUS Authenticated + 2+strlen($sessionid)+ // Acct SessionID + 6+ // Acct terminate + 6+ // Session time + 6+ // input bytes + 6+ // input packets + 6+ // input gigawords + 6+ // output bytes + 6+ // output packets + 6+ // output gigawords + 2+strlen($calledstationid)+ //Called-Station-ID + 2+strlen($callingstationid)+ //Calling-Station-ID + 6+ //nas-IP-Address + 6; //Framed-IP-Address + + if ($interimupdate) + $acctstatustype = 3; + else + $acctstatustype = 2; + + // v v v v v v v v v 1 1 1 1 1 1 1 1 1 v + // Line # 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 E + $data=pack("CCCCNNNNCCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCNCCNCCNCCNCCNCCNCCNCCNCCa*CCa*CCCCCCCCCCCC", + 4,$thisidentifier,$length/256,$length%256, // header + 0,0,0,0, // authcode + 6,6,0,0,0,1, // service type + 1,2+strlen($username),$username, // username + 32,2+strlen($nasHostname[0]),$nasHostname[0], // nasIdentifier + 5,6,0,0,0,$nas_port, // nasPort + 61,6,0,0,0,15, // nasPortType = Ethernet + 40,6,0,0,0,$acctstatustype, // Acct Status Type + 45,6,0,0,0,1, // Acct RADIUS Authenticated + 44,2+strlen($sessionid),$sessionid, // Acct Session ID + 49,6,$radius_term_cause, // Acct Terminate = User Request + 46,6,time() - $start_time, // Session Time + 42,6,$input_bytes, // Input Octets + 47,6,$input_pkts, // Input Packets + 52,6,$input_gigawords, // Input Gigawords + 43,6,$output_bytes, // Output Octets + 48,6,$output_pkts, // Output Packets + 53,6,$output_gigawords, // Output Gigawords + 30,2+strlen($calledstationid),$calledstationid, //Called-Station-ID + 31,2+strlen($callingstationid),$callingstationid, //Calling-Station-ID + 4,6,$nas_ip_exp[0],$nas_ip_exp[1],$nas_ip_exp[2],$nas_ip_exp[3], //nas-IP-Address + 8,6,$ip_exp[0],$ip_exp[1],$ip_exp[2],$ip_exp[3] //Framed-IP-Address + ); + + /* Generate Accounting Request Authenticator */ + $RA = md5($data.$radiuskey) ; + + // v v v v v v v v v 1 1 1 1 1 1 1 1 1 v + // Line # 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 E + $data=pack("CCCCH*CCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCNCCNCCNCCNCCNCCNCCNCCNCCa*CCa*CCCCCCCCCCCC", + 4,$thisidentifier,$length/256,$length%256, // header + $RA, // authcode + 6,6,0,0,0,1, // service type + 1,2+strlen($username),$username, // username + 32,2+strlen($nasHostname[0]),$nasHostname[0], // nasIdentifier + 5,6,0,0,0,$nas_port, // nasPort + 61,6,0,0,0,15, // nasPortType = Ethernet + 40,6,0,0,0,$acctstatustype, // Acct Status Type + 45,6,0,0,0,1, // Acct RADIUS Authenticated + 44,2+strlen($sessionid),$sessionid, // Acct Session ID + 49,6,$radius_term_cause, // Acct Terminate = User Request + 46,6,time() - $start_time, // Session Time + 42,6,$input_bytes, // Input Octets + 47,6,$input_pkts, // Input Packets + 52,6,$input_gigawords, // Input Gigawords + 43,6,$output_bytes, // Output Octets + 48,6,$output_pkts, // Output Packets + 53,6,$output_gigawords, // Output Gigawords + 30,2+strlen($calledstationid),$calledstationid, //Called-Station-ID + 31,2+strlen($callingstationid),$callingstationid, //Calling-Station-ID + 4,6,$nas_ip_exp[0],$nas_ip_exp[1],$nas_ip_exp[2],$nas_ip_exp[3], //nas-IP-Address + 8,6,$ip_exp[0],$ip_exp[1],$ip_exp[2],$ip_exp[3] //Framed-IP-Address + ); + + if($debug) { + echo "username is $username with len " . strlen($username) ."\n" ; + echo "nasHostname is {$nasHostname[0]} with len " . strlen($nasHostname[0]) ."\n" ; + } + + $ret = fwrite($fd,$data) ; + if( !$ret || ($ret != $length) ) + return 1; /* error return */ + + if ($debug) + echo "
writing $length bytes
\n"; + + $readdata = fgets($fd,2) ; /* read 1 byte */ + $status = socket_get_status($fd) ; + fclose($fd) ; + + if($status['timed_out']) + $retvalue = 1 ; + else + $retvalue = ord($readdata) ; + + return $retvalue ; + // 5 -> Accounting-Response + // See RFC2866 for this. +} + +function gigawords($bytes) { + + /* We use BCMath functions since normal integers don't work with so large numbers */ + $gigawords = bcdiv( bcsub( $bytes, remainder($bytes) ) , 2147483647) ; + + return $gigawords; +} + +function remainder($bytes) { + + /* Calculate the bytes we are going to send to the radius. */ + $bytes = bcmod($bytes, 2147483647); + + return $bytes; +} + + +?> diff --git a/captiveportal/radius_accounting_v2.inc b/captiveportal/radius_accounting_v2.inc new file mode 100644 index 0000000..193bfaa --- /dev/null +++ b/captiveportal/radius_accounting_v2.inc @@ -0,0 +1,237 @@ + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This code cannot simply be copied and put under the GNU Public License or +any other GPL-like (LGPL, GPL2) License. + + This code is made possible thx to samples made by Michael Bretterklieber + author of the PHP PECL Radius package + + Changes made include: + * Porting to M0n0wall environment + * Sends NAS-IP-Address AND Nas-Identifier (first word of hostname) in Accounting request + * Sending of Framed-IP-Address (client IP) + * Sending of Called-Station-ID (NAS IP) + * Sending of Calling-Station-ID (client IP) + * RADIUS Extensions (RFC2869) => Acct-(Input|Output)-Gigawords + * TODO implementation of different Acct-Terminate-Cause (Disconnect reason) (should be changed in index.php) + +*/ + +/* +RADIUS ACCOUNTING START +----------------------- +*/ + +function RADIUS_ACCOUNTING_START($username,$sessionid,$radiusip,$radiusport,$radiuskey,$clientip) { + global $debug; + + exec("/bin/hostname", $nasHostname) ; + if(!$nasHostname[0]) + $nasHostname[0] = "m0n0wall" ; + + $nas_ip_address = get_nas_ip(); + + if(!isset($clientip)) { + //if there's no client ip, we'll need to use the NAS ip + $clientip=$nas_ip_address; + } + + +$racct = new Auth_RADIUS_Acct_Start; +$racct->addServer($radiusip, $radiusport, $radiuskey); +/* Different Authentication options + RADIUS_AUTH_RADIUS => authenticated via Radius + RADIUS_AUTH_LOCAL => authenicated local + RADIUS_AUTH_REMOTE => authenticated remote +*/ + +$racct->authentic = RADIUS_AUTH_RADIUS; +$racct->username = $username; +$status = $racct->start(); +if(PEAR::isError($status)) { + if ($debug) + printf("Radius start: %s
\n", $status->getMessage()); + exit; +} + +/* +NAS_PORT_TYPE, int => RADIUS_ETHERNET (15), RADIUS_WIRELESS_OTHER (18), RADIUS_WIRELESS_IEEE_802_11 (19) +NAS_IDENTIFIER, int => should be int but nasHostname[0] returns string +*/ + +$racct->putAttribute(RADIUS_SERVICE_TYPE, RADIUS_LOGIN); +$racct->putAttribute(RADIUS_NAS_PORT, 0); +$racct->putAttribute(RADIUS_NAS_PORT_TYPE, RADIUS_ETHERNET); +//$racct->putAttribute(RADIUS_NAS_IDENTIFIER, $nasHostname[0]); +$racct->putAttribute(RADIUS_NAS_IP_ADDRESS, $nas_ip_address); +$racct->putAttribute(RADIUS_ACCT_SESSION_ID, $sessionid); +$racct->putAttribute(RADIUS_FRAMED_IP_ADDRESS, $clientip); +$result = $racct->send(); +if (PEAR::isError($result)) { + $retvalue = 1; +if ($debug) + printf("Radius send failed: %s
\n", $result->getMessage()); +} else if ($result === true) { + $retvalue = 5 ; + if ($debug) + printf("Radius Accounting succeeded
\n") ; +} else { + $retvalue = 1 ; + if ($debug) + printf("Radius Accounting rejected
\n") ; +} + +$racct->close(); + +return $retvalue ; + +} + +/* +RADIUS ACCOUNTING STOP/UPDATE +----------------------------- +*/ + +p +function RADIUS_ACCOUNTING_STOP($ruleno,$username,$sessionid,$start_time,$radiusip,$radiusport,$radiuskey,$clientip,$interimupdate=false,$radius_term_cause = "RADIUS_TERM_IDLE_TIMEOUT") { + global $debug; + + exec("/bin/hostname", $nasHostname) ; + if(!$nasHostname[0]) + $nasHostname[0] = "quewall" ; + + $input_pkts = $input_bytes = $input_gigawords = $output_pkts = $output_bytes = $output_gigawords = 0 ; + + exec("/sbin/ipfw show {$ruleno}", $ipfw) ; + preg_match("/(\d+)\s+(\d+)\s+(\d+)\s+skipto/", $ipfw[0], $matches) ; + $input_pkts = $matches[2] ; + $input_bytes = remainder($matches[3]); + $input_gigawords = gigawords($matches[3]); + + unset($matches) ; + preg_match("/(\d+)\s+(\d+)\s+(\d+)\s+skipto/", $ipfw[1], $matches) ; + $output_pkts = $matches[2] ; + $output_bytes = remainder($matches[3]); + $output_gigawords = gigawords($matches[3]); + + $nas_ip_address = get_nas_ip(); + + if(!isset($clientip)) { + //if there's no client ip, we'll need to use the NAS ip + $clientip=$nas_ip_address; + } + + if ($debug) + echo "
radius-port: $radiusport
radius-host: $radiusip
username: $username
\n"; + + + // See if we should use Accounting Interim Updates or Accounting STOP messages + if ($interimupdate) + $racct = new_Auth_RADIUS_Acct_Update; + else + $racct = new_Auth_RADIUS_Acct_Stop; + +// Construct data package +$racct->addServer($radiusip, $radiusport, $radiuskey); +$racct->username = $username; +$racct->session_time = time() - $start_time; +$status = $racct->start(); +if(PEAR::isError($status)) { + if ($debug) + printf("Radius start: %s
\n", $status->getMessage()); + exit; +} +// you can put any additional attributes here +//$racct->putAttribute(RADIUS_SERVICE_TYPE, RADIUS_LOGIN); +//$racct->putAttribute(RADIUS_NAS_IDENTIFIER, $nasHostname[0]); +$racct->putAttribute(RADIUS_NAS_IP_ADDRESS, $nas_ip_address); +$racct->putAttribute(RADIUS_ACCT_SESSION_ID, $sessionid); +$racct->putAttribute(RADIUS_FRAMED_IP_ADDRESS, $clientip); +$racct->putAttribute(RADIUS_CALLING_STATION_ID, $clientip); +$racct->putAttribute(RADIUS_CALLED_STATION_ID, $nas_ip_address); +$racct->putAttribute(RADIUS_ACCT_INPUT_PACKETS, $input_pkts); +$racct->putAttribute(RADIUS_ACCT_INPUT_OCTETS, $input_bytes); +$racct->putAttribute(RADIUS_ACCT_INPUT_GIGAWORDS, $input_gigawords); +$racct->putAttribute(RADIUS_ACCT_OUTPUT_PACKETS, $output_pkts); +$racct->putAttribute(RADIUS_ACCT_OUTPUT_OCTETS, $output_bytes); +$racct->putAttribute(RADIUS_ACCT_OUTPUT_GIGAWORDS, $output_gigawords); +if (!$interimupdate) +$racct->putAttribute(RADIUS_ACCT_TERMINATE_CAUSE, $radius_term_cause); + +$result = $racct->send(); +if (PEAR::isError($result)) { + $retvalue = 1; + if ($debug) + printf("Radius send failed: %s
\n", $result->getMessage()); +} else if ($result === true) { + $retvalue = 5 ; + if ($debug) + printf("Radius Accounting succeeded
\n"); +} else { + $retvalue = 1 ; + if ($debug) + printf("Radius Accounting rejected
\n"); +} + +$racct->close(); + +return $retvalue ; +// 5 -> Accounting-Response +// See RFC2866 for this. + +} + +function get_nas_ip() { + global $config; + + /* static WAN IP address */ + return $config['interfaces']['wan']['ipaddr']; +} + +function gigawords($bytes) { + /* We use BCMath functions since normal integers don't work */ + $gigawords = bcdiv( bcsub( $bytes, remainder($bytes) ) , 4294967295); + + return $gigawords; +} + +function remainder($bytes) { + /* Calculate the remainder */ + $bytes = bcmod($bytes, 4294967295); + + return $bytes; +} + + + +?> diff --git a/captiveportal/radius_authentication_nas_ip.inc b/captiveportal/radius_authentication_nas_ip.inc new file mode 100644 index 0000000..774ffce --- /dev/null +++ b/captiveportal/radius_authentication_nas_ip.inc @@ -0,0 +1,219 @@ + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This code cannot simply be copied and put under the GNU Public License or +any other GPL-like (LGPL, GPL2) License. + + This code is made possible thx to samples made by Michael Bretterklieber + author of the PHP PECL Radius package + + $Id_jdg: 2005/11/08 20:42 + + Changes made include: + * Support for multiple radius servers + * Error Message and Reply Message + * Called-Station-Id,Calling-Station-Id,NAS-Port,NAS-Port-Type,NAS-Ip-Address + * Different Authentication Methods + +*/ + +require_once("radius.inc"); + +/* +RADIUS AUTHENTICATION +--------------------- +*/ + +function RADIUS_AUTHENTICATION($username,$password,$radiusservers,$clientip,$clientmac,$ruleno,$auth_type = "PAP") { + global $config, $debug; + + /* Initialisation of variables */ + $retvalue = array(); + $retvalue['error'] = $retvalue['reply_message'] = $retvalue['url_redirection'] = null; + $retvalue['session_timeout'] = 0; + $nas_ip = get_nas_ip(); + $nas_mac = get_interface_mac($config['interfaces']['wan']['if']); + $nas_port = $ruleno - 10000; + $radiusvendor = $config['captiveportal']['radiusvendor'] ? $config['captiveportal']['radiusvendor'] : null; + +/* +Possible Authentication methods +$auth_type = 'PAP'; +$auth_type = 'CHAP_MD5'; +$auth_type = 'MSCHAPv1'; +$auth_type = 'MSCHAPv2'; +*/ + + exec("/bin/hostname", $nasHostname) ; + if(!$nasHostname[0]) + $nasHostname[0] = "m0n0wall" ; + +$classname = 'Auth_RADIUS_' . $auth_type; +$rauth = new $classname($username, $password); + +/* +Add support for more then one radiusserver. +At most 10 servers may be specified. +When multiple servers are given, they are tried in round-robin fashion until a valid response is received +*/ + +foreach ($radiusservers as $radsrv) { + + // Add a new server to our instance + $rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['key']); + +} + +$rauth->username = $username; + +switch($auth_type) { +case 'CHAP_MD5': +case 'MSCHAPv1': + $classname = $auth_type == 'MSCHAPv1' ? 'Crypt_CHAP_MSv1' : 'Crypt_CHAP_MD5'; + $crpt = new $classname; + $crpt->password = $password; + $rauth->challenge = $crpt->challenge; + $rauth->chapid = $crpt->chapid; + $rauth->response = $crpt->challengeResponse(); + $rauth->flags = 1; + break; + +case 'MSCHAPv2': + $crpt = new Crypt_CHAP_MSv2; + $crpt->username = $username; + $crpt->password = $password; + $rauth->challenge = $crpt->authChallenge; + $rauth->peerChallenge = $crpt->peerChallenge; + $rauth->chapid = $crpt->chapid; + $rauth->response = $crpt->challengeResponse(); + break; + +default: + $rauth->password = $password; + break; +} + + +if (!$rauth->start()) { + $retvalue['auth_val'] = 1; + $retvalue['error'] = $rauth->getError(); + if ($debug) + printf("Radius start: %s
\n", $retvalue['error']); +} +else { + + // 1 -> Access-Request => We will use this value as an error indicator since we can't get a 1 back from the radius + // 2 -> Access-Accept + // 3 -> Access-Reject + // See RFC2865 for this. + + /* + * We put our attributes in here + */ + + switch($radiusvendor) { + + case 'cisco': + $rauth->putAttribute(RADIUS_CALLED_STATION_ID, $clientmac); + $rauth->putAttribute(RADIUS_CALLING_STATION_ID, $clientip); + break; + + default: + $rauth->putAttribute(RADIUS_CALLED_STATION_ID, $nas_mac); + $rauth->putAttribute(RADIUS_CALLING_STATION_ID, $clientmac); + break; + } + + // Default attributes + $rauth->putAttribute(RADIUS_NAS_IP_ADDRESS, $nas_ip, "addr"); + $rauth->putAttribute(RADIUS_NAS_PORT, $nas_port); + + // Send request + + $result = $rauth->send(); + if (PEAR::isError($result)) { + $retvalue['auth_val'] = 1; + $retvalue['error'] = $result->getMessage(); + if ($debug) + printf("Radius send failed: %s
\n", $retvalue['error']); + } else if ($result === true) { + $retvalue['auth_val'] = 2; + if ($debug) + printf("Radius Auth succeeded
\n"); + } else { + $retvalue['auth_val'] = 3; + if ($debug) + printf("Radius Auth rejected
\n"); + } + + // Get attributes, even if auth failed. + // We will push the results in the retvalue array + if (!$rauth->getAttributes()) { + $retvalue['error'] = $rauth->getError(); + if ($debug) + printf("Radius getAttributes: No attributes
\n", $retvalue['error']); + } else { + $retvalue = array_merge($retvalue,$rauth->listAttributes()); + if ($debug) { + if (!$rauth->listAttributes()) + printf("No Attributes
\n"); + else + print_r($rauth->listAttributes()); + } + } + } + + // close OO RADIUS_AUTHENTICATION + $rauth->close(); + + return $retvalue; + +} + +function get_nas_ip() { + global $config; + + /* static WAN IP address */ + return $config['interfaces']['wan']['ipaddr']; +} + +function get_interface_mac($interface) { + + /* build interface list with netstat */ + exec("/usr/bin/netstat -I $interface -nW -f link", $linkinfo); + array_shift($linkinfo); + $alink = preg_split("/\s+/", $linkinfo[0]); + $mac = chop($alink[3]); + return $mac; +} + + +?>