Skip to content

Commit

Permalink
restore ldap_password_pr
Browse files Browse the repository at this point in the history
  • Loading branch information
GitHubUser4234 committed Aug 30, 2016
1 parent f4dfd1f commit 81af16b
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 1 deletion.
15 changes: 15 additions & 0 deletions apps/user_ldap/js/wizard/wizardTabAdvanced.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ OCA = OCA || {};
$element: $('#ldap_paging_size'),
setMethod: 'setPagingSize'
},
ldap_turn_on_pwd_change: {
$element: $('#ldap_turn_on_pwd_change'),
setMethod: 'setPasswordChangeEnabled'
},

//Special Attributes
ldap_quota_attr: {
Expand Down Expand Up @@ -288,6 +292,17 @@ OCA = OCA || {};
setPagingSize: function(size) {
this.setElementValue(this.managedItems.ldap_paging_size.$element, size);
},

/**
* sets whether the password changes per user should be enabled
*
* @param {string} doPasswordChange contains an int
*/
setPasswordChangeEnabled: function(doPasswordChange) {
this.setElementValue(
this.managedItems.ldap_turn_on_pwd_change.$element, doPasswordChange
);
},

/**
* sets the email attribute
Expand Down
23 changes: 23 additions & 0 deletions apps/user_ldap/lib/Access.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,29 @@ public function readAttribute($dn, $attr, $filter = 'objectClass=*') {
\OCP\Util::writeLog('user_ldap', 'Requested attribute '.$attr.' not found for '.$dn, \OCP\Util::DEBUG);
return false;
}

/**
* Set password for an LDAP user identified by a DN
* @param string $userDN the user in question
* @param LDAP $password the new password
* @return bool
*/
public function setPassword($userDN, $password) {
if(!$this->checkConnection()) {
\OCP\Util::writeLog('user_ldap',
'No LDAP Connector assigned, access impossible for setPassword.',
\OCP\Util::WARN);
return false;
}
$cr = $this->connection->getConnectionResource();
if(!$this->ldap->isResource($cr)) {
//LDAP not available
\OCP\Util::writeLog('user_ldap', 'LDAP resource not available.', \OCP\Util::DEBUG);
return false;
}

return $this->ldap->setPassword($cr, $userDN, $password);
}

/**
* checks whether the given attributes value is probably a DN
Expand Down
3 changes: 3 additions & 0 deletions apps/user_ldap/lib/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class Configuration {
'lastJpegPhotoLookup' => null,
'ldapNestedGroups' => false,
'ldapPagingSize' => null,
'turnOnPasswordChange' => false,
'ldapDynamicGroupMemberURL' => null,
);

Expand Down Expand Up @@ -448,6 +449,7 @@ public function getDefaults() {
'last_jpegPhoto_lookup' => 0,
'ldap_nested_groups' => 0,
'ldap_paging_size' => 500,
'ldap_turn_on_pwd_change' => 0,
'ldap_experienced_admin' => 0,
'ldap_dynamic_group_member_url' => '',
);
Expand Down Expand Up @@ -504,6 +506,7 @@ public function getConfigTranslationArray() {
'last_jpegPhoto_lookup' => 'lastJpegPhotoLookup',
'ldap_nested_groups' => 'ldapNestedGroups',
'ldap_paging_size' => 'ldapPagingSize',
'ldap_turn_on_pwd_change' => 'turnOnPasswordChange',
'ldap_experienced_admin' => 'ldapExperiencedAdmin',
'ldap_dynamic_group_member_url' => 'ldapDynamicGroupMemberURL',
);
Expand Down
15 changes: 15 additions & 0 deletions apps/user_ldap/lib/LDAP.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
namespace OCA\User_LDAP;

use OC\ServerNotAvailableException;
use OC\HintException;

class LDAP implements ILDAPWrapper {
protected $curFunc = '';
Expand Down Expand Up @@ -192,6 +193,16 @@ public function search($link, $baseDN, $filter, $attr, $attrsOnly = 0, $limit =
return $this->invokeLDAPMethod('search', $link, $baseDN, $filter, $attr, $attrsOnly, $limit);
}

/**
* @param LDAP $link
* @param string $userDN
* @param string $password
* @return bool
*/
public function setPassword($link, $userDN, $password) {
return $this->invokeLDAPMethod('mod_replace', $link, $userDN, array('userPassword' => $password));
}

/**
* @param LDAP $link
* @param string $option
Expand Down Expand Up @@ -293,6 +304,10 @@ private function postFunctionCall() {
$errorCode.') after calling '.
$this->curFunc,
\OCP\Util::DEBUG);
if ($errorCode === 19) { // constraint violation
ldap_get_option($this->curArgs[0], LDAP_OPT_ERROR_STRING, $extended_error);
throw new HintException(!empty($extended_error)?$extended_error:$errorMsg, '', $errorCode);
}
}
}
}
Expand Down
38 changes: 37 additions & 1 deletion apps/user_ldap/lib/User_LDAP.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,41 @@ public function checkPassword($uid, $password) {
return false;
}

/**
* Set password
* @param string $uid The username
* @param string $password The new password
* @return bool
*/
public function setPassword($uid, $password) {
try {
$ldapRecord = $this->getLDAPUserByLoginName($uid);
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, ['app' => 'user_ldap']);
return false;
}
$dn = $ldapRecord['dn'][0];
$user = $this->access->userManager->get($dn);

if(!$user instanceof User) {
\OC::$server->getLogger()->warn('LDAP setPassword: Could not get user object for DN ' . $dn .
'. Maybe the LDAP entry has no set display name attribute?');
return false;
}
if($user->getUsername() !== false && $this->access->setPassword($this->access->username2dn($uid), $password)) {
//remove last password expiry warning if any
$notification = $this->notificationManager->createNotification();
$notification->setApp('user_ldap')
->setUser($uid)
->setObject('pwd_exp_warn', $uid)
;
$this->notificationManager->markProcessed($notification);
return true;
}

return false;
}

