summaryrefslogtreecommitdiff
path: root/inc/auth
diff options
context:
space:
mode:
Diffstat (limited to 'inc/auth')
-rw-r--r--inc/auth/ad.class.php98
-rw-r--r--inc/auth/basic.class.php2
-rw-r--r--inc/auth/ldap.class.php111
-rw-r--r--inc/auth/mysql.class.php3
-rw-r--r--inc/auth/pgsql.class.php3
-rw-r--r--inc/auth/plain.class.php29
6 files changed, 221 insertions, 25 deletions
diff --git a/inc/auth/ad.class.php b/inc/auth/ad.class.php
index 9915b9f11..9ae6dbbd1 100644
--- a/inc/auth/ad.class.php
+++ b/inc/auth/ad.class.php
@@ -26,6 +26,10 @@
* $conf['auth']['ad']['use_ssl'] = 1;
* $conf['auth']['ad']['debug'] = 1;
*
+ * // get additional informations to the userinfo array
+ * // add a list of comma separated ldap contact fields.
+ * $conf['auth']['ad']['additional'] = 'field1,field2';
+ *
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author James Van Lommel <jamesvl@gmail.com>
* @link http://www.nosq.com/blog/2005/08/ldap-activedirectory-and-dokuwiki/
@@ -38,6 +42,7 @@ class auth_ad extends auth_basic {
var $cnf = null;
var $opts = null;
var $adldap = null;
+ var $users = null;
/**
* Constructor
@@ -46,6 +51,12 @@ class auth_ad extends auth_basic {
global $conf;
$this->cnf = $conf['auth']['ad'];
+ // additional information fields
+ if (isset($this->cnf['additional'])) {
+ $this->cnf['additional'] = str_replace(' ', '', $this->cnf['additional']);
+ $this->cnf['additional'] = explode(',', $this->cnf['additional']);
+ } else $this->cnf['additional'] = array();
+
// ldap extension is needed
if (!function_exists('ldap_connect')) {
if ($this->cnf['debug'])
@@ -130,15 +141,27 @@ class auth_ad extends auth_basic {
global $conf;
if(!$this->_init()) return false;
- //get info for given user
- $result = $this->adldap->user_info($user);
+ $fields = array('mail','displayname','samaccountname');
+ // add additional fields to read
+ $fields = array_merge($fields, $this->cnf['additional']);
+ $fields = array_unique($fields);
+
+ //get info for given user
+ $result = $this->adldap->user_info($user, $fields);
//general user info
$info['name'] = $result[0]['displayname'][0];
$info['mail'] = $result[0]['mail'][0];
$info['uid'] = $result[0]['samaccountname'][0];
$info['dn'] = $result[0]['dn'];
+ // additional informations
+ foreach ($this->cnf['additional'] as $field) {
+ if (isset($result[0][strtolower($field)])) {
+ $info[$field] = $result[0][strtolower($field)][0];
+ }
+ }
+
// handle ActiveDirectory memberOf
$info['grps'] = $this->adldap->user_groups($user,(bool) $this->opts['recursive_groups']);
@@ -185,6 +208,45 @@ class auth_ad extends auth_basic {
}
/**
+ * Bulk retrieval of user data
+ *
+ * @author Dominik Eckelmann <dokuwiki@cosmocode.de>
+ * @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=array()) {
+ if(!$this->_init()) return false;
+
+ if ($this->users === null) {
+ //get info for given user
+ $result = $this->adldap->all_users();
+ if (!$result) return array();
+ $this->users = array_fill_keys($result, false);
+ }
+
+ $i = 0;
+ $count = 0;
+ $this->_constructPattern($filter);
+ $result = array();
+
+ foreach ($this->users as $user => &$info) {
+ if ($i++ < $start) {
+ continue;
+ }
+ if ($info === false) {
+ $info = $this->getUserData($user);
+ }
+ if ($this->_filter($user, $info)) {
+ $result[$user] = $info;
+ if (($limit >= 0) && (++$count >= $limit)) break;
+ }
+ }
+ return $result;
+ }
+
+ /**
* Initialize the AdLDAP library and connect to the server
*/
function _init(){
@@ -193,13 +255,45 @@ class auth_ad extends auth_basic {
// connect
try {
$this->adldap = new adLDAP($this->opts);
+ if (isset($this->opts['ad_username']) && isset($this->opts['ad_password'])) {
+ $this->canDo['getUsers'] = true;
+ }
return true;
} catch (adLDAPException $e) {
+ if ($this->cnf['debug']) {
+ msg($e->getMessage(), -1);
+ }
$this->success = false;
$this->adldap = null;
}
return false;
}
+
+ /**
+ * return 1 if $user + $info match $filter criteria, 0 otherwise
+ *
+ * @author Chris Smith <chris@jalakai.co.uk>
+ */
+ function _filter($user, $info) {
+ 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,"/").'/i'; // don't allow regex characters
+ $this->_pattern[$item] = '/'.str_replace('/','\/',$pattern).'/i'; // allow regex characters
+ }
+ }
}
//Setup VIM: ex: et ts=4 enc=utf-8 :
diff --git a/inc/auth/basic.class.php b/inc/auth/basic.class.php
index c08422488..fa38970ae 100644
--- a/inc/auth/basic.class.php
+++ b/inc/auth/basic.class.php
@@ -30,7 +30,7 @@ class auth_basic {
'getUserCount'=> false, // can the number of users be retrieved?
'getGroups' => false, // can a list of available groups be retrieved?
'external' => false, // does the module do external auth checking?
- 'logoff' => false, // has the module some special logoff method?
+ 'logout' => true, // can the user logout again? (eg. not possible with HTTP auth)
);
diff --git a/inc/auth/ldap.class.php b/inc/auth/ldap.class.php
index c51924135..5cc186ce2 100644
--- a/inc/auth/ldap.class.php
+++ b/inc/auth/ldap.class.php
@@ -27,7 +27,9 @@ class auth_ldap extends auth_basic {
return;
}
- if(empty($this->cnf['groupkey'])) $this->cnf['groupkey'] = 'cn';
+ if(empty($this->cnf['groupkey'])) $this->cnf['groupkey'] = 'cn';
+ if(empty($this->cnf['userscope'])) $this->cnf['userscope'] = 'sub';
+ if(empty($this->cnf['groupscope'])) $this->cnf['groupscope'] = 'sub';
// auth_ldap currently just handles authentication, so no
// capabilities are set
@@ -171,7 +173,7 @@ class auth_ldap extends auth_basic {
$filter = "(ObjectClass=*)";
}
- $sr = @ldap_search($this->con, $base, $filter);
+ $sr = $this->_ldapsearch($this->con, $base, $filter, $this->cnf['userscope']);
$result = @ldap_get_entries($this->con, $sr);
if($this->cnf['debug']){
msg('LDAP user search: '.htmlspecialchars(ldap_error($this->con)),0,__LINE__,__FILE__);
@@ -216,10 +218,10 @@ class auth_ldap extends auth_basic {
$user_result = array_merge($info,$user_result);
//get groups for given user if grouptree is given
- if ($this->cnf['grouptree'] && $this->cnf['groupfilter']) {
+ if ($this->cnf['grouptree'] || $this->cnf['groupfilter']) {
$base = $this->_makeFilter($this->cnf['grouptree'], $user_result);
$filter = $this->_makeFilter($this->cnf['groupfilter'], $user_result);
- $sr = @ldap_search($this->con, $base, $filter, array($this->cnf['groupkey']));
+ $sr = $this->_ldapsearch($this->con, $base, $filter, $this->cnf['groupscope'], array($this->cnf['groupkey']));
if(!$sr){
msg("LDAP: Reading group memberships failed",-1);
if($this->cnf['debug']){
@@ -255,6 +257,58 @@ class auth_ldap extends auth_basic {
}
/**
+ * Bulk retrieval of user data
+ *
+ * @author Dominik Eckelmann <dokuwiki@cosmocode.de>
+ * @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=array()) {
+ if(!$this->_openLDAP()) return false;
+
+ if (!isset($this->users)) {
+ // Perform the search and grab all their details
+ if(!empty($this->cnf['userfilter'])) {
+ $all_filter = str_replace('%{user}', '*', $this->cnf['userfilter']);
+ } else {
+ $all_filter = "(ObjectClass=*)";
+ }
+ $sr=ldap_search($this->con,$this->cnf['usertree'],$all_filter);
+ $entries = ldap_get_entries($this->con, $sr);
+ $users_array = array();
+ for ($i=0; $i<$entries["count"]; $i++){
+ array_push($users_array, $entries[$i]["uid"][0]);
+ }
+ asort($users_array);
+ $result = $users_array;
+ if (!$result) return array();
+ $this->users = array_fill_keys($result, false);
+ }
+ $i = 0;
+ $count = 0;
+ $this->_constructPattern($filter);
+ $result = array();
+
+ foreach ($this->users as $user => &$info) {
+ if ($i++ < $start) {
+ continue;
+ }
+ if ($info === false) {
+ $info = $this->getUserData($user);
+ }
+ if ($this->_filter($user, $info)) {
+ $result[$user] = $info;
+ if (($limit >= 0) && (++$count >= $limit)) break;
+ }
+ }
+ return $result;
+
+
+ }
+
+ /**
* Make LDAP filter strings.
*
* Used by auth_getUserData to make the filter
@@ -283,6 +337,32 @@ class auth_ldap extends auth_basic {
}
/**
+ * return 1 if $user + $info match $filter criteria, 0 otherwise
+ *
+ * @author Chris Smith <chris@jalakai.co.uk>
+ */
+ function _filter($user, $info) {
+ 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,"/").'/i'; // don't allow regex characters
+ $this->_pattern[$item] = '/'.str_replace('/','\/',$pattern).'/i'; // allow regex characters
+ }
+ }
+
+ /**
* Escape a string to be used in a LDAP filter
*
* Ported from Perl's Net::LDAP::Util escape_filter_value
@@ -350,8 +430,31 @@ class auth_ldap extends auth_basic {
}
}
+ $this->canDo['getUsers'] = true;
return true;
}
+
+ /**
+ * Wraps around ldap_search, ldap_list or ldap_read depending on $scope
+ *
+ * @param $scope string - can be 'base', 'one' or 'sub'
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ function _ldapsearch($link_identifier, $base_dn, $filter, $scope='sub', $attributes=null,
+ $attrsonly=0, $sizelimit=0, $timelimit=0, $deref=LDAP_DEREF_NEVER){
+ if(is_null($attributes)) $attributes = array();
+
+ if($scope == 'base'){
+ return @ldap_read($link_identifier, $base_dn, $filter, $attributes,
+ $attrsonly, $sizelimit, $timelimit, $deref);
+ }elseif($scope == 'one'){
+ return @ldap_list($link_identifier, $base_dn, $filter, $attributes,
+ $attrsonly, $sizelimit, $timelimit, $deref);
+ }else{
+ return @ldap_search($link_identifier, $base_dn, $filter, $attributes,
+ $attrsonly, $sizelimit, $timelimit, $deref);
+ }
+ }
}
//Setup VIM: ex: et ts=4 enc=utf-8 :
diff --git a/inc/auth/mysql.class.php b/inc/auth/mysql.class.php
index b1c6a3a52..ca607ced5 100644
--- a/inc/auth/mysql.class.php
+++ b/inc/auth/mysql.class.php
@@ -8,9 +8,6 @@
* @author Matthias Grimm <matthias.grimmm@sourceforge.net>
*/
-define('DOKU_AUTH', dirname(__FILE__));
-require_once(DOKU_AUTH.'/basic.class.php');
-
class auth_mysql extends auth_basic {
var $dbcon = 0;
diff --git a/inc/auth/pgsql.class.php b/inc/auth/pgsql.class.php
index a6da56af5..8e68e865e 100644
--- a/inc/auth/pgsql.class.php
+++ b/inc/auth/pgsql.class.php
@@ -11,8 +11,7 @@
* @author Matthias Grimm <matthias.grimmm@sourceforge.net>
*/
-define('DOKU_AUTH', dirname(__FILE__));
-require_once(DOKU_AUTH.'/mysql.class.php');
+require_once(DOKU_INC.'inc/auth/mysql.class.php');
class auth_pgsql extends auth_mysql {
diff --git a/inc/auth/plain.class.php b/inc/auth/plain.class.php
index 96649e3c4..ec9e52beb 100644
--- a/inc/auth/plain.class.php
+++ b/inc/auth/plain.class.php
@@ -7,11 +7,6 @@
* @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');
-
class auth_plain extends auth_basic {
var $users = null;
@@ -26,10 +21,12 @@ class auth_plain extends auth_basic {
* @author Christopher Smith <chris@jalakai.co.uk>
*/
function auth_plain() {
- if (!@is_readable(AUTH_USERFILE)){
+ global $config_cascade;
+
+ if (!@is_readable($config_cascade['plainauth.users']['default'])){
$this->success = false;
}else{
- if(@is_writable(AUTH_USERFILE)){
+ if(@is_writable($config_cascade['plainauth.users']['default'])){
$this->cando['addUser'] = true;
$this->cando['delUser'] = true;
$this->cando['modLogin'] = true;
@@ -92,6 +89,7 @@ class auth_plain extends auth_basic {
*/
function createUser($user,$pwd,$name,$mail,$grps=null){
global $conf;
+ global $config_cascade;
// user mustn't already exist
if ($this->getUserData($user) !== false) return false;
@@ -105,12 +103,13 @@ class auth_plain extends auth_basic {
$groups = join(',',$grps);
$userline = join(':',array($user,$pass,$name,$mail,$groups))."\n";
- if (io_saveFile(AUTH_USERFILE,$userline,true)) {
+ if (io_saveFile($config_cascade['plainauth.users']['default'],$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);
+ msg('The '.$config_cascade['plainauth.users']['default'].
+ ' file is not writable. Please inform the Wiki-Admin',-1);
return null;
}
@@ -126,6 +125,7 @@ class auth_plain extends auth_basic {
global $conf;
global $ACT;
global $INFO;
+ global $config_cascade;
// sanity checks, user must already exist and there must be something to change
if (($userinfo = $this->getUserData($user)) === false) return false;
@@ -150,7 +150,7 @@ class auth_plain extends auth_basic {
return false;
}
- if (!io_saveFile(AUTH_USERFILE,$userline,true)) {
+ if (!io_saveFile($config_cascade['plainauth.users']['default'],$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';
@@ -169,6 +169,7 @@ class auth_plain extends auth_basic {
* @return int the number of users deleted
*/
function deleteUsers($users) {
+ global $config_cascade;
if (!is_array($users) || empty($users)) return 0;
@@ -183,7 +184,7 @@ class auth_plain extends auth_basic {
$pattern = '/^('.join('|',$deleted).'):/';
- if (io_deleteFromFile(AUTH_USERFILE,$pattern,true)) {
+ if (io_deleteFromFile($config_cascade['plainauth.users']['default'],$pattern,true)) {
foreach ($deleted as $user) unset($this->users[$user]);
return count($deleted);
}
@@ -274,11 +275,13 @@ class auth_plain extends auth_basic {
* @author Andreas Gohr <andi@splitbrain.org>
*/
function _loadUserData(){
+ global $config_cascade;
+
$this->users = array();
- if(!@file_exists(AUTH_USERFILE)) return;
+ if(!@file_exists($config_cascade['plainauth.users']['default'])) return;
- $lines = file(AUTH_USERFILE);
+ $lines = file($config_cascade['plainauth.users']['default']);
foreach($lines as $line){
$line = preg_replace('/#.*$/','',$line); //ignore comments
$line = trim($line);