Skip to content

Commit 15851c6

Browse files
authored
Merge pull request #13350 from nextcloud/backport/13172/stable14
[stable14] fix can change password check in case of encryption is enabled
2 parents 848029f + 5153c1b commit 15851c6

2 files changed

Lines changed: 95 additions & 21 deletions

File tree

settings/Controller/UsersController.php

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
use OC\Accounts\AccountManager;
4343
use OC\AppFramework\Http;
44+
use OC\Encryption\Exceptions\ModuleDoesNotExistsException;
4445
use OC\ForbiddenException;
4546
use OC\Security\IdentityProof\Manager;
4647
use OCA\User_LDAP\User_Proxy;
@@ -128,9 +129,9 @@ public function __construct(string $appName,
128129
/**
129130
* @NoCSRFRequired
130131
* @NoAdminRequired
131-
*
132+
*
132133
* Display users list template
133-
*
134+
*
134135
* @return TemplateResponse
135136
*/
136137
public function usersListByGroup() {
@@ -140,17 +141,17 @@ public function usersListByGroup() {
140141
/**
141142
* @NoCSRFRequired
142143
* @NoAdminRequired
143-
*
144+
*
144145
* Display users list template
145-
*
146+
*
146147
* @return TemplateResponse
147148
*/
148149
public function usersList() {
149150
$user = $this->userSession->getUser();
150151
$uid = $user->getUID();
151152

152153
\OC::$server->getNavigationManager()->setActiveEntry('core_users');
153-
154+
154155
/* SORT OPTION: SORT_USERCOUNT or SORT_GROUPNAME */
155156
$sortGroupsBy = \OC\Group\MetaData::SORT_USERCOUNT;
156157
$isLDAPUsed = false;
@@ -166,22 +167,17 @@ public function usersList() {
166167
}
167168
}
168169
}
169-
170-
/* ENCRYPTION CONFIG */
171-
$isEncryptionEnabled = $this->encryptionManager->isEnabled();
172-
$useMasterKey = $this->config->getAppValue('encryption', 'useMasterKey', true);
173-
// If masterKey enabled, then you can change password. This is to avoid data loss!
174-
$canChangePassword = ($isEncryptionEnabled && $useMasterKey) || $useMasterKey;
175-
176-
177-
/* GROUPS */
170+
171+
$canChangePassword = $this->canAdminChangeUserPasswords();
172+
173+
/* GROUPS */
178174
$groupsInfo = new \OC\Group\MetaData(
179175
$uid,
180176
$this->isAdmin,
181177
$this->groupManager,
182178
$this->userSession
183179
);
184-
180+
185181
$groupsInfo->setSorting($sortGroupsBy);
186182
list($adminGroup, $groups) = $groupsInfo->get();
187183

@@ -190,7 +186,7 @@ public function usersList() {
190186
return $ldapFound || $backend instanceof User_Proxy;
191187
});
192188
}
193-
189+
194190
if ($this->isAdmin) {
195191
$disabledUsers = $isLDAPUsed ? -1 : $this->userManager->countDisabledUsers();
196192
$userCount = $isLDAPUsed ? 0 : array_reduce($this->userManager->countUsers(), function($v, $w) {
@@ -221,7 +217,7 @@ public function usersList() {
221217
'name' => 'Disabled users',
222218
'usercount' => $disabledUsers
223219
];
224-
220+
225221
/* QUOTAS PRESETS */
226222
$quotaPreset = $this->config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB');
227223
$quotaPreset = explode(',', $quotaPreset);
@@ -230,12 +226,12 @@ public function usersList() {
230226
}
231227
$quotaPreset = array_diff($quotaPreset, array('default', 'none'));
232228
$defaultQuota = $this->config->getAppValue('files', 'default_quota', 'none');
233-
229+
234230
\OC::$server->getEventDispatcher()->dispatch('OC\Settings\Users::loadAdditionalScripts');
235-
231+
236232
/* LANGUAGES */
237233
$languages = $this->l10nFactory->getLanguages();
238-
234+
239235
/* FINAL DATA */
240236
$serverData = array();
241237
// groups
@@ -254,6 +250,38 @@ public function usersList() {
254250
return new TemplateResponse('settings', 'settings-vue', ['serverData' => $serverData]);
255251
}
256252

253+
/**
254+
* check if the admin can change the users password
255+
*
256+
* The admin can change the passwords if:
257+
*
258+
* - no encryption module is loaded and encryption is disabled
259+
* - encryption module is loaded but it doesn't require per user keys
260+
*
261+
* The admin can not change the passwords if:
262+
*
263+
* - an encryption module is loaded and it uses per-user keys
264+
* - encryption is enabled but no encryption modules are loaded
265+
*
266+
* @return bool
267+
*/
268+
protected function canAdminChangeUserPasswords() {
269+
$isEncryptionEnabled = $this->encryptionManager->isEnabled();
270+
try {
271+
$noUserSpecificEncryptionKeys =!$this->encryptionManager->getEncryptionModule()->needDetailedAccessList();
272+
$isEncryptionModuleLoaded = true;
273+
} catch (ModuleDoesNotExistsException $e) {
274+
$noUserSpecificEncryptionKeys = true;
275+
$isEncryptionModuleLoaded = false;
276+
}
277+
278+
$canChangePassword = ($isEncryptionEnabled && $isEncryptionModuleLoaded && $noUserSpecificEncryptionKeys)
279+
|| (!$isEncryptionEnabled && !$isEncryptionModuleLoaded)
280+
|| (!$isEncryptionEnabled && $isEncryptionModuleLoaded && $noUserSpecificEncryptionKeys);
281+
282+
return $canChangePassword;
283+
}
284+
257285
/**
258286
* @NoAdminRequired
259287
* @NoSubadminRequired

tests/Settings/Controller/UsersControllerTest.php

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
namespace Tests\Settings\Controller;
1212

1313
use OC\Accounts\AccountManager;
14+
use OC\Encryption\Exceptions\ModuleDoesNotExistsException;
1415
use OC\Group\Group;
1516
use OC\Group\Manager;
1617
use OC\Settings\Controller\UsersController;
@@ -98,7 +99,7 @@ protected function setUp() {
9899
$this->securityManager = $this->getMockBuilder(\OC\Security\IdentityProof\Manager::class)->disableOriginalConstructor()->getMock();
99100
$this->jobList = $this->createMock(IJobList::class);
100101
$this->encryptionManager = $this->createMock(IManager::class);
101-
102+
102103
$this->l->method('t')
103104
->will($this->returnCallback(function ($text, $parameters = []) {
104105
return vsprintf($text, $parameters);
@@ -513,4 +514,49 @@ public function testGetVerificationCodeInvalidUser() {
513514
$this->assertSame(Http::STATUS_BAD_REQUEST, $result->getStatus());
514515
}
515516

517+
/**
518+
* @dataProvider dataTestCanAdminChangeUserPasswords
519+
*
520+
* @param bool $encryptionEnabled
521+
* @param bool $encryptionModuleLoaded
522+
* @param bool $masterKeyEnabled
523+
* @param bool $expected
524+
*/
525+
public function testCanAdminChangeUserPasswords($encryptionEnabled,
526+
$encryptionModuleLoaded,
527+
$masterKeyEnabled,
528+
$expected) {
529+
$controller = $this->getController();
530+
531+
$this->encryptionManager->expects($this->any())
532+
->method('isEnabled')
533+
->willReturn($encryptionEnabled);
534+
$this->encryptionManager->expects($this->any())
535+
->method('getEncryptionModule')
536+
->willReturnCallback(function() use ($encryptionModuleLoaded) {
537+
if ($encryptionModuleLoaded) return $this->encryptionModule;
538+
else throw new ModuleDoesNotExistsException();
539+
});
540+
$this->encryptionModule->expects($this->any())
541+
->method('needDetailedAccessList')
542+
->willReturn(!$masterKeyEnabled);
543+
544+
$result = $this->invokePrivate($controller, 'canAdminChangeUserPasswords', []);
545+
$this->assertSame($expected, $result);
546+
}
547+
548+
public function dataTestCanAdminChangeUserPasswords() {
549+
return [
550+
// encryptionEnabled, encryptionModuleLoaded, masterKeyEnabled, expectedResult
551+
[true, true, true, true],
552+
[false, true, true, true],
553+
[true, false, true, false],
554+
[false, false, true, true],
555+
[true, true, false, false],
556+
[false, true, false, false],
557+
[true, false, false, false],
558+
[false, false, false, true],
559+
];
560+
}
561+
516562
}

0 commit comments

Comments
 (0)