]> source.dussan.org Git - nextcloud-server.git/commitdiff
make recovery key work
authorBjoern Schiessle <schiessle@owncloud.com>
Wed, 1 Apr 2015 12:24:56 +0000 (14:24 +0200)
committerThomas Müller <thomas.mueller@tmit.eu>
Tue, 7 Apr 2015 11:30:30 +0000 (13:30 +0200)
apps/encryption/appinfo/application.php
apps/encryption/controller/recoverycontroller.php
apps/encryption/hooks/userhooks.php
apps/encryption/lib/keymanager.php
apps/encryption/lib/recovery.php
settings/changepassword/controller.php
settings/users.php

index 955146f7182902f8834cdfebe08b0876c2519e4b..0d1bd0d6bedc5d4078a5b6d2a3f75d3a333d7453 100644 (file)
@@ -75,6 +75,7 @@ class Application extends \OCP\AppFramework\App {
                                        $server->getUserSession(),
                                        $container->query('Util'),
                                        new \OCA\Encryption\Session($server->getSession()),
+                                       $container->query('Crypt'),
                                        $container->query('Recovery'))
                        ]);
 
index d115feb8e39ceaccca0b866e6f417eb6068d7a22..24d7f5a06ed948d32011de6da43197565a6a9f41 100644 (file)
@@ -142,6 +142,9 @@ class RecoveryController extends Controller {
                }
        }
 
