mirror of
https://github.com/e107inc/e107.git
synced 2025-08-08 23:56:58 +02:00
Tidy up alt_auth; first cut of radius support (thanks to Cameron K for testing)
This commit is contained in:
226
e107_plugins/alt_auth/radius_auth.php
Normal file
226
e107_plugins/alt_auth/radius_auth.php
Normal file
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
/*
|
||||
+ ----------------------------------------------------------------------------+
|
||||
| e107 website system
|
||||
|
|
||||
| Steve Dunstan 2001-2002
|
||||
| http://e107.org
|
||||
| jalist@e107.org
|
||||
|
|
||||
| Released under the terms and conditions of the
|
||||
| GNU General Public License (http://gnu.org).
|
||||
|
|
||||
| $Source: /cvs_backup/e107_0.8/e107_plugins/alt_auth/radius_auth.php,v $
|
||||
| $Revision: 1.1 $
|
||||
| $Date: 2008-09-02 19:39:12 $
|
||||
| $Author: e107steved $
|
||||
+----------------------------------------------------------------------------+
|
||||
|
||||
RFC2865 is the main RADIUS standard - http://www.faqs.org/rfcs/rfc2865
|
||||
|
||||
Potential enhancements:
|
||||
- Multiple servers (done, but not tested)
|
||||
- Configurable port (probably not necessary)
|
||||
- Configurable timeout
|
||||
- Configurable retries
|
||||
|
||||
Error recfrom: 10054 - winsock error for 'connection reset'
|
||||
*/
|
||||
|
||||
define('RADIUS_DEBUG',TRUE);
|
||||
class auth_login
|
||||
{
|
||||
|
||||
var $server;
|
||||
var $secret;
|
||||
var $port;
|
||||
var $usr;
|
||||
var $pwd;
|
||||
var $ErrorText;
|
||||
var $connection; // Handle to use on successful creation
|
||||
var $result;
|
||||
var $Available;
|
||||
|
||||
function auth_login()
|
||||
{
|
||||
$this->copyAttribs = array();
|
||||
$sql = new db;
|
||||
$sql -> db_Select("alt_auth", "*", "auth_type = 'radius' ");
|
||||
while($row = $sql -> db_Fetch())
|
||||
{
|
||||
$radius[$row['auth_parmname']] = base64_decode(base64_decode($row['auth_parmval']));
|
||||
}
|
||||
$this->server = explode(',',$radius['radius_server']);
|
||||
$this->port = 1812; // Assume fixed port number for now - 1812 (UDP) is listed for servers, 1645 for authentification. (1646, 1813 for accounting)
|
||||
// (A Microsoft app note says 1812 is the RFC2026-compliant port number. (http://support.microsoft.com/kb/230786)
|
||||
// $this->port = 1645;
|
||||
$this->secret = explode(',',$radius['radius_secret']);
|
||||
if ((count($this->server) > 1) && (count($this->secret) == 1))
|
||||
{
|
||||
$this->secret = array();
|
||||
foreach ($this->server as $k => $v)
|
||||
{
|
||||
$this->secret[$k] = $radius['radius_secret']; // Same secret for all servers, if only one entered
|
||||
}
|
||||
}
|
||||
$this->ErrorText = '';
|
||||
if(!function_exists('radius_auth_open'))
|
||||
{
|
||||
$this->Available = FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!$this -> connect())
|
||||
{
|
||||
return AUTH_NOCONNECT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function makeErrorText($extra = '')
|
||||
{
|
||||
$this->ErrorText = $extra.radius_strerror($this->connection) ;
|
||||
if (!RADIUS_DEBUG) return;
|
||||
$text = "<br />Server: {$this->server} Stored secret: ".radius_server_secret($this->connection)." Port: {$this->port}";
|
||||
$this->ErrorText .= $text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function connect()
|
||||
{
|
||||
// Try to connect to a radius server
|
||||
if (!($this->connection = radius_auth_open()))
|
||||
{
|
||||
$this->makeErrorText('RADIUS open failed: ') ;
|
||||
return FALSE;
|
||||
}
|
||||
foreach ($this->server as $k => $s)
|
||||
{
|
||||
if (!radius_add_server($this->connection, $s, $this->port, $this->secret[$k], 15, 1)) // fixed 15 second timeout, one try ATM
|
||||
{
|
||||
$this->makeErrorText('RADIUS add server failed: ') ;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function close()
|
||||
{
|
||||
if ( !radius_close( $this->connection)) // (Not strictly necessary, but tidy)
|
||||
{
|
||||
$this->makeErrorText('RADIUS close error: ') ;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function login($uname, $pass, &$newvals, $connect_only = FALSE)
|
||||
{
|
||||
// Create authentification request
|
||||
if (!radius_create_request($this->connection,RADIUS_ACCESS_REQUEST))
|
||||
{
|
||||
$this->makeErrorText('RADIUS failed authentification request: ') ;
|
||||
return AUTH_NOCONNECT;
|
||||
}
|
||||
|
||||
if (trim($pass) == '') return AUTH_BADPASSWORD; // Pick up a blank password - always expect one
|
||||
|
||||
// Attach username and password
|
||||
if (!radius_put_attr($this->connection,RADIUS_USER_NAME,$uname)
|
||||
|| !radius_put_attr($this->connection,RADIUS_USER_PASSWORD,$pass))
|
||||
{
|
||||
$this->makeErrorText('RADIUS could not attach username/password: ') ;
|
||||
return AUTH_NOCONNECT;
|
||||
}
|
||||
|
||||
// Finally, send request to server
|
||||
switch (radius_send_request($this->connection))
|
||||
{
|
||||
case RADIUS_ACCESS_ACCEPT : // Valid username/password
|
||||
break;
|
||||
case RADIUS_ACCESS_CHALLENGE : // CHAP response required - not currently implemented
|
||||
$this->makeErrorText('CHAP not supported');
|
||||
return AUTH_NOUSER;
|
||||
case RADIUS_ACCESS_REJECT : // Specifically rejected
|
||||
default: // Catch-all
|
||||
$this->makeErrorText('RADIUS validation error: ') ;
|
||||
return AUTH_NOUSER;
|
||||
}
|
||||
|
||||
// User accepted here.
|
||||
|
||||
if ($connect_only) return AUTH_SUCCESS;
|
||||
return AUTH_SUCCESS; // Not interested in any attributes returned ATM, so done.
|
||||
|
||||
|
||||
|
||||
// See if we get any attributes - not really any use to us unless we implement CHAP, so disabled ATM
|
||||
$attribs = array();
|
||||
while ($resa = radius_get_attr($this->connection))
|
||||
{
|
||||
if (!is_array($resa))
|
||||
{
|
||||
$this->makeErrorText("Error getting attribute: ");
|
||||
exit;
|
||||
}
|
||||
// Decode attribute according to type (this isn't an exhaustive list)
|
||||
// Codes: 2, 3, 4, 5, 30, 31, 32, 60, 61 should never be received by us
|
||||
// Codes 17, 21 not assigned
|
||||
switch ($resa['attr'])
|
||||
{
|
||||
case 8 : // IP address to be set (255.255.255.254 indicates 'allocate your own address')
|
||||
case 9 : // Subnet mask
|
||||
case 14 : // Login-IP host
|
||||
$attribs[$resa['attr']] = radius_cvt_addr($resa['data']);
|
||||
break;
|
||||
case 6 : // Service type (integer bitmap)
|
||||
case 7 : // Protocol (integer bitmap)
|
||||
case 10 : // Routing method (integer)
|
||||
case 12 : // Framed MTU
|
||||
case 13 : // Compression method
|
||||
case 15 : // Login service (bitmap)
|
||||
case 16 : // Login TCP port
|
||||
case 23 : // Framed IPX network (0xFFFFFFFE indicates 'allocate your own')
|
||||
case 27 : // Session timeout - maximum connection/login time in seconds
|
||||
case 28 : // Idle timeout in seconds
|
||||
case 29 : // Termination action
|
||||
case 37 : // AppleTalk link number
|
||||
case 38 : // AppleTalk network
|
||||
case 62 : // Max ports
|
||||
case 63 : // Login LAT port
|
||||
$attribs[$resa['attr']] = radius_cvt_int($resa['data']);
|
||||
break;
|
||||
case 1 : // User name
|
||||
case 11 : // Filter ID - could get several of these
|
||||
case 18 : // Reply message (text, various purposes)
|
||||
case 19 : // Callback number
|
||||
case 20 : // Callback ID
|
||||
case 22 : // Framed route - could get several of these
|
||||
case 24 : // State - used in CHAP
|
||||
case 25 : // Class
|
||||
case 26 : // Vendor-specific
|
||||
case 33 : // Proxy State
|
||||
case 34 : // Login LAT service
|
||||
case 35 : // Login LAT node
|
||||
case 36 : // Login LAT group
|
||||
case 39 : // AppleTalk zone
|
||||
default :
|
||||
$attribs[$resa['attr']] = radius_cvt_string($resa['data']); // Default to string type
|
||||
}
|
||||
printf("Got Attr: %d => %d Bytes %s\n", $resa['attr'], strlen($attribs[$resa['attr']]), $attribs[$resa['attr']]);
|
||||
}
|
||||
|
||||
return AUTH_SUCCESS;
|
||||
}
|
||||
}
|
||||
?>
|
Reference in New Issue
Block a user