From 480d71dc6b0d7427566c5abf6bd41b2e5d9e6ff7 Mon Sep 17 00:00:00 2001 From: Scott Ullrich Date: Tue, 8 Mar 2005 18:28:30 +0000 Subject: Sync with 1.2b6 which would extended radius patch requires. --- usr/local/captiveportal/radius_accounting.inc | 80 ++++++++---- usr/local/captiveportal/radius_authentication.inc | 152 ++++++++++++++++++++-- 2 files changed, 191 insertions(+), 41 deletions(-) (limited to 'usr') diff --git a/usr/local/captiveportal/radius_accounting.inc b/usr/local/captiveportal/radius_accounting.inc index 398af92..1aac92d 100644 --- a/usr/local/captiveportal/radius_accounting.inc +++ b/usr/local/captiveportal/radius_accounting.inc @@ -26,10 +26,16 @@ 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) */ -function RADIUS_ACCOUNTING_START($username,$sessionid,$port_type,$stationid,$ipaddr,$portalmac,$radiusip,$radiusport,$radiuskey) { +function RADIUS_ACCOUNTING_START($username,$sessionid,$radiusip,$radiusport,$radiuskey,$clientip) { $sharedsecret=$radiuskey ; # $debug = 1 ; @@ -44,6 +50,14 @@ function RADIUS_ACCOUNTING_START($username,$sessionid,$port_type,$stationid,$ipa /* set 5 second timeout on socket i/o */ stream_set_timeout($fd, 5) ; + $nas_ip_address=get_current_wan_address(); + + if(!isset($clientip)) { + //if there's no client ip, we'll need to use the NAS ip + $clientip=get_current_wan_address(); + } + $ip_exp=explode(".",$clientip); + if ($debug) echo "
radius-port: $radiusport
radius-host: $radiusip
username: $username
\n"; @@ -59,53 +73,47 @@ function RADIUS_ACCOUNTING_START($username,$sessionid,$port_type,$stationid,$ipa 6+ // Acct Status Type 6+ // Acct RADIUS Authenticated 2+strlen($sessionid)+ // Acct SessionID - 2+strlen($stationid)+ // Calling-Station-Id - 2+strlen($portalmac)+ // Called-Station-Id 6; // Framed-IP-Address - // v v v v v v v v v 1 1 1 v - // Line # 1 2 3 4 5 6 7 8 9 0 1 2 E - $data=pack("CCCCNNNNCCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCa*CCa*CCN", + // 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*CCCCCC", 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,0, // nasPort - 61,6,0,0,0,$port_type, // nasPortType + 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 - 31,2+strlen($stationid),$stationid, // Calling Station - 30,2+strlen($portalmac),$portalmac, // Called Station - 8,6,ip2long($ipaddr) // Framed-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 v - // Line # 1 2 3 4 5 6 7 8 9 0 1 2 E - $data=pack("CCCCH*CCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCa*CCa*CCN", + // 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*CCCCCC", 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,0, // nasPort - 61,6,0,0,0,$port_type, // nasPortType + 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 - 31,2+strlen($stationid),$stationid, // Calling Station - 30,2+strlen($portalmac),$portalmac, // Called Station - 8,6,ip2long($ipaddr) // Framed-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) ) @@ -123,18 +131,20 @@ function RADIUS_ACCOUNTING_START($username,$sessionid,$port_type,$stationid,$ipa else $retvalue = ord($readdata) ; + syslog(LOG_INFO,"Sent Accounting-Request Start packet to RADIUS for $username"); + return $retvalue ; // 5 -> Accounting-Response // See RFC2866 for this. } -function RADIUS_ACCOUNTING_STOP($ruleno,$username,$sessionid,$start_time,$port_type,$radiusip,$radiusport,$radiuskey) { +function RADIUS_ACCOUNTING_STOP($ruleno,$username,$sessionid,$start_time,$radiusip,$radiusport,$radiuskey,$clientip) { $sharedsecret=$radiuskey ; # $debug = 1 ; exec("/bin/hostname", $nasHostname) ; if(!$nasHostname[0]) - $nasHostname[0] = "m0n0wall" ; + $nasHostname[0] = "quewall" ; $input_pkts = $input_bytes = $output_pkts = $output_bytes = 0 ; @@ -155,6 +165,14 @@ function RADIUS_ACCOUNTING_STOP($ruleno,$username,$sessionid,$start_time,$port_t /* set 5 second timeout on socket i/o */ stream_set_timeout($fd, 5) ; + $nas_ip_address=get_current_wan_address(); + + if(!isset($clientip)) { + //if there's no client ip, we'll need to use the NAS ip + $clientip=get_current_wan_address(); + } + $ip_exp=explode(".",$clientip); + if ($debug) echo "
radius-port: $radiusport
radius-host: $radiusip
username: $username
\n"; @@ -175,18 +193,20 @@ function RADIUS_ACCOUNTING_STOP($ruleno,$username,$sessionid,$start_time,$port_t 6+ // input bytes 6+ // input packets 6+ // output bytes - 6; // output packets + 6+ // output packets + 2+strlen($nas_ip_address)+ //Called-Station-ID + 2+strlen($clientip); //Calling-Station-ID // v v v v v v v v v 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 E - $data=pack("CCCCNNNNCCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCNCCNCCNCCNCCNCCN", + $data=pack("CCCCNNNNCCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCNCCNCCNCCNCCNCCNCCa*CCa*", 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,0, // nasPort - 61,6,0,0,0,$port_type, // nasPortType + 61,6,0,0,0,15, // nasPortType = Ethernet 40,6,0,0,0,2, // Acct Status Type = Stop 45,6,0,0,0,1, // Acct RADIUS Authenticated 44,2+strlen($sessionid),$sessionid, // Acct Session ID @@ -195,7 +215,9 @@ function RADIUS_ACCOUNTING_STOP($ruleno,$username,$sessionid,$start_time,$port_t 42,6,$input_bytes, // Input Octets 47,6,$input_pkts, // Input Packets 43,6,$output_bytes, // Output Octets - 48,6,$output_pkts // Output Packets + 48,6,$output_pkts, // Output Packets + 30,2+strlen($nas_ip_address),$nas_ip_address, //Called-Station-ID + 31,2+strlen($clientip),$clientip //Calling-Station-ID ); /* Generate Accounting Request Authenticator */ @@ -203,14 +225,14 @@ function RADIUS_ACCOUNTING_STOP($ruleno,$username,$sessionid,$start_time,$port_t // v v v v v v v v v 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 E - $data=pack("CCCCH*CCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCNCCNCCNCCNCCNCCN", + $data=pack("CCCCH*CCCCCCCCa*CCa*CCCCCCCCCCCCCCCCCCCCCCCCCCa*CCNCCNCCNCCNCCNCCNCCa*CCa*", 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,0, // nasPort - 61,6,0,0,0,$port_type, // nasPortType + 61,6,0,0,0,15, // nasPortType = Ethernet 40,6,0,0,0,2, // Acct Status Type = Stop 45,6,0,0,0,1, // Acct RADIUS Authenticated 44,2+strlen($sessionid),$sessionid, // Acct Session ID @@ -219,7 +241,9 @@ function RADIUS_ACCOUNTING_STOP($ruleno,$username,$sessionid,$start_time,$port_t 42,6,$input_bytes, // Input Octets 47,6,$input_pkts, // Input Packets 43,6,$output_bytes, // Output Octets - 48,6,$output_pkts // Output Packets + 48,6,$output_pkts, // Output Packets + 30,2+strlen($nas_ip_address),$nas_ip_address, //Called-Station-ID + 31,2+strlen($clientip),$clientip //Calling-Station-ID ); if($debug) { @@ -243,6 +267,8 @@ function RADIUS_ACCOUNTING_STOP($ruleno,$username,$sessionid,$start_time,$port_t else $retvalue = ord($readdata) ; + syslog(LOG_INFO,"Sent Accounting-Request Stop packet to RADIUS for $username"); + return $retvalue ; // 5 -> Accounting-Response // See RFC2866 for this. diff --git a/usr/local/captiveportal/radius_authentication.inc b/usr/local/captiveportal/radius_authentication.inc index 10a2009..77d263a 100644 --- a/usr/local/captiveportal/radius_authentication.inc +++ b/usr/local/captiveportal/radius_authentication.inc @@ -28,9 +28,33 @@ // was also fixed and patches submitted to Edwin. This bug would // have caused authentication to fail on every access. -function RADIUS_AUTHENTICATION($username,$password,$port_type,$radiusip,$radiusport,$radiuskey) { + // This version of radius_authentication.inc has been modified by + // Rob Parker . Changes made include: + // * move to fread() from fgets() to ensure binary safety + // * ability to read back specific attributes from a + // RADIUS Access-Accept packet + // * these attributes (in this version, Nomadix-Bw-Up and -Down, + // which are Nomadix vendor specific attributes to be passed back + // to index.php of m0n0wall to create dummynet rules for per-user + // radius-based bandwidth restriction. + // * IMPORTANT NOTE: this function no longer returns a simple integer + // of '2' for Access-Accept, and '3' for Access-Deny. It will return + // x/y/z, where x = 2 or 3 (Accept or Deny), y = up bandwidth, if + // enabled in web gui, and z = down bandwidth. These will be empty if + // per user bw is disabled in webgui. + // * these changes are (c) 2004 Keycom PLC. + +function RADIUS_AUTHENTICATION($username,$password,$radiusip,$radiusport,$radiuskey) { + global $config; + + //radius database, hack this if we need to + + $radius_db[1]=="Nomadix-Bw-Up"; + $radius_db[2]=="Nomadix-Bw-Down"; + $radius_db[5]=="Nomadix-Expiration"; + $sharedsecret=$radiuskey ; - # $debug = 1 ; + #$debug = 1 ; exec("/bin/hostname", $nasHostname) ; if(!$nasHostname[0]) @@ -64,6 +88,9 @@ function RADIUS_AUTHENTICATION($username,$password,$port_type,$radiusip,$radiusp 6; // nasPortType $thisidentifier=rand()%256; + + + // v v v v v v v v v // Line # 1 2 3 4 5 6 7 8 E $data=pack("CCCCa*CCCCCCCCa*CCa*CCa*CCCCCCCCCCCC", @@ -74,7 +101,7 @@ function RADIUS_AUTHENTICATION($username,$password,$port_type,$radiusip,$radiusp 2,2+strlen($encryptedpassword),$encryptedpassword, // userpassword 32,2+strlen($nasHostname[0]),$nasHostname[0], // nasIdentifier 5,6,0,0,0,0, // nasPort - 61,6,0,0,0,$port_type // nasPortType + 61,6,0,0,0,15 // nasPortType = Ethernet ); if($debug) { @@ -90,16 +117,113 @@ function RADIUS_AUTHENTICATION($username,$password,$port_type,$radiusip,$radiusp 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 ; + + //RADIUS attributes returned in Access-Accept packet. + + #turn off magic quotes so we're binary-safe on fread. + set_magic_quotes_runtime(0); + $readdata = fread($fd,1024); + $pack_upack = unpack("Ctype/Cuid/nlength/A16resp/A*payload",$readdata); + if($pack_upack[type]==2) { + //only for 'Access-Accept' packets, otherwise throw back the number so error page is shown + $payload_upack = unpack("Cnum/Clen/C*value",$pack_upack[payload]); + $used_upack = $payload_upack; + + while(count($used_upack)>=1) { + //the payload contains two initial packets we need to record (number, and payload) + $attribute_number++; + $packet_type=array_shift($used_upack); //push the type off + $attributes[$attribute_number][]=$packet_type; + $packet_length=array_shift($used_upack); //push the length off + $attributes[$attribute_number][]=$packet_length; + //iterate until the end of this attribute + for($n=1;$n<=$packet_length-2;$n+=1) { + $attributes[$attribute_number][]=array_shift($used_upack); + } + } + + //at this stage, $attribute contains a list of ALL attributes that were sent (well, the first 1kbyte of them anyway, + //change fread above to alter the quantity of data read from the socket. + //we're only interested in two specific nomadix (3309) attributes (1 and 2, Bw-Up and Bw-Down) + + for($n=1;$n<=count($attributes);$n+=1) { + if($attributes[$n][0]=="26") { //VSA attribs + if((($attributes[$n][4]*256)+$attributes[$n][5])=="3309") { //just nomadix + switch($attributes[$n][6]) { //nomadix packet type + //we do this *256 because otherwise we'd need to unpack the packet + //again with a different packet format. which is a waste of time for now. + case "1": + $bw_up = 0; + $bw_up += $attributes[$n][10]*256; + $bw_up += $attributes[$n][11]; + if ($debug) {echo ">>VSA: Nomadix-Bw-Up=" . $bw_up . "kbit\n";} + break; + case "2": + $bw_down = 0; + $bw_down += $attributes[$n][10]*256; + $bw_down += $attributes[$n][11]; + if ($debug) {echo ">>VSA: Nomadix-Bw-Down=" . $bw_down . "kbit\n";} + break; + default: + if ($debug) {echo ">>VSA: Unknown Nomadix Packet (" . $attributes[$n][6] . ")!\n";} + } + } + } + } + //end RADIUS attribute return code. + + $status = socket_get_status($fd) ; + fclose($fd) ; + + if($status['timed_out']) + $retvalue = 1 ; + else + $retvalue = $pack_upack[type]; + + if($debug) { + switch($retvalue) { + case 1: + echo "Socket Failure!\n"; + break; + case 2: + echo "Access-Accept!\n"; + break; + case 3: + echo "Access-Reject!\n"; + break; + default: + echo "Unknown Reply!\n"; + } + } + + //what happens if there's no Nomadix attributes set, but the user has this turned on? + //we give them a default of 64kbit. this should be an option in the webgui too. + if(!isset($bw_up)) { + //go for default bw up + $bw_up==$config['captiveportal']['bwdefaultup']; + if(!isset($bw_up)) { + $bw_up=64; + } + } + if(!isset($bw_down)) { + //go for default bw down + $bw_down==$config['captiveportal']['bwdefaultdn']; + if(!isset($bw_down)) { + $bw_down=64; + } + } + + //whilst we're debugging, we're also going to syslog this + syslog(LOG_INFO,"Authenticated user $username. Setting bandwidth to $bwdown/$bwup KBit/s"); + + return $retvalue . "/" . $bw_up . "/" . $bw_down; + } else { + //we're returning 5kbit/s each way here, but really it doesn't matter + //if it's a 3, it's Access-Reject anyway, so the user will actually get + //nothing at all. :) + syslog(LOG_INFO,"Authentication failed for $username"); + return "3/5/5"; + } // 2 -> Access-Accept // 3 -> Access-Reject // See RFC2865 for this. @@ -125,4 +249,4 @@ function Encrypt($password,$key,$RA) { } return $output; } -?> +?> \ No newline at end of file -- cgit v1.1