+       /**
+        * @NoAdminRequired
+        */
        public function userSetRecovery($userEnableRecovery) {
                if ($userEnableRecovery === '0' || $userEnableRecovery === '1') {
 
index 330d8a873badfd14481d7b52efde4a69d57a3915..3b56135c36b8910e9b0ab9ac718b80fb4d8d6a75 100644 (file)
@@ -25,6 +25,7 @@ namespace OCA\Encryption\Hooks;
 use OCP\Util as OCUtil;
 use OCA\Encryption\Hooks\Contracts\IHook;
 use OCA\Encryption\KeyManager;
+use OCA\Encryption\Crypto\Crypt;
 use OCA\Encryption\Users\Setup;
 use OCP\App;
 use OCP\ILogger;
@@ -62,6 +63,10 @@ class UserHooks implements IHook {
         * @var Recovery
         */
        private $recovery;
+       /**
+        * @var Crypt
+        */
+       private $crypt;
 
        /**
         * UserHooks constructor.
@@ -72,6 +77,7 @@ class UserHooks implements IHook {
         * @param IUserSession $user
         * @param Util $util
         * @param Session $session
+        * @param Crypt $crypt
         * @param Recovery $recovery
         */
        public function __construct(KeyManager $keyManager,
@@ -80,6 +86,7 @@ class UserHooks implements IHook {
                                                                IUserSession $user,
                                                                Util $util,
                                                                Session $session,
+                                                               Crypt $crypt,
                                                                Recovery $recovery) {
 
                $this->keyManager = $keyManager;
@@ -89,6 +96,7 @@ class UserHooks implements IHook {
                $this->util = $util;
                $this->session = $session;
                $this->recovery = $recovery;
+               $this->crypt = $crypt;
        }
 
        /**
@@ -214,7 +222,7 @@ class UserHooks implements IHook {
 
                        // Save private key
                        if ($encryptedPrivateKey) {
-                               $this->setPrivateKey($this->user->getUser()->getUID(),
+                               $this->keyManager->setPrivateKey($this->user->getUser()->getUID(),
                                        $encryptedPrivateKey);
                        } else {
                                $this->log->error('Encryption could not update users encryption password');
@@ -231,28 +239,31 @@ class UserHooks implements IHook {
                        // ...we have a recovery password and the user enabled the recovery key
                        // ...encryption was activated for the first time (no keys exists)
                        // ...the user doesn't have any files
-                       if (($util->recoveryEnabledForUser() && $recoveryPassword) || !$this->userHasKeys($user) || !$util->userHasFiles($user)
+                       if (
+                               ($this->recovery->isRecoveryEnabledForUser($user) && $recoveryPassword)
+                               || !$this->keyManager->userHasKeys($user)
+                               || !$this->util->userHasFiles($user)
                        ) {
 
                                // backup old keys
-                               $this->backupAllKeys('recovery');
+                               //$this->backupAllKeys('recovery');
 
                                $newUserPassword = $params['password'];
 
                                $keyPair = $this->crypt->createKeyPair();
 
                                // Save public key
-                               $this->setPublicKey($user, $keyPair['publicKey']);
+                               $this->keyManager->setPublicKey($user, $keyPair['publicKey']);
 
                                // Encrypt private key with new password
                                $encryptedKey = $this->crypt->symmetricEncryptFileContent($keyPair['privateKey'],
                                        $newUserPassword);
 
                                if ($encryptedKey) {
-                                       $this->setPrivateKey($user, $encryptedKey);
+                                       $this->keyManager->setPrivateKey($user, $encryptedKey);
 
                                        if ($recoveryPassword) { // if recovery key is set we can re-encrypt the key files
-                                               $this->recovery->recoverUsersFiles($recoveryPassword);
+                                               $this->recovery->recoverUsersFiles($recoveryPassword, $user);
                                        }
                                } else {
                                        $this->log->error('Encryption Could not update users encryption password');
index f3f96b9ef21cf6adada6ef11b9d6693eb2ad3c01..4c5cb1365eadc5c99b38aeb6c0598e0ff9f14d3d 100644 (file)
@@ -206,7 +206,6 @@ class KeyManager {
 
                if ($encryptedKey) {
                        $this->setPrivateKey($uid, $encryptedKey);
-                       $this->config->setAppValue('encryption', 'recoveryAdminEnabled', 0);
                        return true;
                }
                return false;
@@ -355,6 +354,19 @@ class KeyManager {
                throw new FileKeyMissingException();
        }
 
+       /**
+        * get the encrypted file key
+        *
+        * @param $path
+        * @return string
+        */
+       public function getEncryptedFileKey($path) {
+               $encryptedFileKey = $this->keyStorage->getFileKey($path,
+                       $this->fileKeyId);
+
+               return $encryptedFileKey;
+       }
+
        /**
         * delete share key
         *
index 4201b829ec924ce0fc1aebfacb0f02b09c5234c4..34acdd0a6e34c6701bbc3318f8e6deba780124f7 100644 (file)
@@ -156,10 +156,15 @@ class Recovery {
        }
 
        /**
+        * check if recovery is enabled for user
+        *
+        * @param string $user if no user is given we check the current logged-in user
+        *
         * @return bool
         */
-       public function recoveryEnabledForUser() {
-               $recoveryMode = $this->config->getUserValue($this->user->getUID(),
+       public function isRecoveryEnabledForUser($user = '') {
+               $uid = empty($user) ? $this->user->getUID() : $user;
+               $recoveryMode = $this->config->getUserValue($uid,
                        'encryption',
                        'recoveryEnabled',
                        0);
@@ -167,6 +172,17 @@ class Recovery {
                return ($recoveryMode === '1');
        }
 
+       /**
+        * check if recovery is key is enabled by the administrator
+        *
+        * @return bool
+        */
+       public function isRecoveryKeyEnabled() {
+               $enabled = $this->config->getAppValue('encryption', 'recoveryAdminEnabled', 0);
+
+               return ($enabled === '1');
+       }
+
        /**
         * @param string $value
         * @return bool
@@ -234,15 +250,18 @@ class Recovery {
        }
 
        /**
-        * @param $recoveryPassword
+        * recover users files with the recovery key
+        *
+        * @param string $recoveryPassword
+        * @param string $user
         */
-       public function recoverUsersFiles($recoveryPassword) {
-               $encryptedKey = $this->keyManager->getSystemPrivateKey();
+       public function recoverUsersFiles($recoveryPassword, $user) {
+               $encryptedKey = $this->keyManager->getSystemPrivateKey($this->keyManager->getRecoveryKeyId());
 
                $privateKey = $this->crypt->decryptPrivateKey($encryptedKey,
                        $recoveryPassword);
 
-               $this->recoverAllFiles('/', $privateKey);
+               $this->recoverAllFiles('/' . $user . '/files/', $privateKey);
        }
 
        /**
@@ -250,12 +269,12 @@ class Recovery {
         * @param $privateKey
         */
        private function recoverAllFiles($path, $privateKey) {
-               $dirContent = $this->files->getDirectoryContent($path);
+               $dirContent = $this->view->getDirectoryContent($path);
 
                foreach ($dirContent as $item) {
                        // Get relative path from encryption/keyfiles
-                       $filePath = substr($item['path'], strlen('encryption/keys'));
-                       if ($this->files->is_dir($this->user->getUID() . '/files' . '/' . $filePath)) {
+                       $filePath = $item->getPath();
+                       if ($this->view->is_dir($filePath)) {
                                $this->recoverAllFiles($filePath . '/', $privateKey);
                        } else {
                                $this->recoverFile($filePath, $privateKey);
@@ -265,50 +284,32 @@ class Recovery {
        }
 
        /**
-        * @param $filePath
-        * @param $privateKey
+        * @param string $path
+        * @param string $privateKey
         */
-       private function recoverFile($filePath, $privateKey) {
-               $sharingEnabled = Share::isEnabled();
-               $uid = $this->user->getUID();
-
-               // Find out who, if anyone, is sharing the file
-               if ($sharingEnabled) {
-                       $result = Share::getUsersSharingFile($filePath,
-                               $uid,
-                               true);
-                       $userIds = $result['users'];
-                       $userIds[] = 'public';
-               } else {
-                       $userIds = [
-                               $uid,
-                               $this->recoveryKeyId
-                       ];
+       private function recoverFile($path, $privateKey) {
+               $encryptedFileKey = $this->keyManager->getEncryptedFileKey($path);
+               $shareKey = $this->keyManager->getShareKey($path, $this->keyManager->getRecoveryKeyId());
+
+               if ($encryptedFileKey && $shareKey && $privateKey) {
+                       $fileKey = $this->crypt->multiKeyDecrypt($encryptedFileKey,
+                               $shareKey,
+                               $privateKey);
                }
-               $filteredUids = $this->filterShareReadyUsers($userIds);
 
-               // Decrypt file key
-               $encKeyFile = $this->keyManager->getFileKey($filePath,
-                       $uid);
-
-               $shareKey = $this->keyManager->getShareKey($filePath,
-                       $uid);
-
-               $plainKeyFile = $this->crypt->multiKeyDecrypt($encKeyFile,
-                       $shareKey,
-                       $privateKey);
+               if (!empty($fileKey)) {
+                       $accessList = $this->file->getAccessList($path);
+                       $publicKeys = array();
+                       foreach ($accessList['users'] as $uid) {
+                               $publicKeys[$uid] = $this->keyManager->getPublicKey($uid);
+                       }
 
-               // Encrypt the file key again to all users, this time with the new publick keyt for the recovered user
-               $userPublicKeys = $this->keyManager->getPublicKeys($filteredUids['ready']);
-               $multiEncryptionKey = $this->crypt->multiKeyEncrypt($plainKeyFile,
-                       $userPublicKeys);
+                       $publicKeys = $this->keyManager->addSystemKeys($accessList, $publicKeys);
 
-               $this->keyManager->setFileKey($multiEncryptionKey['data'],
-                       $uid);
+                       $encryptedKeyfiles = $this->crypt->multiKeyEncrypt($fileKey, $publicKeys);
+                       $this->keyManager->setAllFileKeys($path, $encryptedKeyfiles);
+               }
 
-               $this->keyManager->setShareKey($filePath,
-                       $uid,
-                       $multiEncryptionKey['keys']);
        }
 
 
index 1be30b725df63378273a3f10c83fce97c88daaf3..f041cb5b29f759129879581588a418e7a9e89821 100644 (file)
@@ -77,16 +77,43 @@ class Controller {
                        exit();
                }
 
-               if (\OC_App::isEnabled('files_encryption')) {
+               if (\OC_App::isEnabled('encryption')) {
                        //handle the recovery case
-                       $util = new \OCA\Files_Encryption\Util(new \OC\Files\View('/'), $username);
-                       $recoveryAdminEnabled = \OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled');
+                       $crypt = new \OCA\Encryption\Crypto\Crypt(
+                               \OC::$server->getLogger(),
+                               \OC::$server->getUserSession(),
+                               \OC::$server->getConfig());
+                       $keyStorage = \OC::$server->getEncryptionKeyStorage(\OCA\Encryption\Crypto\Encryption::ID);
+                       $util = new \OCA\Encryption\Util(
+                               new \OC\Files\View(),
+                               $crypt,
+                               \OC::$server->getLogger(),
+                               \OC::$server->getUserSession(),
+                               \OC::$server->getConfig());
+                       $keyManager = new \OCA\Encryption\KeyManager(
+                               $keyStorage,
+                               $crypt,
+                               \OC::$server->getConfig(),
+                               \OC::$server->getUserSession(),
+                               new \OCA\Encryption\Session(\OC::$server->getSession()),
+                               \OC::$server->getLogger(),
+                               $util);
+                       $recovery = new \OCA\Encryption\Recovery(
+                               \OC::$server->getUserSession(),
+                               $crypt,
+                               \OC::$server->getSecureRandom(),
+                               $keyManager,
+                               \OC::$server->getConfig(),
+                               $keyStorage,
+                               \OC::$server->getEncryptionFilesHelper(),
+                               new \OC\Files\View());
+                       $recoveryAdminEnabled = $recovery->isRecoveryKeyEnabled();
 
                        $validRecoveryPassword = false;
                        $recoveryEnabledForUser = false;
                        if ($recoveryAdminEnabled) {
-                               $validRecoveryPassword = $util->checkRecoveryPassword($recoveryPassword);
-                               $recoveryEnabledForUser = $util->recoveryEnabledForUser();
+                               $validRecoveryPassword = $keyManager->checkRecoveryPassword($recoveryPassword);
+                               $recoveryEnabledForUser = $recovery->isRecoveryEnabledForUser();
                        }
 
                        if ($recoveryEnabledForUser && $recoveryPassword === '') {
index 08498edec29324a91bd5d8475a6c4d5cd82c69fb..0fc9fbeafc2afbf78030300e1f3b1daf289edcab 100644 (file)
@@ -45,8 +45,8 @@ $groupsInfo = new \OC\Group\MetaData(OC_User::getUser(), $isAdmin, $groupManager
 $groupsInfo->setSorting($groupsInfo::SORT_USERCOUNT);
 list($adminGroup, $groups) = $groupsInfo->get();
 
-$recoveryAdminEnabled = OC_App::isEnabled('files_encryption') &&
-                                           $config->getAppValue( 'files_encryption', 'recoveryAdminEnabled', null );
+$recoveryAdminEnabled = OC_App::isEnabled('encryption') &&
+                                           $config->getAppValue( 'encryption', 'recoveryAdminEnabled', null );
 
 if($isAdmin) {
        $subadmins = OC_SubAdmin::getAllSubAdmins();