From 0c837cefb68102dc7548d62fb78ab36ef8be9a29 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Fri, 13 Sep 2013 19:01:40 +0200 Subject: [PATCH] LDAP: allow different UUID attributes for groups and users --- apps/user_ldap/appinfo/update.php | 101 ++++---------------------- apps/user_ldap/appinfo/version | 2 +- apps/user_ldap/lib/access.php | 70 +++++++++++------- apps/user_ldap/lib/connection.php | 69 ++++++++++++------ apps/user_ldap/settings.php | 12 --- apps/user_ldap/templates/settings.php | 3 +- 6 files changed, 106 insertions(+), 151 deletions(-) diff --git a/apps/user_ldap/appinfo/update.php b/apps/user_ldap/appinfo/update.php index 179451dad6..41770cf97b 100644 --- a/apps/user_ldap/appinfo/update.php +++ b/apps/user_ldap/appinfo/update.php @@ -1,20 +1,5 @@ setConnector($connector); -$groupBE = new \OCA\user_ldap\GROUP_LDAP(); -$groupBE->setConnector($connector); - -foreach($objects as $object) { - $fetchDNSql = ' - SELECT `ldap_dn`, `owncloud_name`, `directory_uuid` - FROM `*PREFIX*ldap_'.$object.'_mapping`'; - $updateSql = ' - UPDATE `*PREFIX*ldap_'.$object.'_mapping` - SET `ldap_DN` = ?, `directory_uuid` = ? - WHERE `ldap_dn` = ?'; - - $query = OCP\DB::prepare($fetchDNSql); - $res = $query->execute(); - $DNs = $res->fetchAll(); - $updateQuery = OCP\DB::prepare($updateSql); - foreach($DNs as $dn) { - $newDN = escapeDN(mb_strtolower($dn['ldap_dn'], 'UTF-8')); - if(!empty($dn['directory_uuid'])) { - $uuid = $dn['directory_uuid']; - } elseif($object === 'user') { - $uuid = $userBE->getUUID($newDN); - //fix home folder to avoid new ones depending on the configuration - $userBE->getHome($dn['owncloud_name']); - } else { - $uuid = $groupBE->getUUID($newDN); - } - try { - $updateQuery->execute(array($newDN, $uuid, $dn['ldap_dn'])); - } catch(Exception $e) { - \OCP\Util::writeLog('user_ldap', - 'Could not update '.$object.' '.$dn['ldap_dn'].' in the mappings table. ', - \OCP\Util::WARN); - } - - } + $value = \OCP\Config::getAppValue('user_ldap', + $config.'ldap_expert_uuid_attr', 'auto'); + \OCP\Config::setAppValue('user_ldap', + $config.'ldap_expert_uuid_user_attr', $value); + \OCP\Config::setAppValue('user_ldap', + $config.'ldap_expert_uuid_group_attr', $value); } - -function escapeDN($dn) { - $aDN = ldap_explode_dn($dn, false); - unset($aDN['count']); - foreach($aDN as $key => $part) { - $value = substr($part, strpos($part, '=')+1); - $escapedValue = strtr($value, Array(','=>'\2c', '='=>'\3d', '+'=>'\2b', - '<'=>'\3c', '>'=>'\3e', ';'=>'\3b', '\\'=>'\5c', - '"'=>'\22', '#'=>'\23')); - $part = str_replace($part, $value, $escapedValue); - } - $dn = implode(',', $aDN); - - return $dn; -} - - -// SUPPORTED UPGRADE FROM Version 0.3 (ownCloud 4.5) to 0.4 (ownCloud 5) - -if(!isset($connector)) { - $connector = new \OCA\user_ldap\lib\Connection(); -} -//it is required, that connections do have ldap_configuration_active setting stored in the database -$connector->getConfiguration(); -$connector->saveConfiguration(); - -// we don't save it anymore, was a well-meant bad idea. Clean up database. -$query = OC_DB::prepare('DELETE FROM `*PREFIX*preferences` WHERE `appid` = ? AND `configkey` = ?'); -$query->execute(array('user_ldap' , 'homedir')); diff --git a/apps/user_ldap/appinfo/version b/apps/user_ldap/appinfo/version index 60a2d3e96c..44bb5d1f74 100644 --- a/apps/user_ldap/appinfo/version +++ b/apps/user_ldap/appinfo/version @@ -1 +1 @@ -0.4.0 \ No newline at end of file +0.4.1 \ No newline at end of file diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index fdf9c24612..f75a78bcb0 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -288,7 +288,7 @@ class Access extends LDAPUtility { } //second try: get the UUID and check if it is known. Then, update the DN and return the name. - $uuid = $this->getUUID($dn); + $uuid = $this->getUUID($dn, $isUser); if($uuid) { $query = \OCP\DB::prepare(' SELECT `owncloud_name` @@ -580,7 +580,9 @@ class Access extends LDAPUtility { '); //feed the DB - $insRows = $insert->execute(array($dn, $ocname, $this->getUUID($dn), $dn, $ocname)); + $insRows = $insert->execute(array($dn, $ocname, + $this->getUUID($dn, $isUser), $dn, + $ocname)); if(\OCP\DB::isError($insRows)) { return false; @@ -905,55 +907,67 @@ class Access extends LDAPUtility { * @param $force the detection should be run, even if it is not set to auto * @returns true on success, false otherwise */ - private function detectUuidAttribute($dn, $force = false) { - if(($this->connection->ldapUuidAttribute !== 'auto') && !$force) { + private function detectUuidAttribute($dn, $isUser = true, $force = false) { + if($isUser) { + $uuidAttr = 'ldapUuidUserAttribute'; + $uuidOverride = $this->connection->ldapExpertUUIDUserAttr; + } else { + $uuidAttr = 'ldapUuidGroupAttribute'; + $uuidOverride = $this->connection->ldapExpertUUIDGroupAttr; + } + + if(($this->connection->$uuidAttr !== 'auto') && !$force) { return true; } - $fixedAttribute = $this->connection->ldapExpertUUIDAttr; - if(!empty($fixedAttribute)) { - $this->connection->ldapUuidAttribute = $fixedAttribute; + if(!empty($uuidOverride) && !$force) { + $this->connection->$uuidAttr = $uuidOverride; return true; } - //for now, supported (known) attributes are entryUUID, nsuniqueid, objectGUID + //for now, supported attributes are entryUUID, nsuniqueid, objectGUID $testAttributes = array('entryuuid', 'nsuniqueid', 'objectguid', 'guid'); foreach($testAttributes as $attribute) { - \OCP\Util::writeLog('user_ldap', 'Testing '.$attribute.' as UUID attr', \OCP\Util::DEBUG); - $value = $this->readAttribute($dn, $attribute); if(is_array($value) && isset($value[0]) && !empty($value[0])) { - \OCP\Util::writeLog('user_ldap', 'Setting '.$attribute.' as UUID attr', \OCP\Util::DEBUG); - $this->connection->ldapUuidAttribute = $attribute; + \OCP\Util::writeLog('user_ldap', + 'Setting '.$attribute.' as '.$uuidAttr, + \OCP\Util::DEBUG); + $this->connection->$uuidAttr = $attribute; return true; } - \OCP\Util::writeLog('user_ldap', - 'The looked for uuid attr is not '.$attribute.', result was '.print_r($value, true), - \OCP\Util::DEBUG); } + \OCP\Util::writeLog('user_ldap', + 'Could not autodetect the UUID attribute', + \OCP\Util::ERROR); return false; } - public function getUUID($dn) { - if($this->detectUuidAttribute($dn)) { - \OCP\Util::writeLog('user_ldap', - 'UUID Checking \ UUID for '.$dn.' using '. $this->connection->ldapUuidAttribute, - \OCP\Util::DEBUG); - $uuid = $this->readAttribute($dn, $this->connection->ldapUuidAttribute); - if(!is_array($uuid) && $this->connection->ldapOverrideUuidAttribute) { - $this->detectUuidAttribute($dn, true); - $uuid = $this->readAttribute($dn, $this->connection->ldapUuidAttribute); + public function getUUID($dn, $isUser = true) { + if($isUser) { + $uuidAttr = 'ldapUuidUserAttribute'; + $uuidOverride = $this->connection->ldapExpertUUIDUserAttr; + } else { + $uuidAttr = 'ldapUuidGroupAttribute'; + $uuidOverride = $this->connection->ldapExpertUUIDGroupAttr; + } + + $uuid = false; + if($this->detectUuidAttribute($dn, $isUser)) { + $uuid = $this->readAttribute($dn, $this->connection->$uuidAttr); + if( !is_array($uuid) + && !empty($uuidOverride) + && $this->detectUuidAttribute($dn, $isUser, true)) { + $uuid = $this->readAttribute($dn, + $this->connection->$uuidAttr); } if(is_array($uuid) && isset($uuid[0]) && !empty($uuid[0])) { $uuid = $uuid[0]; - } else { - $uuid = false; } - } else { - $uuid = false; } + return $uuid; } diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index a53022c27b..93efdb4c9c 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -60,7 +60,8 @@ class Connection extends LDAPUtility { 'ldapQuotaDefault' => null, 'ldapEmailAttribute' => null, 'ldapCacheTTL' => null, - 'ldapUuidAttribute' => 'auto', + 'ldapUuidUserAttribute' => 'auto', + 'ldapUuidGroupAttribute' => 'auto', 'ldapOverrideUuidAttribute' => null, 'ldapOverrideMainServer' => false, 'ldapConfigurationActive' => false, @@ -69,7 +70,8 @@ class Connection extends LDAPUtility { 'homeFolderNamingRule' => null, 'hasPagedResultSupport' => false, 'ldapExpertUsernameAttr' => null, - 'ldapExpertUUIDAttr' => null, + 'ldapExpertUUIDUserAttr' => null, + 'ldapExpertUUIDGroupAttr' => null, ); /** @@ -120,11 +122,11 @@ class Connection extends LDAPUtility { public function __set($name, $value) { $changed = false; //only few options are writable - if($name === 'ldapUuidAttribute') { - \OCP\Util::writeLog('user_ldap', 'Set config ldapUuidAttribute to '.$value, \OCP\Util::DEBUG); + if($name === 'ldapUuidUserAttribute' || $name === 'ldapUuidGroupAttribute') { + \OCP\Util::writeLog('user_ldap', 'Set config '.$name.' to '.$value, \OCP\Util::DEBUG); $this->config[$name] = $value; if(!empty($this->configID)) { - \OCP\Config::setAppValue($this->configID, $this->configPrefix.'ldap_uuid_attribute', $value); + \OCP\Config::setAppValue($this->configID, $this->configPrefix.$name, $value); } $changed = true; } @@ -285,8 +287,10 @@ class Connection extends LDAPUtility { $this->config['ldapIgnoreNamingRules'] = \OCP\Config::getSystemValue('ldapIgnoreNamingRules', false); $this->config['ldapCacheTTL'] = $this->$v('ldap_cache_ttl'); - $this->config['ldapUuidAttribute'] - = $this->$v('ldap_uuid_attribute'); + $this->config['ldapUuidUserAttribute'] + = $this->$v('ldap_uuid_user_attribute'); + $this->config['ldapUuidGroupAttribute'] + = $this->$v('ldap_uuid_group_attribute'); $this->config['ldapOverrideUuidAttribute'] = $this->$v('ldap_override_uuid_attribute'); $this->config['homeFolderNamingRule'] @@ -299,8 +303,10 @@ class Connection extends LDAPUtility { = preg_split('/\r\n|\r|\n/', $this->$v('ldap_attributes_for_group_search')); $this->config['ldapExpertUsernameAttr'] = $this->$v('ldap_expert_username_attr'); - $this->config['ldapExpertUUIDAttr'] - = $this->$v('ldap_expert_uuid_attr'); + $this->config['ldapExpertUUIDUserAttr'] + = $this->$v('ldap_expert_uuid_user_attr'); + $this->config['ldapExpertUUIDGroupAttr'] + = $this->$v('ldap_expert_uuid_group_attr'); $this->configured = $this->validateConfiguration(); } @@ -339,7 +345,8 @@ class Connection extends LDAPUtility { 'ldap_attributes_for_user_search' => 'ldapAttributesForUserSearch', 'ldap_attributes_for_group_search' => 'ldapAttributesForGroupSearch', 'ldap_expert_username_attr' => 'ldapExpertUsernameAttr', - 'ldap_expert_uuid_attr' => 'ldapExpertUUIDAttr', + 'ldap_expert_uuid_user_attr' => 'ldapExpertUUIDUserAttr', + 'ldap_expert_uuid_group_attr' => 'ldapExpertUUIDGroupAttr', ); return $array; } @@ -413,7 +420,8 @@ class Connection extends LDAPUtility { break; case 'ldapIgnoreNamingRules': case 'ldapOverrideUuidAttribute': - case 'ldapUuidAttribute': + case 'ldapUuidUserAttribute': + case 'ldapUuidGroupAttribute': case 'hasPagedResultSupport': continue 2; } @@ -476,13 +484,23 @@ class Connection extends LDAPUtility { } $uuidAttributes = array( 'auto', 'entryuuid', 'nsuniqueid', 'objectguid', 'guid'); - if(!in_array($this->config['ldapUuidAttribute'], $uuidAttributes) - && (!is_null($this->configID))) { - \OCP\Config::setAppValue($this->configID, $this->configPrefix.'ldap_uuid_attribute', 'auto'); - \OCP\Util::writeLog('user_ldap', - 'Illegal value for the UUID Attribute, reset to autodetect.', - \OCP\Util::INFO); + $uuidSettings = array( + 'ldapUuidUserAttribute' => 'ldapExpertUUIDUserAttr', + 'ldapUuidGroupAttribute' => 'ldapExpertUUIDGroupAttr'); + $cta = array_flip($this->getConfigTranslationArray()); + foreach($uuidSettings as $defaultKey => $overrideKey) { + if( !in_array($this->config[$defaultKey], $uuidAttributes) + && is_null($this->config[$overrideKey]) + && !is_null($this->configID)) { + \OCP\Config::setAppValue($this->configID, + $this->configPrefix.$cta[$defaultKey], + 'auto'); + \OCP\Util::writeLog('user_ldap', + 'Illegal value for'.$defaultKey.', reset to autodetect.', + \OCP\Util::DEBUG); + } } + if(empty($this->config['ldapBackupPort'])) { //force default $this->config['ldapBackupPort'] = $this->config['ldapPort']; @@ -502,8 +520,6 @@ class Connection extends LDAPUtility { \OCP\Util::INFO); } - - //second step: critical checks. If left empty or filled wrong, set as unconfigured and give a warning. $configurationOK = true; if(empty($this->config['ldapHost'])) { @@ -552,8 +568,11 @@ class Connection extends LDAPUtility { $configurationOK = false; } - if(!empty($this->config['ldapExpertUUIDAttr'])) { - $this->config['ldapUuidAttribute'] = $this->config['ldapExpertUUIDAttr']; + if(!empty($this->config['ldapExpertUUIDUserAttr'])) { + $this->config['ldapUuidUserAttribute'] = $this->config['ldapExpertUUIDUserAttr']; + } + if(!empty($this->config['ldapExpertUUIDGroupAttr'])) { + $this->config['ldapUuidGroupAttribute'] = $this->config['ldapExpertUUIDGroupAttr']; } return $configurationOK; @@ -587,15 +606,17 @@ class Connection extends LDAPUtility { 'ldap_email_attr' => '', 'ldap_group_member_assoc_attribute' => 'uniqueMember', 'ldap_cache_ttl' => 600, - 'ldap_uuid_attribute' => 'auto', + 'ldap_uuid_user_attribute' => 'auto', + 'ldap_uuid_group_attribute' => 'auto', 'ldap_override_uuid_attribute' => 0, 'home_folder_naming_rule' => '', 'ldap_turn_off_cert_check' => 0, 'ldap_configuration_active' => 1, 'ldap_attributes_for_user_search' => '', 'ldap_attributes_for_group_search' => '', - 'ldap_expert_username_attr' => '', - 'ldap_expert_uuid_attr' => '', + 'ldap_expert_username_attr' => '', + 'ldap_expert_uuid_user_attr' => '', + 'ldap_expert_uuid_group_attr' => '', ); } diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php index b7070f2318..f20bc19118 100644 --- a/apps/user_ldap/settings.php +++ b/apps/user_ldap/settings.php @@ -25,18 +25,6 @@ OC_Util::checkAdminUser(); -$params = array('ldap_host', 'ldap_port', 'ldap_backup_host', - 'ldap_backup_port', 'ldap_override_main_server', 'ldap_dn', - 'ldap_agent_password', 'ldap_base', 'ldap_base_users', - 'ldap_base_groups', 'ldap_userlist_filter', - 'ldap_login_filter', 'ldap_group_filter', 'ldap_display_name', - 'ldap_group_display_name', 'ldap_tls', - 'ldap_turn_off_cert_check', 'ldap_nocase', 'ldap_quota_def', - 'ldap_quota_attr', 'ldap_email_attr', - 'ldap_group_member_assoc_attribute', 'ldap_cache_ttl', - 'home_folder_naming_rule' - ); - OCP\Util::addscript('user_ldap', 'settings'); OCP\Util::addstyle('user_ldap', 'settings'); diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index e214d57fb1..319dc38a62 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -100,7 +100,8 @@

t('Override UUID detection'));?>

t('By default, the UUID attribute is automatically detected. The UUID attribute is used to doubtlessly identify LDAP users and groups. Also, the internal username will be created based on the UUID, if not specified otherwise above. You can override the setting and pass an attribute of your choice. You must make sure that the attribute of your choice can be fetched for both users and groups and it is unique. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users and groups.'));?>

-

+

+

t('Username-LDAP User Mapping'));?>

t('Usernames are used to store and assign (meta) data. In order to precisely identify and recognize users, each LDAP user will have a internal username. This requires a mapping from username to LDAP user. The created username is mapped to the UUID of the LDAP user. Additionally the DN is cached as well to reduce LDAP interaction, but it is not used for identification. If the DN changes, the changes will be found. The internal username is used all over. Clearing the mappings will have leftovers everywhere. Clearing the mappings is not configuration sensitive, it affects all LDAP configurations! Never clear the mappings in a production environment, only in a testing or experimental stage.'));?>