Merge pull request #15677 from owncloud/enc_reset_private_key_password
[encryption] let user update the private key passwordremotes/origin/poc-doctrine-migrations
commit
b78e76a1cb
@ -0,0 +1,131 @@ |
||||
<?php |
||||
/** |
||||
* @author Björn Schießle <schiessle@owncloud.com> |
||||
* |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption\Controller; |
||||
|
||||
use OCA\Encryption\Crypto\Crypt; |
||||
use OCA\Encryption\KeyManager; |
||||
use OCA\Encryption\Session; |
||||
use OCP\AppFramework\Controller; |
||||
use OCP\AppFramework\Http; |
||||
use OCP\AppFramework\Http\DataResponse; |
||||
use OCP\IL10N; |
||||
use OCP\IRequest; |
||||
use OCP\IUserManager; |
||||
use OCP\IUserSession; |
||||
|
||||
class SettingsController extends Controller { |
||||
|
||||
/** @var IL10N */ |
||||
private $l; |
||||
|
||||
/** @var IUserManager */ |
||||
private $userManager; |
||||
|
||||
/** @var IUserSession */ |
||||
private $userSession; |
||||
|
||||
/** @var KeyManager */ |
||||
private $keyManager; |
||||
|
||||
/** @var Crypt */ |
||||
private $crypt; |
||||
|
||||
/** @var Session */ |
||||
private $session; |
||||
|
||||
/** |
||||
* @param string $AppName |
||||
* @param IRequest $request |
||||
* @param IL10N $l10n |
||||
* @param IUserManager $userManager |
||||
* @param IUserSession $userSession |
||||
* @param KeyManager $keyManager |
||||
* @param Crypt $crypt |
||||
* @param Session $session |
||||
*/ |
||||
public function __construct($AppName, |
||||
IRequest $request, |
||||
IL10N $l10n, |
||||
IUserManager $userManager, |
||||
IUserSession $userSession, |
||||
KeyManager $keyManager, |
||||
Crypt $crypt, |
||||
Session $session) { |
||||
parent::__construct($AppName, $request); |
||||
$this->l = $l10n; |
||||
$this->userSession = $userSession; |
||||
$this->userManager = $userManager; |
||||
$this->keyManager = $keyManager; |
||||
$this->crypt = $crypt; |
||||
$this->session = $session; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @NoAdminRequired |
||||
* @UseSession |
||||
* |
||||
* @param string $oldPassword |
||||
* @param string $newPassword |
||||
* @return DataResponse |
||||
*/ |
||||
public function updatePrivateKeyPassword($oldPassword, $newPassword) { |
||||
$result = false; |
||||
$uid = $this->userSession->getUser()->getUID(); |
||||
$errorMessage = $this->l->t('Could not update the private key password.'); |
||||
|
||||
//check if password is correct |
||||
$passwordCorrect = $this->userManager->checkPassword($uid, $newPassword); |
||||
|
||||
if ($passwordCorrect !== false) { |
||||
$encryptedKey = $this->keyManager->getPrivateKey($uid); |
||||
$decryptedKey = $this->crypt->decryptPrivateKey($encryptedKey, $oldPassword); |
||||
|
||||
if ($decryptedKey) { |
||||
$encryptedKey = $this->crypt->symmetricEncryptFileContent($decryptedKey, $newPassword); |
||||
$header = $this->crypt->generateHeader(); |
||||
if ($encryptedKey) { |
||||
$this->keyManager->setPrivateKey($uid, $header . $encryptedKey); |
||||
$this->session->setPrivateKey($decryptedKey); |
||||
$result = true; |
||||
} |
||||
} else { |
||||
$errorMessage = $this->l->t('The old password was not correct, please try again.'); |
||||
} |
||||
} else { |
||||
$errorMessage = $this->l->t('The current log-in password was not correct, please try again.'); |
||||
} |
||||
|
||||
if ($result === true) { |
||||
$this->session->setStatus(Session::INIT_SUCCESSFUL); |
||||
return new DataResponse( |
||||
['message' => (string) $this->l->t('Private key password successfully updated.')] |
||||
); |
||||
} else { |
||||
return new DataResponse( |
||||
['message' => (string) $errorMessage], |
||||
Http::STATUS_BAD_REQUEST |
||||
); |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,222 @@ |
||||
<?php |
||||
/** |
||||
* @author Björn Schießle <schiessle@owncloud.com> |
||||
* |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption\Tests\Controller; |
||||
|
||||
use OCA\Encryption\Controller\SettingsController; |
||||
use OCA\Encryption\Session; |
||||
use OCP\AppFramework\Http; |
||||
use Test\TestCase; |
||||
|
||||
class SettingsControllerTest extends TestCase { |
||||
|
||||
/** @var SettingsController */ |
||||
private $controller; |
||||
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject */ |
||||
private $requestMock; |
||||
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject */ |
||||
private $l10nMock; |
||||
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject */ |
||||
private $userManagerMock; |
||||
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject */ |
||||
private $userSessionMock; |
||||
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject */ |
||||
private $keyManagerMock; |
||||
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject */ |
||||
private $cryptMock; |
||||
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject */ |
||||
private $sessionMock; |
||||
|
||||
protected function setUp() { |
||||
|
||||
parent::setUp(); |
||||
|
||||
$this->requestMock = $this->getMock('OCP\IRequest'); |
||||
|
||||
$this->l10nMock = $this->getMockBuilder('OCP\IL10N') |
||||
->disableOriginalConstructor()->getMock(); |
||||
|
||||
$this->l10nMock->expects($this->any()) |
||||
->method('t') |
||||
->will($this->returnCallback(function($message) { |
||||
return $message; |
||||
})); |
||||
|
||||
$this->userManagerMock = $this->getMockBuilder('OCP\IUserManager') |
||||
->disableOriginalConstructor()->getMock(); |
||||
|
||||
$this->keyManagerMock = $this->getMockBuilder('OCA\Encryption\KeyManager') |
||||
->disableOriginalConstructor()->getMock(); |
||||
|
||||
$this->cryptMock = $this->getMockBuilder('OCA\Encryption\Crypto\Crypt') |
||||
->disableOriginalConstructor()->getMock(); |
||||
|
||||
$this->userSessionMock = $this->getMockBuilder('OCP\IUserSession') |
||||
->disableOriginalConstructor() |
||||
->setMethods([ |
||||
'isLoggedIn', |
||||
'getUID', |
||||
'login', |
||||
'logout', |
||||
'setUser', |
||||
'getUser', |
||||
'canChangePassword', |
||||
]) |
||||
->getMock(); |
||||
|
||||
$this->userSessionMock->expects($this->any()) |
||||
->method('getUID') |
||||
->willReturn('testUser'); |
||||
|
||||
$this->userSessionMock->expects($this->any()) |
||||
->method($this->anything()) |
||||
->will($this->returnSelf()); |
||||
|
||||
$this->sessionMock = $this->getMockBuilder('OCA\Encryption\Session') |
||||
->disableOriginalConstructor()->getMock(); |
||||
|
||||
$this->controller = new SettingsController( |
||||
'encryption', |
||||
$this->requestMock, |
||||
$this->l10nMock, |
||||
$this->userManagerMock, |
||||
$this->userSessionMock, |
||||
$this->keyManagerMock, |
||||
$this->cryptMock, |
||||
$this->sessionMock |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* test updatePrivateKeyPassword() if wrong new password was entered |
||||
*/ |
||||
public function testUpdatePrivateKeyPasswordWrongNewPassword() { |
||||
|
||||
$oldPassword = 'old'; |
||||
$newPassword = 'new'; |
||||
|
||||
$this->userManagerMock |
||||
->expects($this->once()) |
||||
->method('checkPassword') |
||||
->willReturn(false); |
||||
|
||||
$result = $this->controller->updatePrivateKeyPassword($oldPassword, $newPassword); |
||||
|
||||
$data = $result->getData(); |
||||
|
||||
$this->assertSame(Http::STATUS_BAD_REQUEST, $result->getStatus()); |
||||
$this->assertSame('The current log-in password was not correct, please try again.', |
||||
$data['message']); |
||||
} |
||||
|
||||
/** |
||||
* test updatePrivateKeyPassword() if wrong old password was entered |
||||
*/ |
||||
public function testUpdatePrivateKeyPasswordWrongOldPassword() { |
||||
|
||||
$oldPassword = 'old'; |
||||
$newPassword = 'new'; |
||||
|
||||
$this->userManagerMock |
||||
->expects($this->once()) |
||||
->method('checkPassword') |
||||
->willReturn(true); |
||||
|
||||
$this->cryptMock |
||||
->expects($this->once()) |
||||
->method('decryptPrivateKey') |
||||
->willReturn(false); |
||||
|
||||
$result = $this->controller->updatePrivateKeyPassword($oldPassword, $newPassword); |
||||
|
||||
$data = $result->getData(); |
||||
|
||||
$this->assertSame(Http::STATUS_BAD_REQUEST, $result->getStatus()); |
||||
$this->assertSame('The old password was not correct, please try again.', |
||||
$data['message']); |
||||
} |
||||
|
||||
/** |
||||
* test updatePrivateKeyPassword() with the correct old and new password |
||||
*/ |
||||
public function testUpdatePrivateKeyPassword() { |
||||
|
||||
$oldPassword = 'old'; |
||||
$newPassword = 'new'; |
||||
|
||||
$this->userSessionMock |
||||
->expects($this->once()) |
||||
->method('getUID') |
||||
->willReturn('testUser'); |
||||
|
||||
$this->userManagerMock |
||||
->expects($this->once()) |
||||
->method('checkPassword') |
||||
->willReturn(true); |
||||
|
||||
$this->cryptMock |
||||
->expects($this->once()) |
||||
->method('decryptPrivateKey') |
||||
->willReturn('decryptedKey'); |
||||
|
||||
$this->cryptMock |
||||
->expects($this->once()) |
||||
->method('symmetricEncryptFileContent') |
||||
->willReturn('encryptedKey'); |
||||
|
||||
$this->cryptMock |
||||
->expects($this->once()) |
||||
->method('generateHeader') |
||||
->willReturn('header.'); |
||||
|
||||
// methods which must be called after successful changing the key password |
||||
$this->keyManagerMock |
||||
->expects($this->once()) |
||||
->method('setPrivateKey') |
||||
->with($this->equalTo('testUser'), $this->equalTo('header.encryptedKey')); |
||||
|
||||
$this->sessionMock |
||||
->expects($this->once()) |
||||
->method('setPrivateKey') |
||||
->with($this->equalTo('decryptedKey')); |
||||
|
||||
$this->sessionMock |
||||
->expects($this->once()) |
||||
->method('setStatus') |
||||
->with($this->equalTo(Session::INIT_SUCCESSFUL)); |
||||
|
||||
$result = $this->controller->updatePrivateKeyPassword($oldPassword, $newPassword); |
||||
|
||||
$data = $result->getData(); |
||||
|
||||
$this->assertSame(Http::STATUS_OK, $result->getStatus()); |
||||
$this->assertSame('Private key password successfully updated.', |
||||
$data['message']); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue