public function testUseBackupServer() { $mainHost = 'ldap://nixda.ldap'; $backupHost = 'ldap://fallback.ldap'; $config = ['ldapConfigurationActive' => true, 'ldapHost' => $mainHost, 'ldapPort' => 389, 'ldapBackupHost' => $backupHost, 'ldapBackupPort' => 389, 'ldapAgentName' => 'uid=agent', 'ldapAgentPassword' => 'SuchASecret']; $this->connection->setIgnoreValidation(true); $this->connection->setConfiguration($config); $this->ldap->expects($this->any())->method('isResource')->will($this->returnValue(true)); $this->ldap->expects($this->any())->method('setOption')->will($this->returnValue(true)); $this->ldap->expects($this->exactly(3))->method('connect')->will($this->returnValue('ldapResource')); // Not called often enough? Then, the fallback to the backup server is broken. $this->connection->expects($this->exactly(4))->method('getFromCache')->with('overrideMainServer')->will($this->onConsecutiveCalls(false, false, true, true)); $this->connection->expects($this->once())->method('writeToCache')->with('overrideMainServer', true); $isThrown = false; $this->ldap->expects($this->exactly(3))->method('bind')->will($this->returnCallback(function () use(&$isThrown) { if (!$isThrown) { $isThrown = true; throw new \OC\ServerNotAvailableException(); } return true; })); $this->connection->init(); $this->connection->resetConnectionResource(); // with the second init() we test whether caching works $this->connection->init(); }
/** * tests the specified connection * @param string $configID * @return int */ protected function testConfig($configID) { $lw = new \OCA\user_ldap\lib\LDAP(); $connection = new Connection($lw, $configID); //ensure validation is run before we attempt the bind $connection->getConfiguration(); if (!$connection->setConfiguration(array('ldap_configuration_active' => 1))) { return 1; } if ($connection->bind()) { return 0; } return 2; }
/** * Prepares a paged search, if possible * @param string $filter the LDAP filter for the search * @param string[] $bases an array containing the LDAP subtree(s) that shall be searched * @param string[] $attr optional, when a certain attribute shall be filtered outside * @param int $limit * @param int $offset * @return bool|true */ private function initPagedSearch($filter, $bases, $attr, $limit, $offset) { $pagedSearchOK = false; if ($this->connection->hasPagedResultSupport && $limit !== 0) { $offset = intval($offset); //can be null \OCP\Util::writeLog('user_ldap', 'initializing paged search for Filter ' . $filter . ' base ' . print_r($bases, true) . ' attr ' . print_r($attr, true) . ' limit ' . $limit . ' offset ' . $offset, \OCP\Util::DEBUG); //get the cookie from the search for the previous search, required by LDAP foreach ($bases as $base) { $cookie = $this->getPagedResultCookie($base, $filter, $limit, $offset); if (empty($cookie) && $cookie !== "0" && $offset > 0) { // no cookie known, although the offset is not 0. Maybe cache run out. We need // to start all over *sigh* (btw, Dear Reader, did you know LDAP paged // searching was designed by MSFT?) // Lukas: No, but thanks to reading that source I finally know! // '0' is valid, because 389ds $reOffset = $offset - $limit < 0 ? 0 : $offset - $limit; //a bit recursive, $offset of 0 is the exit \OCP\Util::writeLog('user_ldap', 'Looking for cookie L/O ' . $limit . '/' . $reOffset, \OCP\Util::INFO); $this->search($filter, array($base), $attr, $limit, $reOffset, true); $cookie = $this->getPagedResultCookie($base, $filter, $limit, $offset); //still no cookie? obviously, the server does not like us. Let's skip paging efforts. //TODO: remember this, probably does not change in the next request... if (empty($cookie) && $cookie !== '0') { // '0' is valid, because 389ds $cookie = null; } } if (!is_null($cookie)) { //since offset = 0, this is a new search. We abandon other searches that might be ongoing. $this->abandonPagedSearch(); $pagedSearchOK = $this->ldap->controlPagedResult($this->connection->getConnectionResource(), $limit, false, $cookie); if (!$pagedSearchOK) { return false; } \OCP\Util::writeLog('user_ldap', 'Ready for a paged search', \OCP\Util::DEBUG); } else { \OCP\Util::writeLog('user_ldap', 'No paged search for us, Cpt., Limit ' . $limit . ' Offset ' . $offset, \OCP\Util::INFO); } } /* ++ Fixing RHDS searches with pages with zero results ++ * We coudn't get paged searches working with our RHDS for login ($limit = 0), * due to pages with zero results. * So we added "&& !empty($this->lastCookie)" to this test to ignore pagination * if we don't have a previous paged search. */ } else { if ($this->connection->hasPagedResultSupport && $limit === 0 && !empty($this->lastCookie)) { // a search without limit was requested. However, if we do use // Paged Search once, we always must do it. This requires us to // initialize it with the configured page size. $this->abandonPagedSearch(); // in case someone set it to 0 … use 500, otherwise no results will // be returned. $pageSize = intval($this->connection->ldapPagingSize) > 0 ? intval($this->connection->ldapPagingSize) : 500; $pagedSearchOK = $this->ldap->controlPagedResult($this->connection->getConnectionResource(), $pageSize, false, ''); } } return $pagedSearchOK; }
public function getMemberOfGroups() { $cacheKey = 'getMemberOf' . $this->getUsername(); if ($this->connection->isCached($cacheKey)) { return $this->connection->getFromCache($cacheKey); } $groupDNs = $this->access->readAttribute($this->getDN(), 'memberOf'); $this->connection->writeToCache($cacheKey, $groupDNs); return $groupDNs; }
/** * Prepares a paged search, if possible * @param string $filter the LDAP filter for the search * @param string[] $bases an array containing the LDAP subtree(s) that shall be searched * @param string[] $attr optional, when a certain attribute shall be filtered outside * @param int $limit * @param int $offset * @return bool|true */ private function initPagedSearch($filter, $bases, $attr, $limit, $offset) { $pagedSearchOK = false; if($this->connection->hasPagedResultSupport && ($limit !== 0)) { $offset = intval($offset); //can be null \OCP\Util::writeLog('user_ldap', 'initializing paged search for Filter '.$filter.' base '.print_r($bases, true) .' attr '.print_r($attr, true). ' limit ' .$limit.' offset '.$offset, \OCP\Util::DEBUG); //get the cookie from the search for the previous search, required by LDAP foreach($bases as $base) { $cookie = $this->getPagedResultCookie($base, $filter, $limit, $offset); if(empty($cookie) && ($offset > 0)) { // no cookie known, although the offset is not 0. Maybe cache run out. We need // to start all over *sigh* (btw, Dear Reader, did you know LDAP paged // searching was designed by MSFT?) // Lukas: No, but thanks to reading that source I finally know! $reOffset = ($offset - $limit) < 0 ? 0 : $offset - $limit; //a bit recursive, $offset of 0 is the exit \OCP\Util::writeLog('user_ldap', 'Looking for cookie L/O '.$limit.'/'.$reOffset, \OCP\Util::INFO); $this->search($filter, array($base), $attr, $limit, $reOffset, true); $cookie = $this->getPagedResultCookie($base, $filter, $limit, $offset); //still no cookie? obviously, the server does not like us. Let's skip paging efforts. //TODO: remember this, probably does not change in the next request... if(empty($cookie)) { $cookie = null; } } if(!is_null($cookie)) { //since offset = 0, this is a new search. We abandon other searches that might be ongoing. $this->abandonPagedSearch(); $pagedSearchOK = $this->ldap->controlPagedResult( $this->connection->getConnectionResource(), $limit, false, $cookie); if(!$pagedSearchOK) { return false; } \OCP\Util::writeLog('user_ldap', 'Ready for a paged search', \OCP\Util::DEBUG); } else { \OCP\Util::writeLog('user_ldap', 'No paged search for us, Cpt., Limit '.$limit.' Offset '.$offset, \OCP\Util::INFO); } } } return $pagedSearchOK; }
/** * sets up the LDAP configuration to be used for the test */ private function initConnection() { $this->connection = new \OCA\user_ldap\lib\Connection($this->ldap, '', null); $this->connection->setConfiguration([ 'ldapHost' => $this->server['host'], 'ldapPort' => $this->server['port'], 'ldapBase' => $this->base, 'ldapAgentName' => $this->server['dn'], 'ldapAgentPassword' => $this->server['pwd'], 'ldapUserFilter' => 'objectclass=inetOrgPerson', 'ldapUserDisplayName' => 'displayName', 'ldapGroupDisplayName' => 'cn', 'ldapLoginFilter' => 'uid=%uid', 'ldapCacheTTL' => 0, 'ldapConfigurationActive' => 1, ]); }
/** * sets up the LDAP configuration to be used for the test */ protected function initConnection() { $this->connection = new Connection($this->ldap, '', null); $this->connection->setConfiguration(['ldapHost' => $this->server['host'], 'ldapPort' => $this->server['port'], 'ldapBase' => $this->base, 'ldapAgentName' => $this->server['dn'], 'ldapAgentPassword' => $this->server['pwd'], 'ldapUserFilter' => 'objectclass=inetOrgPerson', 'ldapUserDisplayName' => 'cn', 'ldapGroupDisplayName' => 'cn', 'ldapLoginFilter' => '(|(uid=%uid)(samaccountname=%uid))', 'ldapCacheTTL' => 0, 'ldapConfigurationActive' => 1]); }