/**
* Get a list of all users
*
Expand Down Expand Up @@ -445,7 +480,8 @@ public function implementsActions($actions) {
| \OC\User\Backend::GET_HOME
| \OC\User\Backend::GET_DISPLAYNAME
| \OC\User\Backend::PROVIDE_AVATAR
| \OC\User\Backend::COUNT_USERS)
| \OC\User\Backend::COUNT_USERS
| ((intval($this->access->connection->turnOnPasswordChange) === 1)?(\OC\User\Backend::SET_PASSWORD):0))
& $actions);
}

Expand Down
11 changes: 11 additions & 0 deletions apps/user_ldap/lib/User_Proxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,17 @@ public function getDisplayNames($search = '', $limit = null, $offset = null) {
public function deleteUser($uid) {
return $this->handleRequest($uid, 'deleteUser', array($uid));
}

/**
* Set password
* @param string $uid The username
* @param string $password The new password
* @return bool
*
*/
public function setPassword($uid, $password) {
return $this->handleRequest($uid, 'setPassword', array($uid, $password));
}

/**
* @return bool
Expand Down
1 change: 1 addition & 0 deletions apps/user_ldap/templates/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
<p><label for="ldap_dynamic_group_member_url"><?php p($l->t('Dynamic Group Member URL'));?></label><input type="text" id="ldap_dynamic_group_member_url" name="ldap_dynamic_group_member_url" title="<?php p($l->t('The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)'));?>" data-default="<?php p($_['ldap_dynamic_group_member_url_default']); ?>" /></p>
<p><label for="ldap_nested_groups"><?php p($l->t('Nested Groups'));?></label><input type="checkbox" id="ldap_nested_groups" name="ldap_nested_groups" value="1" data-default="<?php p($_['ldap_nested_groups_default']); ?>" title="<?php p($l->t('When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)'));?>" /></p>
<p><label for="ldap_paging_size"><?php p($l->t('Paging chunksize'));?></label><input type="number" id="ldap_paging_size" name="ldap_paging_size" title="<?php p($l->t('Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)'));?>" data-default="<?php p($_['ldap_paging_size_default']); ?>" /></p>
<p><label for="ldap_turn_on_pwd_change"><?php p($l->t('Enable LDAP password changes per user'));?></label><input type="checkbox" id="ldap_turn_on_pwd_change" name="ldap_turn_on_pwd_change" value="1" data-default="<?php p($_['ldap_turn_on_pwd_change_default']); ?>" title="<?php p($l->t('Allow LDAP users to change their password and allow Super Administrators and Group Administrators to change the password of their LDAP users. Only works when access control policies are configured accordingly on the LDAP server. As passwords are sent in plaintext to the LDAP server, transport encryption must be used and password hashing should be configured on the LDAP server.'));?>" /><br/></p>
</div>
<h3><?php p($l->t('Special Attributes'));?></h3>
<div>
Expand Down
78 changes: 78 additions & 0 deletions apps/user_ldap/tests/User_LDAPTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

namespace OCA\User_LDAP\Tests;

use OC\HintException;
use OCA\User_LDAP\User_LDAP as UserLDAP;
use \OCA\User_LDAP\Access;
use \OCA\User_LDAP\Connection;
Expand Down Expand Up @@ -842,4 +843,81 @@ public function testCountUsersFailing() {
$result = $backend->countUsers();
$this->assertFalse($result);
}

/**
* Prepares the Access mock for setPassword tests
* @param \OCA\User_LDAP\Access $access mock
* @return void
*/
private function prepareAccessForSetPassword(&$access) {
$access->connection->expects($this->any())
->method('__get')
->will($this->returnCallback(function($name) {
if($name === 'ldapLoginFilter') {
return '%uid';
}
return null;
}));

$access->expects($this->any())
->method('fetchListOfUsers')
->will($this->returnCallback(function($filter) {
if($filter === 'roland') {
return array(array('dn' => ['dnOfRoland,dc=test']));
}
return array();
}));

$access->expects($this->any())
->method('fetchUsersByLoginName')
->will($this->returnCallback(function($uid) {
if($uid === 'roland') {
return array(array('dn' => ['dnOfRoland,dc=test']));
}
return array();
}));

$access->expects($this->any())
->method('dn2username')
->with($this->equalTo('dnOfRoland,dc=test'))
->will($this->returnValue('gunslinger'));

$access->expects($this->any())
->method('stringResemblesDN')
->with($this->equalTo('dnOfRoland,dc=test'))
->will($this->returnValue(true));

$access->expects($this->any())
->method('setPassword')
->will($this->returnCallback(function($uid, $password) {
if(strlen($password) <= 5) {
throw new HintException('Password fails quality checking policy', '', 19);
}
return true;
}));
}

/**
* @expectedException OC\HintException
* @expectedExceptionMessage Password fails quality checking policy
*/
public function testSetPasswordInvalid() {
$access = $this->getAccessMock();

$this->prepareAccessForSetPassword($access);
$backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
\OC_User::useBackend($backend);

$result = $backend->setPassword('roland', 'dt');
}

public function testSetPasswordValid() {
$access = $this->getAccessMock();

$this->prepareAccessForSetPassword($access);
$backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
\OC_User::useBackend($backend);

$result = $backend->setPassword('roland', 'dt12234$');
}
}

0 comments on commit 81af16b

Please sign in to comment.