Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions apps/user_ldap/lib/access.php
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,16 @@ public function cacheUserDisplayName($ocName, $displayName) {
$this->connection->writeToCache($cacheKeyTrunk.$ocName, $displayName);
}

/**
* caches the user display name
* @param string $ocName the internal ownCloud username
* @param string|false $home the home directory path
*/
public function cacheUserHome($ocName, $home) {
$cacheKey = 'getHome'.$ocName;
$this->connection->writeToCache($cacheKey, $home);
}

/**
* creates a unique name for internal ownCloud use for users. Don't call it directly.
* @param string $name the display name of the object
Expand Down
25 changes: 25 additions & 0 deletions apps/user_ldap/lib/user/manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,31 @@ private function checkAccess() {
}
}

/**
* returns a list of attributes that will be processed further, e.g. quota,
* email, displayname, or others.
* @return string[]
*/
public function getAttributes() {
$attrs = array('dn', 'jpegphoto', 'thumbnailphoto');
$possible = array(
$this->access->connection->ldapQuotaAttribute,
$this->access->connection->ldapEmailAttribute,
$this->access->connection->ldapUserDisplayName,
);
foreach($possible as $attr) {
if(!is_null($attr)) {
$attrs[] = $attr;
}
}
$homeRule = $this->access->connection->homeFolderNamingRule;
if(strpos($homeRule, 'attr:') === 0) {
$attrs[] = substr($homeRule, strlen('attr:'));
}

return $attrs;
}

/**
* @brief returns a User object by it's DN or ownCloud username
* @param string the DN or username of the user
Expand Down
129 changes: 104 additions & 25 deletions apps/user_ldap/lib/user/user.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,46 @@ public function update() {
}
}

/**
* processes results from LDAP for attributes as returned by getAttributesToRead()
* @param array $ldapEntry the user entry as retrieved from LDAP
*/
public function processAttributes($ldapEntry) {
$this->markRefreshTime();
//Quota
if(isset($ldapEntry[$this->connection->ldapQuotaAttribute])) {
$this->updateQuota($ldapEntry[$this->connection->ldapQuotaAttribute]);
}
//Email
if(isset($ldapEntry[$this->connection->ldapEmailAttribute])) {
$this->updateEmail($ldapEntry[$this->connection->ldapEmailAttribute]);
}
//displayName
if(isset($ldapEntry[$this->connection->ldapUserDisplayName])) {
$displayName = $ldapEntry[$this->connection->ldapUserDisplayName];
if(!empty($displayName)) {
$this->access->cacheUserDisplayName($this->getUsername(), $displayName);
}
}
//homePath
if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
$attr = substr($this->connection->homeFolderNamingRule, strlen('attr:'));
if(isset($ldapEntry[$attr])) {
$this->access->cacheUserHome(
$this->getUsername(), $this->getHomePath($ldapEntry[$attr]));
}
}
//Avatar
$attrs = array('jpegphoto', 'thumbnailphoto');
foreach ($attrs as $attr) {
if(isset($ldapEntry[$attr])) {
$this->avatarImage = $ldapEntry[$attr];
$this->updateAvatar();
break;
}
}
}

/**
* @brief returns the LDAP DN of the user
* @return string
Expand Down Expand Up @@ -177,6 +217,38 @@ public function getAvatarImage() {
return $this->avatarImage;
}

/**
* returns the home directory of the user if specified by LDAP settings
* @param string $valueFromLDAP i known; avoids a read operation on LDAP
* @return string|false
*/
public function getHomePath($valueFromLDAP = null) {
$path = $valueFromLDAP;
if(is_null($valueFromLDAP)) {
if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
$attr = substr($this->connection->homeFolderNamingRule, strlen('attr:'));
$result = $this->access->readAttribute($this->getDN(), $attr);
if($result && isset($result[0])) {
$path = $result[0];
}
}
}
if(empty($path)) {
return false;
}
//if attribute's value is an absolute path take this, otherwise append it to data dir
//check for / at the beginning or pattern c:\ resp. c:/
if('/' === $path[0]
|| (3 < strlen($path) && ctype_alpha($path[0])
&& $path[1] === ':' && ('\\' === $path[2] || '/' === $path[2]))) {
$homeDir = $path;
} else {
$homeDir = $this->config->getSystemValue(
'datadirectory', \OC::$SERVERROOT.'/data') . '/' . $path;
}
return $homeDir;
}

