diff options
Diffstat (limited to 'inc/auth')
-rw-r--r-- | inc/auth/basic.class.php | 159 | ||||
-rw-r--r-- | inc/auth/plain.class.php | 317 |
2 files changed, 476 insertions, 0 deletions
diff --git a/inc/auth/basic.class.php b/inc/auth/basic.class.php new file mode 100644 index 000000000..cf19e2c79 --- /dev/null +++ b/inc/auth/basic.class.php @@ -0,0 +1,159 @@ +<?php +/** + * auth/basic.class.php + * + * foundation authorisation class + * all auth classes should inherit from this class + * + * @author Chris Smith <chris@jalakaic.co.uk> + */ + +class auth_basic { + + /** + * Check user+password [ MUST BE OVERRIDDEN ] + * + * Checks if the given user exists and the given + * plaintext password is correct + * + * @author Andreas Gohr <andi@splitbrain.org> + * @return bool + */ + function checkPass($user,$pass){ + + msg("no valid authorisation system in use", -1); + return false; + } + + /** + * Return user info [ MUST BE OVERRIDDEN ] + * + * Returns info about the given user 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> + * @return array containing user data or false + */ + function getUserData($user) { + + msg("no valid authorisation system in use", -1); + return false; + } + + /** + * Create a new User [implement only where required/possible] + * + * Returns false if the user already exists, null when an error + * occured and the cleartext password of the new user if + * everything went well. + * + * The new user HAS TO be added to the default group by this + * function! + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +# function createUser($user,$pass,$name,$mail,$grps=null){ +# +# msg("authorisation method does not allow creation of new users", -1); +# return null; +# } + + /** + * Modify user data [implement only where required/possible] + * + * @author Chris Smith <chris@jalakai.co.uk> + * @param $user nick of the user to be changed + * @param $changes array of field/value pairs to be changed (password will be clear text) + * @return bool + */ +# function modifyUser($user, $changes) { +# msg("authorisation method does not allow modifying of user data", -1); +# return false; +# } + + /** + * Delete one or more users [implement only where required/possible] + * + * @author Chris Smith <chris@jalakai.co.uk> + * @param array $users + * @return int number of users deleted + */ +# function deleteUsers($users) { +# msg("authorisation method does not allow deleting of users", -1); +# return false; +# } + + /** + * Return a count of the number of user which meet $filter criteria + * [should be implemented whenever retrieveUsers is implemented] + * + * @author Chris Smith <chris@jalakai.co.uk> + */ +# function getUserCount($filter=array()) { +# +# msg("authorisation method does not provide user counts", -1); +# return 0; +# } + + /** + * Bulk retrieval of user data [implement only where required/possible] + * + * @author Chris Smith <chris@jalakai.co.uk> + * @param start index of first user to be returned + * @param limit max number of users to be returned + * @param filter array of field/pattern pairs, null for no filter + * @return array of userinfo (refer getUserData for internal userinfo details) + */ +# function retrieveUsers($start=0,$limit=-1,$filter=null) { +# msg("authorisation method does not support mass retrieval of user data", -1); +# return array(); +# } + + /** + * Define a group [implement only where required/possible] + * + * @author Chris Smith <chris@jalakai.co.uk> + * @return bool + */ +# function addGroup($group) { +# msg("authorisation method does not support independent group creation", -1); +# return false; +# } + + /** + * Retrieve groups [implement only where required/possible] + * + * @author Chris Smith <chris@jalakai.co.uk> + * @return array + */ +# function retrieveGroups($start=0,$limit=0) { +# msg("authorisation method does not support group list retrieval", -1); +# return array(); +# } + + /** + * Give user membership of a group [implement only where required/possible] + * + * @author Chris Smith <chris@jalakai.co.uk> + * @return bool + */ +# function joinGroup($user, $group) { +# msg("authorisation method does not support alteration of group memberships", -1); +# return false; +# } + + /** + * Remove user from a group [implement only where required/possible] + * + * @author Chris Smith <chris@jalakai.co.uk> + * @return bool + */ +# function leaveGroup($user, $group) { +# msg("authorisation method does not support alteration of group memberships", -1); +# return false; +# } +}
\ No newline at end of file diff --git a/inc/auth/plain.class.php b/inc/auth/plain.class.php new file mode 100644 index 000000000..d492463e5 --- /dev/null +++ b/inc/auth/plain.class.php @@ -0,0 +1,317 @@ +<?php +/** + * Plaintext authentication backend + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Andreas Gohr <andi@splitbrain.org> + * @author Chris Smith <chris@jalakai.co.uk> + */ + +define('DOKU_AUTH', dirname(__FILE__)); +require_once(DOKU_AUTH.'/basic.class.php'); + +define('AUTH_USERFILE',DOKU_CONF.'users.auth.php'); + +// we only accept page ids for auth_plain +if(isset($_REQUEST['u'])) + $_REQUEST['u'] = cleanID($_REQUEST['u']); + +class auth_plain extends auth_basic { + + var $users = null; + var $_pattern = array(); + + /** + * Check user+password [required auth function] + * + * Checks if the given user exists and the given + * plaintext password is correct + * + * @author Andreas Gohr <andi@splitbrain.org> + * @return bool + */ + function checkPass($user,$pass){ + + $userinfo = $this->getUserData($user); + if ($userinfo === false) return false; + + return auth_verifyPassword($pass,$this->users[$user]['pass']); + } + + /** + * Return user info [required auth function] + * + * Returns info about the given user 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 getUserData($user){ + + if($this->users === null) $this->_loadUserData(); + return isset($this->users[$user]) ? $this->users[$user] : false; + } + + /** + * Create a new User [implement only where required/possible] + * + * Returns false if the user already exists, null when an error + * occured and the cleartext password of the new user 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->getUserData($user) !== false) return false; + + $pass = auth_cryptPassword($pwd); + + // 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; + } + + /** + * Modify user data [implement only where required/possible] + * + * @author Chris Smith <chris@jalakai.co.uk> + * @param $user nick of the user to be changed + * @param $changes array of field/value pairs to be changed (password will be clear text) + * @return bool + */ + function modifyUser($user, $changes) { + global $conf; + global $ACT; + global $INFO; + + // sanity checks, user must already exist and there must be something to change + if (($userinfo = $this->getUserData($user)) === false) return false; + if (!is_array($changes) || !count($changes)) return true; + + // update userinfo with new data, remembering to encrypt any password + foreach ($changes as $field => $value) { + if ($field == 'pass') $value = auth_cryptPassword($value); + $userinfo[$field] = $value; + } + + $groups = join(',',$userinfo['grps']); + $userline = join(':',array($user, $userinfo['pass'], $userinfo['name'], $userinfo['mail'], $groups))."\n"; + + if (!$this->deleteUsers(array($user))) { + msg('Unable to modify user data. Please inform the Wiki-Admin',-1); + return false; + } + + if (!io_saveFile(AUTH_USERFILE,$userline,true)) { + msg('There was an error modifying your user data. You should register again.',-1); + // FIXME, user has been deleted but not recreated, should force a logout and redirect to login page + $ACT == 'register'; + return false; + } + + $this->users[$user] = $userinfo; + return true; + } + + /** + * Remove one or more users from the list of registered users + * + * @author Christopher Smith <chris@jalakai.co.uk> + * @param array $users array of users to be deleted + * @return int the number of users deleted + */ + function deleteUsers($users) { + + if (!is_array($users) || empty($users)) return 0; + + if ($this->users === null) $this->_loadUserData(); + + $deleted = array(); + foreach ($users as $user) { + if (isset($this->users[$user])) $deleted[] = preg_quote($user,'/'); + } + + if (empty($deleted)) return 0; + + $pattern = '/^('.join('|',$deleted).'):/'; + + if (io_deleteFromFile(AUTH_USERFILE,$pattern,true)) { + foreach ($deleted as $user) unset($this->users[$user]); + return count($deleted); + } + + // problem deleting, reload the user list and count the difference + $count = count($this->users()); + $this->_loadUserData(); + $count -= $count($this->users()); + return $count; + } + + /** + * Return a count of the number of user which meet $filter criteria + * + * @author Chris Smith <chris@jalakai.co.uk> + */ + function getUserCount($filter=array()) { + + if($this->users === null) $this->_loadUserData(); + + if (!count($filter)) return count($this->users); + + $count = 0; + $this->_constructPattern($filter); + + foreach ($this->users as $user => $info) { + $count += $this->_filter($user, $info); + } + + return $count; + } + + /** + * Bulk retrieval of user data [implement only where required/possible] + * + * @author Chris Smith <chris@jalakai.co.uk> + * @param start index of first user to be returned + * @param limit max number of users to be returned + * @param filter array of field/pattern pairs + * @return array of userinfo (refer getUserData for internal userinfo details) + */ + function retrieveUsers($start=0,$limit=0,$filter=array()) { + + if ($this->users === null) $this->_loadUserData(); + + ksort($this->users); + + $i = 0; + $count = 0; + $out = array(); + $this->_constructPattern($filter); + + foreach ($this->users as $user => $info) { + if ($this->_filter($user, $info)) { + if ($i >= $start) { + $out[$user] = $info; + $count++; + if (($limit > 0) && ($count >= $limit)) break; + } + $i++; + } + } + + return $out; + } + + /** + * Give user membership of a group [implement only where required/possible] + * + * @author Chris Smith <chris@jalakai.co.uk> + * @return bool + */ + function joinGroup($user, $group) { + + // sanity checks, user must exist, and not currently a group member + if (($userinfo = $this->getUserData($user)) === false) return false; + if (in_array($group, $userinfo['grps'])) return true; + + $userinfo['grps'][] = $group; + + return $this->modifyUser($user, array('grps' => $userinfo['grps'])); + } + + /** + * Remove user from a group [implement only where required/possible] + * + * @author Chris Smith <chris@jalakai.co.uk> + * @return bool + */ + function leaveGroup($user, $group) { + + // sanity checks, user must exist, and currently be a group member + if (($userinfo = $this->getUserData($user)) === false) return false; + if (($i = array_search($group, $userinfo['grps'])) === false) return true; + + array_splice($userinfo['grps'],$i,1); + + return $this->modifyUser($user, array('grps' => $userinfo['grps'])); + } + + /** + * Load all user data + * + * loads the user file into a datastructure + * + * @author Andreas Gohr <andi@splitbrain.org> + */ + function _loadUserData(){ + $this->users = array(); + + if(!@file_exists(AUTH_USERFILE)) return; + + $lines = file(AUTH_USERFILE); + foreach($lines as $line){ + $line = preg_replace('/#.*$/','',$line); //ignore comments + $line = trim($line); + if(empty($line)) continue; + + $row = split(":",$line,5); + $groups = split(",",$row[4]); + + $this->users[$row[0]]['pass'] = $row[1]; + $this->users[$row[0]]['name'] = urldecode($row[2]); + $this->users[$row[0]]['mail'] = $row[3]; + $this->users[$row[0]]['grps'] = $groups; + } + } + + /** + * return 1 if $user + $info match $filter criteria, 0 otherwise + * + * @author Chris Smith <chris@jalakai.co.uk> + */ + function _filter($user, $info) { + // FIXME + foreach ($this->_pattern as $item => $pattern) { + if ($item == 'user') { + if (!preg_match($pattern, $user)) return 0; + } else if ($item == 'grps') { + if (!count(preg_grep($pattern, $info['grps']))) return 0; + } else { + if (!preg_match($pattern, $info[$item])) return 0; + } + } + return 1; + } + + function _constructPattern($filter) { + $this->_pattern = array(); + foreach ($filter as $item => $pattern) { +// $this->_pattern[$item] = '/'.preg_quote($pattern,"/").'/'; // don't allow regex characters + $this->_pattern[$item] = '/'.str_replace('/','\/',$pattern).'/'; // allow regex characters + } + } +} + +//Setup VIM: ex: et ts=2 enc=utf-8 : |