From b3b0544e17b172da1ae3760fe5b4e4f90c20b47a Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 31 Jan 2013 01:46:34 +0100 Subject: [PATCH] LDAP: make it possible to define attributes that should be considered on searches --- apps/user_ldap/group_ldap.php | 10 +++---- apps/user_ldap/lib/access.php | 44 +++++++++++++++++++++++++++++++ apps/user_ldap/lib/connection.php | 23 ++++++++++++++-- apps/user_ldap/user_ldap.php | 3 +-- 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php index 6343731008..02ceecaea0 100644 --- a/apps/user_ldap/group_ldap.php +++ b/apps/user_ldap/group_ldap.php @@ -171,7 +171,6 @@ class GROUP_LDAP extends lib\Access implements \OCP\GroupInterface { return array(); } - $search = empty($search) ? '*' : '*'.$search.'*'; $groupUsers = array(); $isMemberUid = (strtolower($this->connection->ldapGroupMemberAssocAttr) == 'memberuid'); foreach($members as $member) { @@ -179,7 +178,7 @@ class GROUP_LDAP extends lib\Access implements \OCP\GroupInterface { //we got uids, need to get their DNs to 'tranlsate' them to usernames $filter = $this->combineFilterWithAnd(array( \OCP\Util::mb_str_replace('%uid', $member, $this->connection>ldapLoginFilter, 'UTF-8'), - $this->connection->ldapUserDisplayName.'='.$search + $this->getFilterPartForUserSearch($search) )); $ldap_users = $this->fetchListOfUsers($filter, 'dn'); if(count($ldap_users) < 1) { @@ -188,8 +187,8 @@ class GROUP_LDAP extends lib\Access implements \OCP\GroupInterface { $groupUsers[] = $this->dn2username($ldap_users[0]); } else { //we got DNs, check if we need to filter by search or we can give back all of them - if($search != '*') { - if(!$this->readAttribute($member, $this->connection->ldapUserDisplayName, $this->connection->ldapUserDisplayName.'='.$search)) { + if(!empty($search)) { + if(!$this->readAttribute($member, $this->connection->ldapUserDisplayName, $this->getFilterPartForUserSearch($search))) { continue; } } @@ -230,10 +229,9 @@ class GROUP_LDAP extends lib\Access implements \OCP\GroupInterface { if($limit <= 0) { $limit = null; } - $search = empty($search) ? '*' : '*'.$search.'*'; $filter = $this->combineFilterWithAnd(array( $this->connection->ldapGroupFilter, - $this->connection->ldapGroupDisplayName.'='.$search + $this->getFilterPartForGroupSearch($search) )); \OCP\Util::writeLog('user_ldap', 'getGroups Filter '.$filter, \OCP\Util::DEBUG); $ldap_groups = $this->fetchListOfGroups($filter, array($this->connection->ldapGroupDisplayName, 'dn'), $limit, $offset); diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index 27c7444697..68cbe4a5e7 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -719,6 +719,50 @@ abstract class Access { return $combinedFilter; } + /** + * @brief creates a filter part for to perfrom search for users + * @param string $search the search term + * @return string the final filter part to use in LDAP searches + */ + public function getFilterPartForUserSearch($search) { + return $this->getFilterPartForSearch($search, $this->connection->ldapAttributesForUserSearch, $this->connection->ldapUserDisplayName); + } + + /** + * @brief creates a filter part for to perfrom search for groups + * @param string $search the search term + * @return string the final filter part to use in LDAP searches + */ + public function getFilterPartForGroupSearch($search) { + return $this->getFilterPartForSearch($search, $this->connection->ldapAttributesForGroupSearch, $this->connection->ldapGroupDisplayName); + } + + /** + * @brief creates a filter part for searches + * @param string $search the search term + * @param string $fallbackAttribute a fallback attribute in case the user + * did not define search attributes. Typically the display name attribute. + * @returns string the final filter part to use in LDAP searches + */ + private function getFilterPartForSearch($search, $searchAttributes, $fallbackAttribute) { + $filter = array(); + $search = empty($search) ? '*' : '*'.$search.'*'; + if(!is_array($searchAttributes) || count($searchAttributes) == 0) { + if(empty($fallbackAttribute)) { + return ''; + } + $filter[] = $fallbackAttribute . '=' . $search; + } else { + foreach($searchAttributes as $attribute) { + $filter[] = $attribute . '=' . $search; + } + } + if(count($filter) == 1) { + return '('.$filter[0].')'; + } + return $this->combineFilterWithOr($filter); + } + public function areCredentialsValid($name, $password) { $name = $this->DNasBaseParameter($name); $testConnection = clone $this->connection; diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 2d34013c9d..9044b395d4 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -61,6 +61,8 @@ class Connection { 'ldapOverrideUuidAttribute' => null, 'ldapOverrideMainServer' => false, 'ldapConfigurationActive' => false, + 'ldapAttributesForUserSearch' => null, + 'ldapAttributesForGroupSearch' => null, 'homeFolderNamingRule' => null, 'hasPagedResultSupport' => false, ); @@ -259,6 +261,10 @@ class Connection { = $this->$v('home_folder_naming_rule'); $this->config['ldapConfigurationActive'] = $this->$v('ldap_configuration_active'); + $this->config['ldapAttributesForUserSearch'] + = preg_split('/\r\n|\r|\n/', $this->$v('ldap_attributes_for_user_search')); + $this->config['ldapAttributesForGroupSearch'] + = preg_split('/\r\n|\r|\n/', $this->$v('ldap_attributes_for_group_search')); $this->configured = $this->validateConfiguration(); } @@ -270,7 +276,7 @@ class Connection { private function getConfigTranslationArray() { static $array = array('ldap_host'=>'ldapHost', 'ldap_port'=>'ldapPort', 'ldap_backup_host'=>'ldapBackupHost', 'ldap_backup_port'=>'ldapBackupPort', 'ldap_override_main_server' => 'ldapOverrideMainServer', 'ldap_dn'=>'ldapAgentName', 'ldap_agent_password'=>'ldapAgentPassword', 'ldap_base'=>'ldapBase', 'ldap_base_users'=>'ldapBaseUsers', 'ldap_base_groups'=>'ldapBaseGroups', 'ldap_userlist_filter'=>'ldapUserFilter', 'ldap_login_filter'=>'ldapLoginFilter', 'ldap_group_filter'=>'ldapGroupFilter', 'ldap_display_name'=>'ldapUserDisplayName', 'ldap_group_display_name'=>'ldapGroupDisplayName', - 'ldap_tls'=>'ldapTLS', 'ldap_nocase'=>'ldapNoCase', 'ldap_quota_def'=>'ldapQuotaDefault', 'ldap_quota_attr'=>'ldapQuotaAttribute', 'ldap_email_attr'=>'ldapEmailAttribute', 'ldap_group_member_assoc_attribute'=>'ldapGroupMemberAssocAttr', 'ldap_cache_ttl'=>'ldapCacheTTL', 'home_folder_naming_rule' => 'homeFolderNamingRule', 'ldap_turn_off_cert_check' => 'turnOffCertCheck', 'ldap_configuration_active' => 'ldapConfigurationActive'); + 'ldap_tls'=>'ldapTLS', 'ldap_nocase'=>'ldapNoCase', 'ldap_quota_def'=>'ldapQuotaDefault', 'ldap_quota_attr'=>'ldapQuotaAttribute', 'ldap_email_attr'=>'ldapEmailAttribute', 'ldap_group_member_assoc_attribute'=>'ldapGroupMemberAssocAttr', 'ldap_cache_ttl'=>'ldapCacheTTL', 'home_folder_naming_rule' => 'homeFolderNamingRule', 'ldap_turn_off_cert_check' => 'turnOffCertCheck', 'ldap_configuration_active' => 'ldapConfigurationActive', 'ldap_attributes_for_user_search' => 'ldapAttributesForUserSearch', 'ldap_attributes_for_group_search' => 'ldapAttributesForGroupSearch'); return $array; } @@ -324,6 +330,8 @@ ingle parameters case 'ldapBase': case 'ldapBaseUsers': case 'ldapBaseGroups': + case 'ldapAttributesForUserSearch': + case 'ldapAttributesForGroupSearch': if(is_array($value)){ $value = implode("\n", $value); } @@ -360,7 +368,8 @@ ingle parameters $config[$dbKey] = substr($this->config[$dbKey], 5); } continue; - } else if(strpos($classKey, 'ldapBase') !== false) { + } else if((strpos($classKey, 'ldapBase') !== false) + || (strpos($classKey, 'ldapAttributes') !== false)) { $config[$dbKey] = implode("\n", $this->config[$classKey]); continue; } @@ -395,6 +404,14 @@ ingle parameters //force default $this->config['ldapBackupPort'] = $this->config['ldapPort']; } + foreach(array('ldapAttributesForUserSearch', 'ldapAttributesForGroupSearch') as $key) { + if(is_array($this->config[$key]) + && count($this->config[$key]) == 1 + && empty($this->config[$key][0])) { + $this->config[$key] = array(); + } + } + //second step: critical checks. If left empty or filled wrong, set as unconfigured and give a warning. @@ -471,6 +488,8 @@ ingle parameters 'home_folder_naming_rule' => 'opt:username', 'ldap_turn_off_cert_check' => 0, 'ldap_configuration_active' => 1, + 'ldap_attributes_for_user_search' => '', + 'ldap_attributes_for_group_search' => '', ); } diff --git a/apps/user_ldap/user_ldap.php b/apps/user_ldap/user_ldap.php index 6591d1d5fe..cb11ae3909 100644 --- a/apps/user_ldap/user_ldap.php +++ b/apps/user_ldap/user_ldap.php @@ -116,10 +116,9 @@ class USER_LDAP extends lib\Access implements \OCP\UserInterface { if($limit <= 0) { $limit = null; } - $search = empty($search) ? '*' : '*'.$search.'*'; $filter = $this->combineFilterWithAnd(array( $this->connection->ldapUserFilter, - $this->connection->ldapUserDisplayName.'='.$search + $this->getFilterPartForUserSearch($search) )); \OCP\Util::writeLog('user_ldap', 'getUsers: Options: search '.$search.' limit '.$limit.' offset '.$offset.' Filter: '.$filter, \OCP\Util::DEBUG);