auth:radius
This is an old revision of the document!
Table of Contents
RADIUS Authentication Backend
Radius is a authentication and accounting protocol for large departments, somehow similar to LDAP. If your department uses RADIUS to manage accounts, you can reuse that accounts for your dokuwiki.
Requirements
- a radius server: host, port, sharedsecret
- perl (depends on distribution, could be part of the php-pear package)
- phpize (depends on distribution, could be part of the php-devel package)
- php radius extension. To install use
# pear install pecl/radius
Code
Save this under …/dokuwiki/inc/auth/radius.class.php:
<?php /** * RADIUS authentication backend * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Sebastian Menge <bastl@users.sf.net> */ define('DOKU_AUTH', dirname(__FILE__)); require_once(DOKU_AUTH.'/plain.class.php'); // FIXME: needed? // we only accept page ids for auth_plain //if(isset($_REQUEST['u'])) // $_REQUEST['u'] = cleanID($_REQUEST['u']); //if(isset($_REQUEST['acl_user'])) // $_REQUEST['acl_user'] = cleanID($_REQUEST['acl_user']); //// the same goes for password reset requests //if(isset($_POST['login'])){ // $_POST['login'] = cleanID($_POST['login']); //} // FIXME: better way to do this? must we support windows? //load radius extension if required if(!extension_loaded('radius')) { if (preg_match('/windows/i', getenv('OS'))) { dl('php_radius.dll'); } else { dl('radius.so'); } } class auth_radius extends auth_plain { /** * handle to the radius server */ var $radius = null; /** * radius config */ var $cnf = null; /** * Constructor * * Carry out sanity checks to ensure the object is * able to operate. Sets no capabilities because we only auhtenticate via radius * * @author Sebastian Menge <bastl@users.sf.net> */ function auth_radius() { parent::auth_plain(); global $conf; $this->cnf = $conf['auth']['radius']; // radius extension is needed if(!function_exists('radius_add_server')) { if ($this->cnf['debug']) msg("Radius err: PHP radius extension not found.",-1,__LINE__,__FILE__); $this->success = false; return; } // FIXME: defaults like this: (e.g. localhost:1812) // if(empty($this->cnf['groupkey'])) $this->cnf['groupkey'] = 'cn'; // get parameters from config $host = $this->cnf['host']; $port = $this->cnf['port']; $secret = $this->cnf['secret']; $timeout = $this->cnf['timeout']; $tries = $this->cnf['tries']; //create handle and add server $this->radius = radius_auth_open(); //try to connect if (!radius_add_server($this->radius,$host,$port,$secret,$timeout,$tries)){ msg("Radius err: ". radius_strerror($this->radius),-1,__LINE__,__FILE__); $this->success = false; return; } // set additional capabilities $this->cando['modLogin'] = false; $this->cando['modPass'] = false; // $this->cando['external'] = true; // does the module do external auth checking? // $this->cando['logoff'] = false; // has the module some special logoff method? return; } /** * Check user+password [required auth function] * * Checks if the given user exists and the given * plaintext password is correct * * @author Sebastian Menge <bastl@users.sf.net> * @return bool */ function checkPass($user,$pass){ if (! radius_create_request($this->radius,RADIUS_ACCESS_REQUEST)) { msg("Radius err: ". radius_strerror($this->radius),-1,__LINE__,__FILE__); } radius_put_attr($this->radius,RADIUS_USER_NAME,$user); radius_put_attr($this->radius,RADIUS_USER_PASSWORD,$pass); //send the actual request and return result switch (radius_send_request($this->radius)) { case RADIUS_ACCESS_ACCEPT: $data = $this->getUserData($user); return true; break; case RADIUS_ACCESS_REJECT: return false; break; case RADIUS_ACCESS_CHALLENGE: //msg("Radius: CHAP not supported by auth_radius.",-1); return false; break; default: msg('Radius Error: ('.$user.') ' . radius_strerror($this->radius),-1,__LINE__,__FILE__); } return false; } /** * Return user info * * Returns info about the given user needs to contain * at least these fields: * * name string full name of the user, for now just $user * mail string email address of the user, for now $user@$mailhost. * $mailhost is set in the config * grps array list of groups the user is in, for now empty. * Could be calculated from the username regexes in the config. * * @author Sebastian Menge <bastl@users.sf.net> */ function getUserData($user) { if($this->users === null) parent::_loadUserData(); $plain_data = isset($this->users[$user]) ? $this->users[$user] : false; if ($plain_data) { $data['grps'] = $plain_data['grps']; $data['mail'] = $plain_data['mail']; $data['name'] = $plain_data['name']; } else { $data['grps'] = array(); $data['mail'] = $user.'@'.$this->cnf['mailhost']; $data['name'] = $user." (".implode(", ",$data['grps']).")"; } //if no email address is set, use login@mailhost if (count ($data['mail']) == 0) { $data['mail'] = $user.'@'.$this->cnf['mailhost']; } //if no groups are found place the user in 'defaultgroup' if (count ($data['grps']) == 0) { $data['grps'][] = $this->cnf['defaultgroup']; } return $data; } /** * Return local user info * * Returns info about the given user from the local db. * Needs to contain * at least these fields: * * name string full name of the user * mail string email addres of the user * grps array list of groups the user is in * * @author Andreas Gohr <andi@splitbrain.org> */ function getLocalUserData($user){ if($this->users === null) $this->_loadUserData(); return isset($this->users[$user]) ? $this->users[$user] : false; } /** * Create a new User * * Returns false if the user already exists, null when an error * occured and true if everything went well. * * The new user will be added to the default group by this * function if grps are not specified (default behaviour). * * @author Andreas Gohr <andi@splitbrain.org> * @author Chris Smith <chris@jalakai.co.uk> */ function createUser($user,$pwd,$name,$mail,$grps=null){ global $conf; // user mustn't already exist if ($this->getLocalUserData($user) !== false) return false; $pass = "pass_set_by_radius"; // set default group if no groups specified if (!is_array($grps)) $grps = array($conf['defaultgroup']); // prepare user line $groups = join(',',$grps); $userline = join(':',array($user,$pass,$name,$mail,$groups))."\n"; if (io_saveFile(AUTH_USERFILE,$userline,true)) { $this->users[$user] = compact('pass','name','mail','grps'); return $pwd; } msg('The '.AUTH_USERFILE.' file is not writable. Please inform the Wiki-Admin',-1); return null; } } //Setup VIM: ex: et ts=2 enc=utf-8 :
Configuration
//enable radius auth $conf['authtype'] = 'radius'; //radius Config $conf['auth']['radius']['host'] = 'radius.mycompany.com'; $conf['auth']['radius']['port'] = '0'; //0 reuses data from /etc/services $conf['auth']['radius']['secret'] = 'radiussecret'; $conf['auth']['radius']['timeout'] = '3'; $conf['auth']['radius']['tries'] = '3'; $conf['auth']['radius']['mailhost'] = 'mail.mycompany.com';
Put the following in …/dokuwiki/lib/plugins/config/settings/config.metadata.php to edit the main settings it via the config plugin.
//radius-settings $meta['auth____radius____host'] = array('string'); $meta['auth____radius____port'] = array('string'); $meta['auth____radius____timeout'] = array('string'); $meta['auth____radius____tries'] = array('string'); $meta['auth____radius____secret'] = array('password'); $meta['auth____radius____mailhost'] = array('string'); $meta['auth____radius____defaultgroup'] = array('string');
Users can be managed via the user-manager plugin now. The password of users.auth.php is ignored. Just put a dummy value in there.
Users have to change the lines
$this->cando['modLogin'] = false; $this->cando['modPass'] = false;
such that the right capabilities are set. (set modLogin to true.)
auth/radius.1279708223.txt.gz · Last modified: 2010-07-21 12:30 by 129.217.40.196