diff options
author | Arthur Schiwon <blizzz@owncloud.com> | 2013-10-04 16:33:37 +0200 |
---|---|---|
committer | Arthur Schiwon <blizzz@owncloud.com> | 2013-10-17 19:13:27 +0200 |
commit | 3b1822cf91407f243f18311b8abc273ad2eb1b11 (patch) | |
tree | dce41cedcf3916bd9ef4951b74fec029fb9636c7 /apps/user_ldap/lib/wizard.php | |
parent | 8290929aa6fcb1e62e79d7acf8bf310c8d6f94d7 (diff) | |
download | nextcloud-server-3b1822cf91407f243f18311b8abc273ad2eb1b11.tar.gz nextcloud-server-3b1822cf91407f243f18311b8abc273ad2eb1b11.zip |
LDAP Wizard: add detection, load and save of LDAP objectClasses for filter purposes
Diffstat (limited to 'apps/user_ldap/lib/wizard.php')
-rw-r--r-- | apps/user_ldap/lib/wizard.php | 150 |
1 files changed, 149 insertions, 1 deletions
diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index ad71fd10f63..170af44e118 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -28,6 +28,10 @@ class Wizard extends LDAPUtility { protected $configuration; protected $result; + const LRESULT_PROCESSED_OK = 0; + const LRESULT_PROCESSED_INVALID = 1; + const LRESULT_PROCESSED_SKIP = 2; + /** * @brief Constructor * @param $configuration an instance of Configuration @@ -48,6 +52,51 @@ class Wizard extends LDAPUtility { } } + public function determineObjectClasses() { + if(!$this->checkRequirements(array('ldapHost', + 'ldapPort', + 'ldapAgentName', + 'ldapAgentPassword', + 'ldapBase', + ))) { + return false; + } + $cr = $this->getConnection(); + if(!$cr) { + throw new \Excpetion('Could not connect to LDAP'); + } + + $p = 'objectclass='; + $obclasses = array($p.'inetOrgPerson', $p.'person', + $p.'organizationalPerson', $p.'user', + $p.'posixAccount', $p.'*'); + + $maxEntryObjC = ''; + $availableObjectClasses = + $this->cumulativeSearchOnAttribute($obclasses, 'objectclass', + true, $maxEntryObjC); + if(is_array($availableObjectClasses) + && count($availableObjectClasses) > 0) { + $this->result->addOptions('ldap_userfilter_objectclass', + $availableObjectClasses); + } else { + throw new \Exception(self::$l->t('Could not find any objectClass')); + } + $setOCs = $this->configuration->ldapUserFilterObjectclass; + file_put_contents('/tmp/set', print_r($setOCs, true)); + if(is_array($setOCs) && !empty($setOCs)) { + //something is already configured? pre-select it. + $this->result->addChange('ldap_userfilter_objectclass', $setOCs); + } else if(!empty($maxEntryObjC)) { + //new? pre-select something hopefully sane + $maxEntryObjC = str_replace($p, '', $maxEntryObjC); + $this->result->addChange('ldap_userfilter_objectclass', + $maxEntryObjC); + } + + return $this->result; + } + /** * Tries to determine the port, requires given Host, User DN and Password * @returns mixed WizardResult on success, false otherwise @@ -55,7 +104,8 @@ class Wizard extends LDAPUtility { public function guessPortAndTLS() { if(!$this->checkRequirements(array('ldapHost', 'ldapAgentName', - 'ldapAgentPassword'))) { + 'ldapAgentPassword' + ))) { return false; } $this->checkHost(); @@ -266,6 +316,104 @@ class Wizard extends LDAPUtility { return true; } + /** + * @brief does a cumulativeSearch on LDAP to get different values of a + * specified attribute + * @param $filters array, the filters that shall be used in the search + * @param $attr the attribute of which a list of values shall be returned + * @param $lfw bool, whether the last filter is a wildcard which shall not + * be processed if there were already findings, defaults to true + * @param $maxF string. if not null, this variable will have the filter that + * yields most result entries + * @return mixed, an array with the values on success, false otherwise + * + */ + private function cumulativeSearchOnAttribute($filters, $attr, $lfw = true, &$maxF = null) { + $dnRead = array(); + $foundItems = array(); + $maxEntries = 0; + if(!is_array($this->configuration->ldapBase) || !isset($this->configuration->ldapBase[0])) { + return false; + } + $base = $this->configuration->ldapBase[0]; + $cr = $this->getConnection(); + if(!is_resource($cr)) { + return false; + } + foreach($filters as $filter) { + if($lfw && count($foundItems) > 0) { + continue; + } + $rr = $this->ldap->search($cr, $base, $filter, array($attr)); + if(!$this->ldap->isResource($rr)) { + \OCP\Util::writeLog('user_ldap', 'Search failed, Base '.$base, \OCP\Util::DEBUG); + continue; + } + $entries = $this->ldap->countEntries($cr, $rr); + $getEntryFunc = 'firstEntry'; + if(($entries !== false) && ($entries > 0)) { + if(!is_null($maxF) && $entries > $maxEntries) { + $maxEntries = $entries; + $maxF = $filter; + } + do { + $entry = $this->ldap->$getEntryFunc($cr, $rr); + if(!$this->ldap->isResource($entry)) { + continue 2; + } + $attributes = $this->ldap->getAttributes($cr, $entry); + $dn = $this->ldap->getDN($cr, $entry); + if($dn === false || in_array($dn, $dnRead)) { + continue; + } + $state = $this->getAttributeValuesFromEntry($attributes, + $attr, + $foundItems); + $dnRead[] = $dn; + $getEntryFunc = 'nextEntry'; + $rr = $entry; //will be expected by nextEntry next round + } while($state === self::LRESULT_PROCESSED_SKIP + || $this->ldap->isResource($entry)); + } + } + + return $foundItems; + } + + /** + * @brief appends a list of values fr + * @param $result resource, the return value from ldap_get_attributes + * @param $attribute string, the attribute values to look for + * @param &$known array, new values will be appended here + * @return int, state on of the class constants LRESULT_PROCESSED_OK, + * LRESULT_PROCESSED_INVALID or LRESULT_PROCESSED_SKIP + */ + private function getAttributeValuesFromEntry($result, $attribute, &$known) { + if(!is_array($result) + || !isset($result['count']) + || !$result['count'] > 0) { + return self::LRESULT_PROCESSED_INVALID; + } + + //strtolower on all keys for proper comparison + $result = \OCP\Util::mb_array_change_key_case($result); + $attribute = strtolower($attribute); + if(isset($result[$attribute])) { + foreach($result[$attribute] as $key => $val) { + if($key === 'count') { + continue; + } + if(!in_array($val, $known)) { + \OCP\Util::writeLog('user_ldap', 'Found objclass '.$val, \OCP\Util::DEBUG); + $known[] = $val; + } + } + return self::LRESULT_PROCESSED_OK; + } else { + return self::LRESULT_PROCESSED_SKIP; + } + } + private function getConnection() { $cr = $this->ldap->connect( $this->configuration->ldapHost.':'.$this->configuration->ldapPort, |