]> source.dussan.org Git - nextcloud-server.git/commitdiff
let user update the private key password in case the login password was changed from...
authorBjoern Schiessle <schiessle@owncloud.com>
Thu, 16 Apr 2015 13:42:13 +0000 (15:42 +0200)
committerBjoern Schiessle <schiessle@owncloud.com>
Fri, 17 Apr 2015 18:11:22 +0000 (20:11 +0200)
apps/encryption/appinfo/application.php
apps/encryption/appinfo/routes.php
apps/encryption/controller/settingscontroller.php [new file with mode: 0644]
apps/encryption/tests/controller/SettingsControllerTest.php [new file with mode: 0644]

index dbeb1171bd81f3db42f7092922d6854cf01fd07d..417b944c02feb91afdfd6fb26ee11cb38e6f5eac 100644 (file)
@@ -167,6 +167,20 @@ class Application extends \OCP\AppFramework\App {
                        );
                });
 
+               $container->registerService('SettingsController', function (IAppContainer $c) {
+                       $server = $c->getServer();
+                       return new \OCA\Encryption\Controller\SettingsController(
+                               $c->getAppName(),
+                               $server->getRequest(),
+                               $server->getL10N($c->getAppName()),
+                               $server->getUserManager(),
+                               $server->getUserSession(),
+                               $c->query('KeyManager'),
+                               $c->query('Crypt'),
+                               $c->query('Session')
+                       );
+               });
+
                $container->registerService('UserSetup',
                        function (IAppContainer $c) {
                                $server = $c->getServer();
index 4194308a0ce625ec8ca48e01341c4f991d1fa844..8fa163d0751b58e3f4f609ece38bf20a402c2620 100644 (file)
@@ -30,6 +30,11 @@ namespace OCA\Encryption\AppInfo;
                'url' => '/ajax/adminRecovery',
                'verb' => 'POST'
        ],
+       [
+               'name' => 'Settings#updatePrivateKeyPassword',
+               'url' => '/ajax/updatePrivateKeyPassword',
+               'verb' => 'POST'
+       ],
        [
                'name' => 'Recovery#changeRecoveryPassword',
                'url' => '/ajax/changeRecoveryPassword',
diff --git a/apps/encryption/controller/settingscontroller.php b/apps/encryption/controller/settingscontroller.php
new file mode 100644 (file)
index 0000000..ec45b05
--- /dev/null
@@ -0,0 +1,144 @@
+<?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\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 {
+                               $result = false;
+                               $errorMessage = $this->l->t(
+                                       'The old password was not correct, please try again.');
+                       }
+               } else {
+                       $result = false;
+                       $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(
+                               array(
+                                       'status' => 'success',
+                                       'data' => array(
+                                               'message' => (string) $this->l->t('Private key password successfully updated.'))
+                               )
+                       );
+               } else {
+                       return new DataResponse(
+                               array(
+                                       'data' => array
+                                       ('message' => (string) $errorMessage)
+                               )
+                       );
+               }
+
+       }
+
+
+}
diff --git a/apps/encryption/tests/controller/SettingsControllerTest.php b/apps/encryption/tests/controller/SettingsControllerTest.php
new file mode 100644 (file)
index 0000000..37a6765
--- /dev/null
@@ -0,0 +1,221 @@
+<?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 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;
+
+       public 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('The current log-in password was not correct, please try again.',
+                       $data['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('The old password was not correct, please try again.',
+                       $data['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('success', $data['status']);
+
+               $this->assertSame('Private key password successfully updated.',
+                       $data['data']['message']);
+       }
+
+}