]> git.gsnw.org Git - m0n0chwall.git/commitdiff
Adding of DRAFT!!! files for NAS-IP and new radius_accounting_v2.inc.
authorjdegraeve <jdegraeve@e36fee2c-cc09-0410-a7cc-ebac5c6737de>
Tue, 7 Feb 2006 15:43:57 +0000 (15:43 +0000)
committerjdegraeve <jdegraeve@e36fee2c-cc09-0410-a7cc-ebac5c6737de>
Tue, 7 Feb 2006 15:43:57 +0000 (15:43 +0000)
git-svn-id: https://svn.m0n0.ch/wall/trunk@53 e36fee2c-cc09-0410-a7cc-ebac5c6737de

captiveportal/radius_accounting_nas_ip.inc [new file with mode: 0644]
captiveportal/radius_accounting_v2.inc [new file with mode: 0644]
captiveportal/radius_authentication_nas_ip.inc [new file with mode: 0644]

diff --git a/captiveportal/radius_accounting_nas_ip.inc b/captiveportal/radius_accounting_nas_ip.inc
new file mode 100644 (file)
index 0000000..720879a
--- /dev/null
@@ -0,0 +1,358 @@
+<?php
+/*
+
+$Id$
+
+       radius_accounting.inc
+       part of m0n0wall (http://m0n0.ch/wall)
+       
+       Copyright (C) 2004 Dinesh Nair <dinesh@alphaque.com>
+       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 <rob.parker@keycom.co.uk>. 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 <jonathan@imelda.be>. 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 "<br>radius-port: $radiusport<br>radius-host: $radiusip<br>username: $username<hr>\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 "<br>writing $length bytes<hr>\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 "<br>radius-port: $radiusport<br>radius-host: $radiusip<br>username: $username<hr>\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 "<br>writing $length bytes<hr>\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 (file)
index 0000000..193bfaa
--- /dev/null
@@ -0,0 +1,237 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+/*
+
+$Id$
+
+Copyright (c) 2006, Jonathan De Graeve <jonathan.de.graeve@imelda.be>
+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 <michael@bretterklieber.com>
+    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<br>\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<br>\n", $result->getMessage());
+} else if ($result === true) {
+    $retvalue = 5 ;
+    if ($debug)
+    printf("Radius Accounting succeeded<br>\n") ;
+} else {
+    $retvalue = 1 ;
+    if ($debug)
+    printf("Radius Accounting rejected<br>\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 "<br>radius-port: $radiusport<br>radius-host: $radiusip<br>username: $username<hr>\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<br>\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<br>\n", $result->getMessage());
+} else if ($result === true) {
+    $retvalue = 5 ;
+    if ($debug)
+    printf("Radius Accounting succeeded<br>\n");
+} else {
+    $retvalue = 1 ;
+    if ($debug)
+    printf("Radius Accounting rejected<br>\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 (file)
index 0000000..774ffce
--- /dev/null
@@ -0,0 +1,219 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+/*
+$Id$
+
+Copyright (c) 2005, Jonathan De Graeve <jonathan.de.graeve@imelda.be>
+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 <michael@bretterklieber.com>
+    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<br>\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<br>\n", $retvalue['error']);
+       } else if ($result === true) {
+           $retvalue['auth_val'] = 2;
+           if ($debug)
+           printf("Radius Auth succeeded<br>\n");
+       } else {
+           $retvalue['auth_val'] = 3;
+           if ($debug)
+           printf("Radius Auth rejected<br>\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<br>\n", $retvalue['error']);
+       } else {
+           $retvalue = array_merge($retvalue,$rauth->listAttributes());
+           if ($debug) {
+               if (!$rauth->listAttributes())
+                   printf("No Attributes<br>\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;
+}
+
+
+?>