summaryrefslogtreecommitdiff
path: root/inc/auth
diff options
context:
space:
mode:
authorchris <chris@teacherscpd.co.uk>2005-10-20 20:14:34 +0200
committerchris <chris@teacherscpd.co.uk>2005-10-20 20:14:34 +0200
commit8b06d178223afa83719d5719942e315c41adc596 (patch)
tree3a2a7e18d883a8aff5ba2db763e6d1eed6793578 /inc/auth
parent453493f24ca09d6d213a95e42de8d91bb5577458 (diff)
downloadrpg-8b06d178223afa83719d5719942e315c41adc596.tar.gz
rpg-8b06d178223afa83719d5719942e315c41adc596.tar.bz2
auth update, incl. auth object, plain.class.php; resend password & update profile actions
darcs-hash:20051020181434-50fdc-44222aa2074bb0e39a1c240c516259579b380740.gz
Diffstat (limited to 'inc/auth')
-rw-r--r--inc/auth/basic.class.php159
-rw-r--r--inc/auth/plain.class.php317
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 :