// for use in the m0n0wall distribution http://m0n0.ch/wall/
//
// Changes include moving from raw sockets to fsockopen
// and the removal of dependency on external conf file
// An existing bug which resulted in a malformed RADIUS packet
// was also fixed and patches submitted to Edwin. This bug would
// have caused authentication to fail on every access.
function RADIUS_AUTHENTICATION($username,$password,$radiusip,$radiusport,$radiuskey) {
$sharedsecret=$radiuskey ;
# $debug = 1 ;
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) ;
if ($debug)
echo "
radius-port: $radiusport
radius-host: $radiusip
username: $username
\n";
$RA=pack("CCCCCCCCCCCCCCCC", // auth code
1+rand()%255, 1+rand()%255, 1+rand()%255, 1+rand()%255,
1+rand()%255, 1+rand()%255, 1+rand()%255, 1+rand()%255,
1+rand()%255, 1+rand()%255, 1+rand()%255, 1+rand()%255,
1+rand()%255, 1+rand()%255, 1+rand()%255, 1+rand()%255);
$encryptedpassword=Encrypt($password,$sharedsecret,$RA);
$length=4+ // header
16+ // auth code
6+ // service type
2+strlen($username)+ // username
2+strlen($encryptedpassword)+ // userpassword
2+strlen($nasHostname[0])+ // nasIdentifier
6+ // nasPort
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",
1,$thisidentifier,$length/256,$length%256, // header
$RA, // authcode
6,6,0,0,0,1, // service type
1,2+strlen($username),$username, // username
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,15 // nasPortType = Ethernet
);
if($debug) {
echo "username is $username with len " . strlen($username) ."\n" ;
echo "encryptedpassword is $encryptedpassword with len " . strlen($encryptedpassword) ."\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 ;
// 2 -> Access-Accept
// 3 -> Access-Reject
// See RFC2865 for this.
}
function Encrypt($password,$key,$RA) {
global $debug;
$keyRA=$key.$RA;
if ($debug)
echo "
key: $key
password: $password
\n";
$md5checksum=md5($keyRA);
$output="";
for ($i=0;$i<=15;$i++) {
if (2*$i>strlen($md5checksum)) $m=0; else $m=hexdec(substr($md5checksum,2*$i,2));
if ($i>strlen($keyRA)) $k=0; else $k=ord(substr($keyRA,$i,1));
if ($i>strlen($password)) $p=0; else $p=ord(substr($password,$i,1));
$c=$m^$p;
$output.=chr($c);
}
return $output;
}
?>