/**
* @brief marks the user as having logged in at least once
* @return null
Expand Down Expand Up @@ -228,50 +300,57 @@ private function wasRefreshed($feature) {
}

/**
* @brief fetches the email from LDAP and stores it as ownCloud user value
* fetches the email from LDAP and stores it as ownCloud user value
* @param string $valueFromLDAP if known, to save an LDAP read request
* @return null
*/
public function updateEmail() {
public function updateEmail($valueFromLDAP = null) {
if($this->wasRefreshed('email')) {
return;
}

$email = null;
$emailAttribute = $this->connection->ldapEmailAttribute;
if(!empty($emailAttribute)) {
$aEmail = $this->access->readAttribute($this->dn, $emailAttribute);
if($aEmail && (count($aEmail) > 0)) {
$email = $aEmail[0];
}
if(!is_null($email)) {
$this->config->setUserValue(
$this->uid, 'settings', 'email', $email);
}
$email = $valueFromLDAP;
if(is_null($valueFromLDAP)) {
$emailAttribute = $this->connection->ldapEmailAttribute;
if(!empty($emailAttribute)) {
$aEmail = $this->access->readAttribute($this->dn, $emailAttribute);
if(is_array($aEmail) && (count($aEmail) > 0)) {
$email = $aEmail[0];
}
}
}

if(!is_null($email)) {
$this->config->setUserValue(
$this->uid, 'settings', 'email', $email);
}
}

/**
* @brief fetches the quota from LDAP and stores it as ownCloud user value
* fetches the quota from LDAP and stores it as ownCloud user value
* @param string $valueFromLDAP the quota attribute's value can be passed,
* to save the readAttribute request
* @return null
*/
public function updateQuota() {
public function updateQuota($valueFromLDAP = null) {
if($this->wasRefreshed('quota')) {
return;
}

$quota = null;
$quotaDefault = $this->connection->ldapQuotaDefault;
$quotaAttribute = $this->connection->ldapQuotaAttribute;
if(!empty($quotaDefault)) {
$quota = $quotaDefault;
}
if(!empty($quotaAttribute)) {
$aQuota = $this->access->readAttribute($this->dn, $quotaAttribute);
//can be null
$quota = !is_null($valueFromLDAP) ? $valueFromLDAP
: $this->connection->ldapQuotaDefault;
if(is_null($valueFromLDAP)) {
$quotaAttribute = $this->connection->ldapQuotaAttribute;
if(!empty($quotaAttribute)) {
$aQuota = $this->access->readAttribute($this->dn, $quotaAttribute);

if($aQuota && (count($aQuota) > 0)) {
$quota = $aQuota[0];
if($aQuota && (count($aQuota) > 0)) {
$quota = $aQuota[0];
}
}
}

if(!is_null($quota)) {
$this->config->setUserValue($this->uid, 'files', 'quota', $quota);
}
Expand Down
14 changes: 10 additions & 4 deletions apps/user_ldap/tests/user_ldap.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
class Test_User_Ldap_Direct extends \Test\TestCase {
protected $backend;
protected $access;
protected $configMock;

protected function setUp() {
parent::setUp();
Expand Down Expand Up @@ -57,8 +58,9 @@ private function getAccessMock() {
$conMethods,
array($lw, null, null));

$this->configMock = $this->getMock('\OCP\IConfig');
$um = new \OCA\user_ldap\lib\user\Manager(
$this->getMock('\OCP\IConfig'),
$this->configMock,
$this->getMock('\OCA\user_ldap\lib\FilesystemHelper'),
$this->getMock('\OCA\user_ldap\lib\LogWrapper'),
$this->getMock('\OCP\IAvatarManager'),
Expand Down Expand Up @@ -123,7 +125,7 @@ private function prepareAccessForCheckPassword(&$access, $noDisplayName = false)
->method('fetchListOfUsers')
->will($this->returnCallback(function($filter) {
if($filter === 'roland') {
return array('dnOfRoland,dc=test');
return array(array('dn'=> 'dnOfRoland,dc=test'));
}
return array();
}));
Expand Down Expand Up @@ -473,14 +475,18 @@ public function testGetHome() {
}
}));

$datadir = \OCP\Config::getSystemValue('datadirectory',
\OC::$SERVERROOT.'/data');
$this->configMock->expects($this->once())
->method('getSystemValue')
->will($this->returnValue($datadir));

//absolut path
$result = $backend->getHome('gunslinger');
$this->assertEquals('/tmp/rolandshome/', $result);

//datadir-relativ path
$result = $backend->getHome('ladyofshadows');
$datadir = \OCP\Config::getSystemValue('datadirectory',
\OC::$SERVERROOT.'/data');
$this->assertEquals($datadir.'/susannah/', $result);

//no path at all – triggers OC default behaviour
Expand Down
48 changes: 15 additions & 33 deletions apps/user_ldap/user_ldap.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,29 +55,31 @@ public function canChangeAvatar($uid) {
*/
public function checkPassword($uid, $password) {
$uid = $this->access->escapeFilterPart($uid);
$attrs = $this->access->userManager->getAttributes();

//find out dn of the user name
$filter = \OCP\Util::mb_str_replace(
'%uid', $uid, $this->access->connection->ldapLoginFilter, 'UTF-8');
$ldap_users = $this->access->fetchListOfUsers($filter, 'dn');
if(count($ldap_users) < 1) {
$ldapResult = $this->access->fetchListOfUsers($filter, $attrs, 1);
if(count($ldapResult) < 1) {
return false;
}
$dn = $ldap_users[0];
$user = $this->access->userManager->get($dn);
$userEntry = $ldapResult[0];
$user = $this->access->userManager->get($userEntry['dn']);
if(is_null($user)) {
\OCP\Util::writeLog('user_ldap',
'LDAP Login: Could not get user object for DN ' . $dn .
'LDAP Login: Could not get user object for DN ' . $userEntry['dn'] .
'. Maybe the LDAP entry has no set display name attribute?',
\OCP\Util::WARN);
return false;
}
if($user->getUsername() !== false) {
//are the credentials OK?
if(!$this->access->areCredentialsValid($dn, $password)) {
if(!$this->access->areCredentialsValid($userEntry['dn'], $password)) {
return false;
}

$this->access->cacheUserExists($user->getUsername());
$user->processAttributes($userEntry);
$user->markLogin();

return $user->getUsername();
Expand Down Expand Up @@ -172,7 +174,7 @@ public function deleteUser($uid) {
/**
* get the user's home directory
* @param string $uid the username
* @return boolean
* @return string|false
*/
public function getHome($uid) {
// user Exists check required as it is not done in user proxy!
Expand All @@ -184,32 +186,12 @@ public function getHome($uid) {
if($this->access->connection->isCached($cacheKey)) {
return $this->access->connection->getFromCache($cacheKey);
}
if(strpos($this->access->connection->homeFolderNamingRule, 'attr:') === 0) {
$attr = substr($this->access->connection->homeFolderNamingRule, strlen('attr:'));
$homedir = $this->access->readAttribute(
$this->access->username2dn($uid), $attr);
if($homedir && isset($homedir[0])) {
$path = $homedir[0];
//if attribute's value is an absolute path take this, otherwise append it to data dir
//check for / at the beginning or pattern c:\ resp. c:/
if(
'/' === $path[0]
|| (3 < strlen($path) && ctype_alpha($path[0])
&& $path[1] === ':' && ('\\' === $path[2] || '/' === $path[2]))
) {
$homedir = $path;
} else {
$homedir = \OCP\Config::getSystemValue('datadirectory',
\OC::$SERVERROOT.'/data' ) . '/' . $homedir[0];
}
$this->access->connection->writeToCache($cacheKey, $homedir);
return $homedir;
}
}

//false will apply default behaviour as defined and done by OC_User
$this->access->connection->writeToCache($cacheKey, false);
return false;
$user = $this->access->userManager->get($uid);
$path = $user->getHomePath();
$this->access->cacheUserHome($uid, $path);

return $path;
}

/**
Expand Down