From 274409ef297b1f80c36bf04e64a1571be0e0039f Mon Sep 17 00:00:00 2001 From: Dominik Eckelmann Date: Thu, 29 Apr 2010 09:53:49 +0200 Subject: added getUsers to ad auth backend --- inc/auth/ad.class.php | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'inc/auth') diff --git a/inc/auth/ad.class.php b/inc/auth/ad.class.php index 9915b9f11..e60598df6 100644 --- a/inc/auth/ad.class.php +++ b/inc/auth/ad.class.php @@ -38,6 +38,7 @@ class auth_ad extends auth_basic { var $cnf = null; var $opts = null; var $adldap = null; + var $users = null; /** * Constructor @@ -184,6 +185,45 @@ class auth_ad extends auth_basic { return false; } + /** + * Bulk retrieval of user data + * + * @author Dominik Eckelmann + * @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 */ @@ -193,6 +233,9 @@ 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) { $this->success = false; @@ -200,6 +243,32 @@ class auth_ad extends auth_basic { } return false; } + + /** + * return 1 if $user + $info match $filter criteria, 0 otherwise + * + * @author Chris Smith + */ + 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 : -- cgit v1.2.3 From ba29aad72a17a6a9c34afcb2adc13f2a7f9e4e17 Mon Sep 17 00:00:00 2001 From: Dominik Eckelmann Date: Thu, 29 Apr 2010 11:51:11 +0200 Subject: gather additional information from ad backend --- inc/auth/ad.class.php | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'inc/auth') diff --git a/inc/auth/ad.class.php b/inc/auth/ad.class.php index e60598df6..a52f5f8b2 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 * @link http://www.nosq.com/blog/2005/08/ldap-activedirectory-and-dokuwiki/ @@ -47,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']) @@ -131,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']); -- cgit v1.2.3 From 8a6e9b060334bab4d8d2ddcbdb4de32241c7f7e1 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Wed, 5 May 2010 14:47:23 +0200 Subject: Add debug message for adLDAP class construction --- inc/auth/ad.class.php | 3 +++ 1 file changed, 3 insertions(+) (limited to 'inc/auth') diff --git a/inc/auth/ad.class.php b/inc/auth/ad.class.php index a52f5f8b2..9ae6dbbd1 100644 --- a/inc/auth/ad.class.php +++ b/inc/auth/ad.class.php @@ -260,6 +260,9 @@ class auth_ad extends auth_basic { } return true; } catch (adLDAPException $e) { + if ($this->cnf['debug']) { + msg($e->getMessage(), -1); + } $this->success = false; $this->adldap = null; } -- cgit v1.2.3 From 880f62faf63b666adcc1d6aec6a8ead3edb18f59 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Tue, 22 Jun 2010 18:51:00 +0200 Subject: new auth capability 'logout' This patch implements what Adrian's patch "Hide logout button if auth backend cannot logout" intended to do. The 'logoff' capability was used to decide if a special method called $auth->logOff() should be called when the user logs out, not if the backend supports logouts at all. This was a superflous capability since an empty logOff() method is implemented in the base class anyway - it doesn't hurt to always call the method. The 'logoff' capability is now deprecated. Backends who want to do actions on logout simply need to overwrite logOff(). A new capability 'logout' was added which defaults to true. Backends that can't logoff the user (eg. because they use some automatic login/logoff mechanism) can set this to false. Probably makes sense to add a 'login' capability as well... --- inc/auth/basic.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'inc/auth') 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) ); -- cgit v1.2.3 From be6541cce13f8d09639459b791dbd5b20c54dbc7 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Wed, 23 Jun 2010 11:05:51 +0200 Subject: basic_auth is loaded by inc/auth.php --- inc/auth/mysql.class.php | 3 --- inc/auth/pgsql.class.php | 3 +-- inc/auth/plain.class.php | 3 --- 3 files changed, 1 insertion(+), 8 deletions(-) (limited to 'inc/auth') 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 */ -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 */ -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..af4fadb36 100644 --- a/inc/auth/plain.class.php +++ b/inc/auth/plain.class.php @@ -7,9 +7,6 @@ * @author Chris Smith */ -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 { -- cgit v1.2.3 From de3427dbc88f1a060e6557d79da3a9bafb9a6039 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 27 Jun 2010 13:28:59 +0200 Subject: Add scope options to LDAP auth backend FS#1832 The scope for the LDAP searches for users and groups can now be set using the new options 'userscope' and 'groupscope'. Valid options are 'base', 'one' and 'sub'. Defaults to 'sub'. --- inc/auth/ldap.class.php | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'inc/auth') diff --git a/inc/auth/ldap.class.php b/inc/auth/ldap.class.php index c51924135..fc1a7ddb6 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__); @@ -219,7 +221,7 @@ class auth_ldap extends auth_basic { 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']){ @@ -352,6 +354,28 @@ class auth_ldap extends auth_basic { 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 + */ + 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 : -- cgit v1.2.3 From c8f80b4e70ee1b73ecc08cac583d021979af9359 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 27 Jun 2010 14:43:56 +0200 Subject: Use config_cascade for ACLs and plain auth users FS#1677 --- inc/auth/plain.class.php | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'inc/auth') diff --git a/inc/auth/plain.class.php b/inc/auth/plain.class.php index af4fadb36..ec9e52beb 100644 --- a/inc/auth/plain.class.php +++ b/inc/auth/plain.class.php @@ -7,8 +7,6 @@ * @author Chris Smith */ -define('AUTH_USERFILE',DOKU_CONF.'users.auth.php'); - class auth_plain extends auth_basic { var $users = null; @@ -23,10 +21,12 @@ class auth_plain extends auth_basic { * @author Christopher Smith */ 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; @@ -89,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; @@ -102,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; } @@ -123,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; @@ -147,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'; @@ -166,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; @@ -180,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); } @@ -271,11 +275,13 @@ class auth_plain extends auth_basic { * @author Andreas Gohr */ 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); -- cgit v1.2.3 From b7c7128b49e4ee249019c666a711792890352b72 Mon Sep 17 00:00:00 2001 From: Kirill Krasnov Date: Wed, 6 Jan 2010 16:45:24 +0200 Subject: Fix for Lotus ldap auth FS#1828 --- inc/auth/ldap.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'inc/auth') diff --git a/inc/auth/ldap.class.php b/inc/auth/ldap.class.php index fc1a7ddb6..e1922ce86 100644 --- a/inc/auth/ldap.class.php +++ b/inc/auth/ldap.class.php @@ -218,7 +218,7 @@ 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 = $this->_ldapsearch($this->con, $base, $filter, $this->cnf['groupscope'], array($this->cnf['groupkey'])); -- cgit v1.2.3 From 47fecefedeb5e1069db2bbc0ce312c9522fd5a62 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Mon, 5 Jul 2010 15:43:53 +0200 Subject: Add getUsers capability to LDAP backend --- inc/auth/ldap.class.php | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) (limited to 'inc/auth') diff --git a/inc/auth/ldap.class.php b/inc/auth/ldap.class.php index e1922ce86..069d0fc92 100644 --- a/inc/auth/ldap.class.php +++ b/inc/auth/ldap.class.php @@ -256,6 +256,58 @@ class auth_ldap extends auth_basic { return false; } + /** + * Bulk retrieval of user data + * + * @author Dominik Eckelmann + * @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'])) { + $filter = str_replace('%{user}', '*', $this->cnf['userfilter']); + } else { + $filter = "(ObjectClass=*)"; + } + $sr=ldap_search($this->con,$this->cnf['usertree'],$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. * @@ -284,6 +336,32 @@ class auth_ldap extends auth_basic { return $filter; } + /** + * return 1 if $user + $info match $filter criteria, 0 otherwise + * + * @author Chris Smith + */ + 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 * @@ -352,6 +430,7 @@ class auth_ldap extends auth_basic { } } + $this->canDo['getUsers'] = true; return true; } -- cgit v1.2.3 From b7f327c9619c6ba12bde90220173f7c114584860 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Mon, 9 Aug 2010 17:26:47 +0200 Subject: Fix variable name in ldap retrieveUsers --- inc/auth/ldap.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'inc/auth') diff --git a/inc/auth/ldap.class.php b/inc/auth/ldap.class.php index 069d0fc92..5cc186ce2 100644 --- a/inc/auth/ldap.class.php +++ b/inc/auth/ldap.class.php @@ -271,11 +271,11 @@ class auth_ldap extends auth_basic { if (!isset($this->users)) { // Perform the search and grab all their details if(!empty($this->cnf['userfilter'])) { - $filter = str_replace('%{user}', '*', $this->cnf['userfilter']); + $all_filter = str_replace('%{user}', '*', $this->cnf['userfilter']); } else { - $filter = "(ObjectClass=*)"; + $all_filter = "(ObjectClass=*)"; } - $sr=ldap_search($this->con,$this->cnf['usertree'],$filter); + $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++){ -- cgit v1.2.3