]> source.dussan.org Git - nextcloud-server.git/commitdiff
Updating keystorage movement and fixing hooks
authorClark Tomlinson <fallen013@gmail.com>
Tue, 24 Mar 2015 21:29:10 +0000 (17:29 -0400)
committerThomas Müller <thomas.mueller@tmit.eu>
Tue, 7 Apr 2015 11:30:27 +0000 (13:30 +0200)
15 files changed:
apps/encryption/appinfo/encryption.php
apps/encryption/hooks/userhooks.php
apps/encryption/lib/crypto/Encryption.php
apps/encryption/lib/crypto/crypt.php
apps/encryption/lib/hookmanager.php
apps/encryption/lib/keymanager.php
apps/encryption/lib/migrator.php [deleted file]
apps/encryption/lib/recovery.php
apps/encryption/lib/users/setup.php
apps/encryption/lib/util.php [new file with mode: 0644]
apps/encryption/settings/settings-admin.php
apps/encryption/tests/lib/KeyManagerTest.php
apps/encryption/tests/lib/MigratorTest.php
apps/files_encryption/lib/hooks.php
lib/private/server.php

index f2ab89aadefe92142e554a5a444e2d7e60b6d306..1a4c17eb60aa808ff4e80c57ff4d41c7bcb1bbd0 100644 (file)
 namespace OCA\Encryption\AppInfo;
 
 
+use OC\Files\Filesystem;
+use OC\Files\View;
 use OCA\Encryption\Crypto\Crypt;
 use OCA\Encryption\HookManager;
-use OCA\Encryption\Hooks\AppHooks;
-use OCA\Encryption\Hooks\FileSystemHooks;
-use OCA\Encryption\Hooks\ShareHooks;
 use OCA\Encryption\Hooks\UserHooks;
 use OCA\Encryption\KeyManager;
 use OCA\Encryption\Migrator;
 use OCA\Encryption\Recovery;
 use OCA\Encryption\Users\Setup;
+use OCA\Encryption\Util;
 use OCP\App;
 use OCP\AppFramework\IAppContainer;
 use OCP\Encryption\IManager;
@@ -81,14 +81,7 @@ class Encryption extends \OCP\AppFramework\App {
                        $hookManager = new HookManager();
 
                        $hookManager->registerHook([
-                               new UserHooks($container->query('KeyManager'),
-                                       $server->getLogger(),
-                                       $container->query('UserSetup'),
-                                       $container->query('Migrator'),
-                                       $server->getUserSession()),
-//                             new ShareHooks(),
-//                             new FileSystemHooks(),
-//                             new AppHooks()
+                               new UserHooks($container->query('KeyManager'), $server->getLogger(), $container->query('UserSetup'), $server->getUserSession(), new \OCP\Util(), $container->query('Util')),
                        ]);
 
                        $hookManager->fireHooks();
@@ -103,7 +96,7 @@ class Encryption extends \OCP\AppFramework\App {
         *
         */
        public function registerEncryptionModule() {
-//             $this->encryptionManager->registerEncryptionModule(new \OCA\Encryption\Crypto\Encryption());
+               $this->encryptionManager->registerEncryptionModule(new \OCA\Encryption\Crypto\Encryption());
        }
 
        /**
@@ -124,10 +117,13 @@ class Encryption extends \OCP\AppFramework\App {
                        function (IAppContainer $c) {
                                $server = $c->getServer();
 
-                               return new KeyManager($server->getEncryptionKeyStorage(),
+                               return new KeyManager($server->getEncryptionKeyStorage('encryption'),
                                        $c->query('Crypt'),
                                        $server->getConfig(),
-                                       $server->getUserSession());
+                                       $server->getUserSession(),
+                                       $server->getMemCacheFactory(),
+                                       $server->getLogger()
+                               );
                        });
 
 
@@ -141,7 +137,7 @@ class Encryption extends \OCP\AppFramework\App {
                                        $server->getSecureRandom(),
                                        $c->query('KeyManager'),
                                        $server->getConfig(),
-                                       $server->getEncryptionKeyStorage());
+                                       $server->getEncryptionKeyStorage('encryption'));
                        });
 
                $container->registerService('UserSetup',
@@ -157,13 +153,26 @@ class Encryption extends \OCP\AppFramework\App {
                        function (IAppContainer $c) {
                                $server = $c->getServer();
 
-                               return new Migrator($server->getUserSession(),
-                                       $server->getConfig(),
+                               return new Migrator($server->getConfig(),
                                        $server->getUserManager(),
                                        $server->getLogger(),
                                        $c->query('Crypt'));
                        });
 
+               $container->registerService('Util',
+                       function (IAppContainer $c) {
+                               $server = $c->getServer();
+
+                               return new Util(new View(),
+                                       new Filesystem(),
+                                       $c->query('Crypt'),
+                                       $c->query('KeyManager'),
+                                       $server->getLogger(),
+                                       $server->getUserSession(),
+                                       $server->getConfig()
+                               );
+                       });
+
        }
 
        /**
index 79de70a6d0256c46b772afee3ba382b8abed4e9b..096fd3beb935331c4b548af4146c89a102b6a6ca 100644 (file)
 namespace OCA\Encryption\Hooks;
 
 
+use OCP\Util as OCUtil;
 use OCA\Encryption\Hooks\Contracts\IHook;
 use OCA\Encryption\KeyManager;
-use OCA\Encryption\Migrator;
-use OCA\Encryption\RequirementsChecker;
 use OCA\Encryption\Users\Setup;
 use OCP\App;
 use OCP\ILogger;
 use OCP\IUserSession;
-use OCP\Util;
+use OCA\Encryption\Util;
 use Test\User;
 
 class UserHooks implements IHook {
@@ -46,14 +45,14 @@ class UserHooks implements IHook {
         * @var Setup
         */
        private $userSetup;
-       /**
-        * @var Migrator
-        */
-       private $migrator;
        /**
         * @var IUserSession
         */
        private $user;
+       /**
+        * @var Util
+        */
+       private $util;
 
        /**
         * UserHooks constructor.
@@ -61,17 +60,19 @@ class UserHooks implements IHook {
         * @param KeyManager $keyManager
         * @param ILogger $logger
         * @param Setup $userSetup
-        * @param Migrator $migrator
         * @param IUserSession $user
+        * @param OCUtil $ocUtil
+        * @param Util $util
+        * @internal param Migrator $migrator
         */
        public function __construct(
-               KeyManager $keyManager, ILogger $logger, Setup $userSetup, Migrator $migrator, IUserSession $user) {
+               KeyManager $keyManager, ILogger $logger, Setup $userSetup, IUserSession $user, OCUtil $ocUtil, Util $util) {
 
                $this->keyManager = $keyManager;
                $this->logger = $logger;
                $this->userSetup = $userSetup;
-               $this->migrator = $migrator;
                $this->user = $user;
+               $this->util = $util;
        }
 
        /**
@@ -80,12 +81,24 @@ class UserHooks implements IHook {
         * @return null
         */
        public function addHooks() {
-               Util::connectHook('OC_User', 'post_login', $this, 'login');
-               Util::connectHook('OC_User', 'logout', $this, 'logout');
-               Util::connectHook('OC_User', 'post_setPassword', $this, 'setPassphrase');
-               Util::connectHook('OC_User', 'pre_setPassword', $this, 'preSetPassphrase');
-               Util::connectHook('OC_User', 'post_createUser', $this, 'postCreateUser');
-               Util::connectHook('OC_User', 'post_deleteUser', $this, 'postDeleteUser');
+               OCUtil::connectHook('OC_User', 'post_login', $this, 'login');
+               OCUtil::connectHook('OC_User', 'logout', $this, 'logout');
+               OCUtil::connectHook('OC_User',
+                       'post_setPassword',
+                       $this,
+                       'setPassphrase');
+               OCUtil::connectHook('OC_User',
+                       'pre_setPassword',
+                       $this,
+                       'preSetPassphrase');
+               OCUtil::connectHook('OC_User',
+                       'post_createUser',
+                       $this,
+                       'postCreateUser');
+               OCUtil::connectHook('OC_User',
+                       'post_deleteUser',
+                       $this,
+                       'postDeleteUser');
        }
 
 
@@ -93,6 +106,8 @@ class UserHooks implements IHook {
         * Startup encryption backend upon user login
         *
         * @note This method should never be called for users using client side encryption
+        * @param array $params
+        * @return bool
         */
        public function login($params) {
 
@@ -107,198 +122,76 @@ class UserHooks implements IHook {
                }
 
                // setup user, if user not ready force relogin
-               if (!$this->userSetup->setupUser($params['password'])) {
-                       return false;
-               }
-
-               $cache = $this->keyManager->init();
-
-               // Check if first-run file migration has already been performed
-               $ready = false;
-               $migrationStatus = $this->migrator->getStatus($params['uid']);
-               if ($migrationStatus === Migrator::$migrationOpen && $cache !== false) {
-                       $ready = $this->migrator->beginMigration();
-               } elseif ($migrationStatus === Migrator::$migrationInProgress) {
-                       // refuse login as long as the initial encryption is running
-                       sleep(5);
-                       $this->user->logout();
+               if (!$this->userSetup->setupUser($params['uid'], $params['password'])) {
                        return false;
                }
 
-               $result = true;
-
-               // If migration not yet done
-               if ($ready) {
-
-                       // Encrypt existing user files
-                       try {
-                               $result = $util->encryptAll('/' . $params['uid'] . '/' . 'files');
-                       } catch (\Exception $ex) {
-                               \OCP\Util::writeLog('Encryption library', 'Initial encryption failed! Error: ' . $ex->getMessage(), \OCP\Util::FATAL);
-                               $result = false;
-                       }
-
-                       if ($result) {
-                               \OC_Log::write(
-                                       'Encryption library', 'Encryption of existing files belonging to "' . $params['uid'] . '" completed'
-                                       , \OC_Log::INFO
-                               );
-                               // Register successful migration in DB
-                               $util->finishMigration();
-                       } else {
-                               \OCP\Util::writeLog('Encryption library', 'Initial encryption failed!', \OCP\Util::FATAL);
-                               $util->resetMigrationStatus();
-                               \OCP\User::logout();
-                       }
-               }
-
-               return $result;
+               $this->keyManager->init($params['uid'], $params['password']);
        }
 
        /**
         * remove keys from session during logout
         */
        public function logout() {
-               $session = new Session(new \OC\Files\View());
-               $session->removeKeys();
+               KeyManager::$cacheFactory->clear();
        }
 
        /**
         * setup encryption backend upon user created
         *
         * @note This method should never be called for users using client side encryption
+        * @param array $params
         */
        public function postCreateUser($params) {
 
-               if (App::isEnabled('files_encryption')) {
-                       $view = new \OC\Files\View('/');
-                       $util = new Util($view, $params['uid']);
-                       Helper::setupUser($util, $params['password']);
+               if (App::isEnabled('encryption')) {
+                       $this->userSetup->setupUser($params['uid'], $params['password']);
                }
        }
 
        /**
         * cleanup encryption backend upon user deleted
         *
+        * @param array $params : uid, password
         * @note This method should never be called for users using client side encryption
         */
        public function postDeleteUser($params) {
 
-               if (App::isEnabled('files_encryption')) {
-                       Keymanager::deletePublicKey(new \OC\Files\View(), $params['uid']);
+               if (App::isEnabled('encryption')) {
+                       $this->keyManager->deletePublicKey($params['uid']);
                }
        }
 
        /**
         * If the password can't be changed within ownCloud, than update the key password in advance.
-        */
-       public function preSetPassphrase($params) {
-               if (App::isEnabled('files_encryption')) {
-                       if (!\OC_User::canUserChangePassword($params['uid'])) {
-                               self::setPassphrase($params);
-                       }
-               }
-       }
-
-       /**
-        * Change a user's encryption passphrase
         *
-        * @param array $params keys: uid, password
+        * @param array $params : uid, password
+        * @return bool
         */
-       public function setPassphrase($params) {
-               if (App::isEnabled('files_encryption') === false) {
-                       return true;
-               }
-
-               // Only attempt to change passphrase if server-side encryption
-               // is in use (client-side encryption does not have access to
-               // the necessary keys)
-               if (Crypt::mode() === 'server') {
-
-                       $view = new \OC\Files\View('/');
-                       $session = new Session($view);
-
-                       // Get existing decrypted private key
-                       $privateKey = $session->getPrivateKey();
-
-                       if ($params['uid'] === \OCP\User::getUser() && $privateKey) {
-
-                               // Encrypt private key with new user pwd as passphrase
-                               $encryptedPrivateKey = Crypt::symmetricEncryptFileContent($privateKey, $params['password'], Helper::getCipher());
-
-                               // Save private key
-                               if ($encryptedPrivateKey) {
-                                       Keymanager::setPrivateKey($encryptedPrivateKey, \OCP\User::getUser());
-                               } else {
-                                       \OCP\Util::writeLog('files_encryption', 'Could not update users encryption password', \OCP\Util::ERROR);
-                               }
-
-                               // NOTE: Session does not need to be updated as the
-                               // private key has not changed, only the passphrase
-                               // used to decrypt it has changed
-
-
-                       } else { // admin changed the password for a different user, create new keys and reencrypt file keys
-
-                               $user = $params['uid'];
-                               $util = new Util($view, $user);
-                               $recoveryPassword = isset($params['recoveryPassword']) ? $params['recoveryPassword'] : null;
-
-                               // we generate new keys if...
-                               // ...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)
-                                       || !$util->userKeysExists()
-                                       || !$view->file_exists($user . '/files')
-                               ) {
-
-                                       // backup old keys
-                                       $util->backupAllKeys('recovery');
-
-                                       $newUserPassword = $params['password'];
-
-                                       // make sure that the users home is mounted
-                                       \OC\Files\Filesystem::initMountPoints($user);
-
-                                       $keypair = Crypt::createKeypair();
-
-                                       // Disable encryption proxy to prevent recursive calls
-                                       $proxyStatus = \OC_FileProxy::$enabled;
-                                       \OC_FileProxy::$enabled = false;
-
-                                       // Save public key
-                                       Keymanager::setPublicKey($keypair['publicKey'], $user);
-
-                                       // Encrypt private key with new password
-                                       $encryptedKey = Crypt::symmetricEncryptFileContent($keypair['privateKey'], $newUserPassword, Helper::getCipher());
-                                       if ($encryptedKey) {
-                                               Keymanager::setPrivateKey($encryptedKey, $user);
-
-                                               if ($recoveryPassword) { // if recovery key is set we can re-encrypt the key files
-                                                       $util = new Util($view, $user);
-                                                       $util->recoverUsersFiles($recoveryPassword);
-                                               }
-                                       } else {
-                                               \OCP\Util::writeLog('files_encryption', 'Could not update users encryption password', \OCP\Util::ERROR);
-                                       }
+       public function preSetPassphrase($params) {
+               if (App::isEnabled('encryption')) {
 
-                                       \OC_FileProxy::$enabled = $proxyStatus;
+                       if (!$this->user->getUser()->canChangePassword()) {
+                               if (App::isEnabled('encryption') === false) {
+                                       return true;
                                }
+                               $this->keyManager->setPassphrase($params,
+                                       $this->user,
+                                       $this->util);
                        }
                }
        }
 
+
        /**
         * after password reset we create a new key pair for the user
         *
         * @param array $params
         */
        public function postPasswordReset($params) {
-               $uid = $params['uid'];
                $password = $params['password'];
 
-               $util = new Util(new \OC\Files\View(), $uid);
-               $util->replaceUserKeys($password);
+               $this->keyManager->replaceUserKeys($params['uid']);
+               $this->userSetup->setupServerSide($params['uid'], $password);
        }
 }
index 123581b83ac6f957a122a4412532ccf06ec837be..b8429d7124ec3710011cdc3cc132cd723f7cf23e 100644 (file)
@@ -18,7 +18,7 @@ class Encryption extends Crypt implements IEncryptionModule {
    * @return string defining the technical unique id
    */
   public function getId() {
-    // TODO: Implement getId() method.
+    return md5($this->getDisplayName());
   }
 
   /**
@@ -27,7 +27,7 @@ class Encryption extends Crypt implements IEncryptionModule {
    * @return string
    */
   public function getDisplayName() {
-    // TODO: Implement getDisplayName() method.
+    return 'ownCloud Default Encryption';
   }
 
   /**
@@ -44,7 +44,9 @@ class Encryption extends Crypt implements IEncryptionModule {
    *                       or if no additional data is needed return a empty array
    */
   public function begin($path, $header, $accessList) {
+
     // TODO: Implement begin() method.
+    // return additional header information that needs to be written i.e. cypher used
   }
 
   /**
@@ -68,6 +70,7 @@ class Encryption extends Crypt implements IEncryptionModule {
    */
   public function encrypt($data) {
     // Todo: xxx Update Signature and usages
+    // passphrase is file key decrypted with user private/share key
     $this->symmetricEncryptFileContent($data);
   }
 
@@ -113,4 +116,14 @@ class Encryption extends Crypt implements IEncryptionModule {
   public function calculateUnencryptedSize($path) {
     // TODO: Implement calculateUnencryptedSize() method.
   }
+
+  /**
+   * get size of the unencrypted payload per block.
+   * ownCloud read/write files with a block size of 8192 byte
+   *
+   * @return integer
+   */
+  public function getUnencryptedBlockSize() {
+    // TODO: Implement getUnencryptedBlockSize() method.
+  }
 }
index 8018f11a37097d51830bc1825f0f27ca9cd4c8f8..f9fe4f9bece65a54e8502e5b9801593ac5936e39 100644 (file)
@@ -25,6 +25,8 @@ namespace OCA\Encryption\Crypto;
 use OC\Encryption\Exceptions\DecryptionFailedException;
 use OC\Encryption\Exceptions\EncryptionFailedException;
 use OC\Encryption\Exceptions\GenericEncryptionException;
+use OCA\Files_Encryption\Exception\MultiKeyDecryptException;
+use OCA\Files_Encryption\Exception\MultiKeyEncryptException;
 use OCP\IConfig;
 use OCP\ILogger;
 use OCP\IUser;
@@ -83,12 +85,17 @@ class Crypt {
                $res = $this->getOpenSSLPKey();
 
                if (!$res) {
-                       $log->error("Encryption Library could'nt generate users key-pair for {$this->user->getUID()}", ['app' => 'encryption']);
+                       $log->error("Encryption Library could'nt generate users key-pair for {$this->user->getUID()}",
+                               ['app' => 'encryption']);
 
                        if (openssl_error_string()) {
-                               $log->error('Encryption library openssl_pkey_new() fails: ' . openssl_error_string(), ['app' => 'encryption']);
+                               $log->error('Encryption library openssl_pkey_new() fails: ' . openssl_error_string(),
+                                       ['app' => 'encryption']);
                        }
-               } elseif (openssl_pkey_export($res, $privateKey, null, $this->getOpenSSLConfig())) {
+               } elseif (openssl_pkey_export($res,
+                       $privateKey,
+                       null,
+                       $this->getOpenSSLConfig())) {
                        $keyDetails = openssl_pkey_get_details($res);
                        $publicKey = $keyDetails['key'];
 
@@ -97,9 +104,11 @@ class Crypt {
                                'privateKey' => $privateKey
                        ];
                }
-               $log->error('Encryption library couldn\'t export users private key, please check your servers openSSL configuration.' . $user->getUID(), ['app' => 'encryption']);
+               $log->error('Encryption library couldn\'t export users private key, please check your servers openSSL configuration.' . $user->getUID(),
+                       ['app' => 'encryption']);
                if (openssl_error_string()) {
-                       $log->error('Encryption Library:' . openssl_error_string(), ['app' => 'encryption']);
+                       $log->error('Encryption Library:' . openssl_error_string(),
+                               ['app' => 'encryption']);
                }
 
                return false;
@@ -118,7 +127,9 @@ class Crypt {
         */
        private function getOpenSSLConfig() {
                $config = ['private_key_bits' => 4096];
-               $config = array_merge(\OC::$server->getConfig()->getSystemValue('openssl', []), $config);
+               $config = array_merge(\OC::$server->getConfig()->getSystemValue('openssl',
+                       []),
+                       $config);
                return $config;
        }
 
@@ -131,14 +142,18 @@ class Crypt {
        public function symmetricEncryptFileContent($plainContent, $passphrase) {
 
                if (!$plainContent) {
-                       $this->logger->error('Encryption Library, symmetrical encryption failed no content given', ['app' => 'encryption']);
+                       $this->logger->error('Encryption Library, symmetrical encryption failed no content given',
+                               ['app' => 'encryption']);
                        return false;
                }
 
                $iv = $this->generateIv();
 
                try {
-                       $encryptedContent = $this->encrypt($plainContent, $iv, $passphrase, $this->getCipher());
+                       $encryptedContent = $this->encrypt($plainContent,
+                               $iv,
+                               $passphrase,
+                               $this->getCipher());
                        // combine content to encrypt the IV identifier and actual IV
                        $catFile = $this->concatIV($encryptedContent, $iv);
                        $padded = $this->addPadding($catFile);
@@ -146,7 +161,8 @@ class Crypt {
                        return $padded;
                } catch (EncryptionFailedException $e) {
                        $message = 'Could not encrypt file content (code: ' . $e->getCode() . '): ';
-                       $this->logger->error('files_encryption' . $message . $e->getMessage(), ['app' => 'encryption']);
+                       $this->logger->error('files_encryption' . $message . $e->getMessage(),
+                               ['app' => 'encryption']);
                        return false;
                }
 
@@ -161,11 +177,16 @@ class Crypt {
         * @throws EncryptionFailedException
         */
        private function encrypt($plainContent, $iv, $passphrase = '', $cipher = self::DEFAULT_CIPHER) {
-               $encryptedContent = openssl_encrypt($plainContent, $cipher, $passphrase, false, $iv);
+               $encryptedContent = openssl_encrypt($plainContent,
+                       $cipher,
+                       $passphrase,
+                       false,
+                       $iv);
 
                if (!$encryptedContent) {
                        $error = 'Encryption (symmetric) of content failed';
-                       $this->logger->error($error . openssl_error_string(), ['app' => 'encryption']);
+                       $this->logger->error($error . openssl_error_string(),
+                               ['app' => 'encryption']);
                        throw new EncryptionFailedException($error);
                }
 
@@ -177,8 +198,9 @@ class Crypt {
         */
        public function getCipher() {
                $cipher = $this->config->getSystemValue('cipher', self::DEFAULT_CIPHER);
-               if ($cipher !== 'AES-256-CFB' || $cipher !== 'AES-128-CFB') {
-                       $this->logger->warning('Wrong cipher defined in config.php only AES-128-CFB and AES-256-CFB are supported. Fall back' . self::DEFAULT_CIPHER, ['app' => 'encryption']);
+               if ($cipher !== 'AES-256-CFB' && $cipher !== 'AES-128-CFB') {
+                       $this->logger->warning('Wrong cipher defined in config.php only AES-128-CFB and AES-256-CFB are supported. Fall back' . self::DEFAULT_CIPHER,
+                               ['app' => 'encryption']);
                        $cipher = self::DEFAULT_CIPHER;
                }
 
@@ -214,10 +236,14 @@ class Crypt {
 
                // If we found a header we need to remove it from the key we want to decrypt
                if (!empty($header)) {
-                       $recoveryKey = substr($recoveryKey, strpos($recoveryKey, self::HEADEREND) + strlen(self::HEADERSTART));
+                       $recoveryKey = substr($recoveryKey,
+                               strpos($recoveryKey,
+                                       self::HEADEREND) + strlen(self::HEADERSTART));
                }
 
-               $plainKey = $this->symmetricDecryptFileContent($recoveryKey, $password, $cipher);
+               $plainKey = $this->symmetricDecryptFileContent($recoveryKey,
+                       $password,
+                       $cipher);
 
                // Check if this is a valid private key
                $res = openssl_get_privatekey($plainKey);
@@ -246,7 +272,10 @@ class Crypt {
 
                $catFile = $this->splitIv($noPadding);
 
-               $plainContent = $this->decrypt($catFile['encrypted'], $catFile['iv'], $passphrase, $cipher);
+               $plainContent = $this->decrypt($catFile['encrypted'],
+                       $catFile['iv'],
+                       $passphrase,
+                       $cipher);
 
                if ($plainContent) {
                        return $plainContent;
@@ -296,7 +325,11 @@ class Crypt {
         * @throws DecryptionFailedException
         */
        private function decrypt($encryptedContent, $iv, $passphrase = '', $cipher = self::DEFAULT_CIPHER) {
-               $plainContent = openssl_decrypt($encryptedContent, $cipher, $passphrase, false, $iv);
+               $plainContent = openssl_decrypt($encryptedContent,
+                       $cipher,
+                       $passphrase,
+                       false,
+                       $iv);
 
                if ($plainContent) {
                        return $plainContent;
@@ -317,7 +350,8 @@ class Crypt {
                        $header = substr($data, 0, $endAt + strlen(self::HEADEREND));
 
                        // +1 not to start with an ':' which would result in empty element at the beginning
-                       $exploded = explode(':', substr($header, strlen(self::HEADERSTART) + 1));
+                       $exploded = explode(':',
+                               substr($header, strlen(self::HEADERSTART) + 1));
 
                        $element = array_shift($exploded);
 
@@ -339,7 +373,8 @@ class Crypt {
                if ($random) {
                        if (!$strong) {
                                // If OpenSSL indicates randomness is insecure log error
-                               $this->logger->error('Encryption Library: Insecure symmetric key was generated using openssl_random_psudo_bytes()', ['app' => 'encryption']);
+                               $this->logger->error('Encryption Library: Insecure symmetric key was generated using openssl_random_psudo_bytes()',
+                                       ['app' => 'encryption']);
                        }
 
                        /*
@@ -351,5 +386,85 @@ class Crypt {
                // If we ever get here we've failed anyway no need for an else
                throw new GenericEncryptionException('Generating IV Failed');
        }
+
+       /**
+        * Check if a file's contents contains an IV and is symmetrically encrypted
+        *
+        * @param $content
+        * @return bool
+        */
+       public function isCatFileContent($content) {
+               if (!$content) {
+                       return false;
+               }
+
+               $noPadding = $this->removePadding($content);
+
+               // Fetch encryption metadata from end of file
+               $meta = substr($noPadding, -22);
+
+               // Fetch identifier from start of metadata
+               $identifier = substr($meta, 0, 6);
+
+               if ($identifier === '00iv00') {
+                       return true;
+               }
+               return false;
+       }
+
+       /**
+        * @param $encKeyFile
+        * @param $shareKey
+        * @param $privateKey
+        * @return mixed
+        * @throws MultiKeyDecryptException
+        */
+       public function multiKeyDecrypt($encKeyFile, $shareKey, $privateKey) {
+               if (!$encKeyFile) {
+                       throw new MultiKeyDecryptException('Cannot multikey decrypt empty plain content');
+               }
+
+               if (openssl_open($encKeyFile, $plainContent, $shareKey, $privateKey)) {
+                       return $plainContent;
+               } else {
+                       throw new MultiKeyDecryptException('multikeydecrypt with share key failed');
+               }
+       }
+
+       /**
+        * @param $plainContent
+        * @param array $keyFiles
+        * @return array
+        * @throws MultiKeyEncryptException
+        */
+       public function multiKeyEncrypt($plainContent, array $keyFiles) {
+               // openssl_seal returns false without errors if plaincontent is empty
+               // so trigger our own error
+               if (empty($plainContent)) {
+                       throw new MultiKeyEncryptException('Cannot multikeyencrypt empty plain content');
+               }
+
+               // Set empty vars to be set by openssl by reference
+               $sealed = '';
+               $shareKeys = [];
+               $mappedShareKeys = [];
+
+               if (openssl_seal($plainContent, $sealed, $shareKeys, $keyFiles)) {
+                       $i = 0;
+
+                       // Ensure each shareKey is labelled with its coreesponding keyid
+                       foreach ($keyFiles as $userId => $publicKey) {
+                               $mappedShareKeys[$userId] = $shareKeys[$i];
+                               $i++;
+                       }
+
+                       return [
+                               'keys' => $mappedShareKeys,
+                               'data' => $sealed
+                       ];
+               } else {
+                       throw new MultiKeyEncryptException('multikeyencryption failed ' . openssl_error_string());
+               }
+       }
 }
 
index a535230a6a745dd79d658d28a542cdd86815a9aa..9e6d9cd855c560ba7c146887b409b47edce993f0 100644 (file)
@@ -54,6 +54,8 @@ class HookManager {
        public function fireHooks() {
                foreach ($this->hookInstances as $instance) {
                        /**
+                        * Fire off the add hooks method of each instance stored in cache
+                        *
                         * @var $instance IHook
                         */
                        $instance->addHooks();
index 272bf0849c2b6c4f9d3bbffafae6d28b1a849e05..83b24c79b8ca788d3f9e045b7d207ba4a4974479 100644 (file)
 namespace OCA\Encryption;
 
 
+use OC\Encryption\Exceptions\DecryptionFailedException;
 use OC\Encryption\Exceptions\PrivateKeyMissingException;
 use OC\Encryption\Exceptions\PublicKeyMissingException;
 use OCA\Encryption\Crypto\Crypt;
-use OCP\Encryption\IKeyStorage;
+use OCP\Encryption\Keys\IStorage;
+use OCP\ICache;
+use OCP\ICacheFactory;
 use OCP\IConfig;
-use OCP\IUser;
+use OCP\ILogger;
 use OCP\IUserSession;
 
 class KeyManager {
 
        /**
-        * @var IKeyStorage
+        * @var ICache
+        */
+       public static $cacheFactory;
+       /**
+        * @var IStorage
         */
        private $keyStorage;
-
        /**
         * @var Crypt
         */
@@ -53,35 +59,143 @@ class KeyManager {
         * @var string UserID
         */
        private $keyId;
+       /**
+        * @var string
+        */
+       private $publicKeyId = 'public';
+       /**
+        * @var string
+        */
+       private $privateKeyId = 'private';
 
        /**
         * @var string
         */
-       private $publicKeyId = '.public';
+       private $shareKeyId = 'sharekey';
+
        /**
         * @var string
         */
-       private $privateKeyId = '.private';
+       private $fileKeyId = 'filekey';
        /**
         * @var IConfig
         */
        private $config;
+       /**
+        * @var ILogger
+        */
+       private $log;
 
        /**
-        * @param IKeyStorage $keyStorage
+        * @param IStorage $keyStorage
         * @param Crypt $crypt
         * @param IConfig $config
         * @param IUserSession $userSession
+        * @param ICacheFactory $cacheFactory
+        * @param ILogger $log
         */
-       public function __construct(IKeyStorage $keyStorage, Crypt $crypt, IConfig $config, IUserSession $userSession) {
+       public function __construct(IStorage $keyStorage, Crypt $crypt, IConfig $config, IUserSession $userSession, ICacheFactory $cacheFactory, ILogger $log) {
 
                $this->keyStorage = $keyStorage;
                $this->crypt = $crypt;
                $this->config = $config;
-               $this->recoveryKeyId = $this->config->getAppValue('encryption', 'recoveryKeyId');
-               $this->publicShareKeyId = $this->config->getAppValue('encryption', 'publicShareKeyId');
+               $this->recoveryKeyId = $this->config->getAppValue('encryption',
+                       'recoveryKeyId');
+               $this->publicShareKeyId = $this->config->getAppValue('encryption',
+                       'publicShareKeyId');
                $this->keyId = $userSession && $userSession->isLoggedIn() ? $userSession->getUser()->getUID() : false;
 
+               self::$cacheFactory = $cacheFactory;
+               self::$cacheFactory = self::$cacheFactory->create('encryption');
+               $this->log = $log;
+       }
+
+       /**
+        * @return bool
+        */
+       public function recoveryKeyExists() {
+               return (strlen($this->keyStorage->getSystemUserKey($this->recoveryKeyId)) !== 0);
+       }
+
+       /**
+        * @param $password
+        * @return bool
+        */
+       public function checkRecoveryPassword($password) {
+               $recoveryKey = $this->keyStorage->getSystemUserKey($this->recoveryKeyId);
+               $decryptedRecoveryKey = $this->crypt->decryptPrivateKey($recoveryKey,
+                       $password);
+
+               if ($decryptedRecoveryKey) {
+                       return true;
+               }
+               return false;
+       }
+
+       /**
+        * @param string $uid
+        * @param string $password
+        * @param string $keyPair
+        * @return bool
+        */
+       public function storeKeyPair($uid, $password, $keyPair) {
+               // Save Public Key
+               $this->setPublicKey($uid, $keyPair['publicKey']);
+
+               $encryptedKey = $this->crypt->symmetricEncryptFileContent($keyPair['privateKey'],
+                       $password);
+
+               if ($encryptedKey) {
+                       $this->setPrivateKey($uid, $encryptedKey);
+                       $this->config->setAppValue('encryption', 'recoveryAdminEnabled', 1);
+                       return true;
+               }
+               return false;
+       }
+
+       /**
+        * @param $userId
+        * @param $key
+        * @return bool
+        */
+       public function setPublicKey($userId, $key) {
+               return $this->keyStorage->setUserKey($userId, $this->publicKeyId, $key);
+       }
+
+       /**
+        * @param $userId
+        * @param $key
+        * @return bool
+        */
+       public function setPrivateKey($userId, $key) {
+               return $this->keyStorage->setUserKey($userId,
+                       $this->privateKeyId,
+                       $key);
+       }
+
+       /**
+        * Decrypt private key and store it
+        *
+        * @param string $uid userid
+        * @param string $passPhrase users password
+        * @return ICache
+        */
+       public function init($uid, $passPhrase) {
+               try {
+                       $privateKey = $this->getPrivateKey($uid);
+                       $privateKey = $this->crypt->decryptPrivateKey($privateKey,
+                               $passPhrase);
+               } catch (PrivateKeyMissingException $e) {
+                       return false;
+               } catch (DecryptionFailedException $e) {
+                       return false;
+               }
+
+               self::$cacheFactory->set('privateKey', $privateKey);
+               self::$cacheFactory->set('initStatus', true);
+
+
+               return self::$cacheFactory;
        }
 
        /**
@@ -90,7 +204,8 @@ class KeyManager {
         * @throws PrivateKeyMissingException
         */
        public function getPrivateKey($userId) {
-               $privateKey = $this->keyStorage->getUserKey($userId, $this->privateKeyId);
+               $privateKey = $this->keyStorage->getUserKey($userId,
+                       $this->privateKeyId);
 
                if (strlen($privateKey) !== 0) {
                        return $privateKey;
@@ -99,24 +214,105 @@ class KeyManager {
        }
 
        /**
-        * @param $userId
+        * @param $path
         * @return mixed
-        * @throws PublicKeyMissingException
         */
-       public function getPublicKey($userId) {
-               $publicKey = $this->keyStorage->getUserKey($userId, $this->publicKeyId);
+       public function getFileKey($path) {
+               return $this->keyStorage->getFileKey($path, $this->fileKeyId);
+       }
 
-               if (strlen($publicKey) !== 0) {
-                       return $publicKey;
-               }
-               throw new PublicKeyMissingException();
+       /**
+        * @param $path
+        * @return mixed
+        */
+       public function getShareKey($path) {
+               return $this->keyStorage->getFileKey($path, $this->keyId . $this->shareKeyId);
        }
 
        /**
+        * Change a user's encryption passphrase
+        *
+        * @param array $params keys: uid, password
+        * @param IUserSession $user
+        * @param Util $util
         * @return bool
         */
-       public function recoveryKeyExists() {
-               return (strlen($this->keyStorage->getSystemUserKey($this->recoveryKeyId)) !== 0);
+       public function setPassphrase($params, IUserSession $user, Util $util) {
+
+               // Only attempt to change passphrase if server-side encryption
+               // is in use (client-side encryption does not have access to
+               // the necessary keys)
+               if ($this->crypt->mode() === 'server') {
+
+                       // Get existing decrypted private key
+                       $privateKey = self::$cacheFactory->get('privateKey');
+
+                       if ($params['uid'] === $user->getUser()->getUID() && $privateKey) {
+
+                               // Encrypt private key with new user pwd as passphrase
+                               $encryptedPrivateKey = $this->crypt->symmetricEncryptFileContent($privateKey,
+                                       $params['password']);
+
+                               // Save private key
+                               if ($encryptedPrivateKey) {
+                                       $this->setPrivateKey($user->getUser()->getUID(),
+                                               $encryptedPrivateKey);
+                               } else {
+                                       $this->log->error('Encryption could not update users encryption password');
+                               }
+
+                               // NOTE: Session does not need to be updated as the
+                               // private key has not changed, only the passphrase
+                               // used to decrypt it has changed
+
+
+                       } else { // admin changed the password for a different user, create new keys and reencrypt file keys
+
+                               $user = $params['uid'];
+                               $recoveryPassword = isset($params['recoveryPassword']) ? $params['recoveryPassword'] : null;
+
+                               // we generate new keys if...
+                               // ...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)
+                               ) {
+
+                                       // backup old keys
+                                       $this->backupAllKeys('recovery');
+
+                                       $newUserPassword = $params['password'];
+
+                                       $keypair = $this->crypt->createKeyPair();
+
+                                       // Disable encryption proxy to prevent recursive calls
+                                       $proxyStatus = \OC_FileProxy::$enabled;
+                                       \OC_FileProxy::$enabled = false;
+
+                                       // Save public key
+                                       $this->setPublicKey($user, $keypair['publicKey']);
+
+                                       // Encrypt private key with new password
+                                       $encryptedKey = $this->crypt->symmetricEncryptFileContent($keypair['privateKey'],
+                                               $newUserPassword);
+
+                                       if ($encryptedKey) {
+                                               $this->setPrivateKey($user, $encryptedKey);
+
+                                               if ($recoveryPassword) { // if recovery key is set we can re-encrypt the key files
+                                                       $util->recoverUsersFiles($recoveryPassword);
+                                               }
+                                       } else {
+                                               $this->log->error('Encryption Could not update users encryption password');
+                                       }
+
+                                       \OC_FileProxy::$enabled = $proxyStatus;
+                               }
+                       }
+               }
        }
 
        /**
@@ -136,82 +332,70 @@ class KeyManager {
        }
 
        /**
-        * @param $password
-        * @return bool
+        * @param $userId
+        * @return mixed
+        * @throws PublicKeyMissingException
         */
-       public function checkRecoveryPassword($password) {
-               $recoveryKey = $this->keyStorage->getSystemUserKey($this->recoveryKeyId);
-               $decryptedRecoveryKey = $this->crypt->decryptPrivateKey($recoveryKey, $password);
+       public function getPublicKey($userId) {
+               $publicKey = $this->keyStorage->getUserKey($userId, $this->publicKeyId);
 
-               if ($decryptedRecoveryKey) {
-                       return true;
+               if (strlen($publicKey) !== 0) {
+                       return $publicKey;
                }
-               return false;
+               throw new PublicKeyMissingException();
        }
 
        /**
-        * @param $userId
-        * @param $key
-        * @return bool
+        * @param $purpose
+        * @param bool $timestamp
+        * @param bool $includeUserKeys
         */
-       public function setPublicKey($userId, $key) {
-               return $this->keyStorage->setUserKey($userId, $this->publicKeyId, $key);
+       public function backupAllKeys($purpose, $timestamp = true, $includeUserKeys = true) {
+//             $backupDir = $this->keyStorage->;
        }
 
        /**
-        * @param $userId
-        * @param $key
-        * @return bool
+        * @param string $uid
         */
-       public function setPrivateKey($userId, $key) {
-               return $this->keyStorage->setUserKey($userId, $this->privateKeyId, $key);
+       public function replaceUserKeys($uid) {
+               $this->backupAllKeys('password_reset');
+               $this->deletePublicKey($uid);
+               $this->deletePrivateKey($uid);
        }
 
-
        /**
-        * @param $password
-        * @param $keyPair
+        * @param $uid
         * @return bool
         */
-       public function storeKeyPair($password, $keyPair) {
-               // Save Public Key
-               $this->setPublicKey($this->keyId, $keyPair['publicKey']);
-
-               $encryptedKey = $this->crypt->symmetricEncryptFileContent($keyPair['privateKey'], $password);
-
-               if ($encryptedKey) {
-                       $this->setPrivateKey($this->keyId, $encryptedKey);
-                       $this->config->setAppValue('encryption', 'recoveryAdminEnabled', 1);
-                       return true;
-               }
-               return false;
+       public function deletePublicKey($uid) {
+               return $this->keyStorage->deleteUserKey($uid, $this->publicKeyId);
        }
 
        /**
+        * @param $uid
         * @return bool
         */
-       public function ready() {
-               return $this->keyStorage->ready();
+       private function deletePrivateKey($uid) {
+               return $this->keyStorage->deleteUserKey($uid, $this->privateKeyId);
        }
 
-
        /**
-        * @return \OCP\ICache
-        * @throws PrivateKeyMissingException
+        * @param array $userIds
+        * @return array
+        * @throws PublicKeyMissingException
         */
-       public function init() {
-               try {
-                       $privateKey = $this->getPrivateKey($this->keyId);
-               } catch (PrivateKeyMissingException $e) {
-                       return false;
-               }
+       public function getPublicKeys(array $userIds) {
+               $keys = [];
 
-               $cache = \OC::$server->getMemCacheFactory();
+               foreach ($userIds as $userId) {
+                       try {
+                               $keys[$userId] = $this->getPublicKey($userId);
+                       } catch (PublicKeyMissingException $e) {
+                               continue;
+                       }
+               }
 
-               $cacheInstance = $cache->create('Encryption');
-               $cacheInstance->set('privateKey', $privateKey);
+               return $keys;
 
-               return $cacheInstance;
        }
-
 }
diff --git a/apps/encryption/lib/migrator.php b/apps/encryption/lib/migrator.php
deleted file mode 100644 (file)
index 8f7823c..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-<?php
-/**
- * @author Clark Tomlinson  <fallen013@gmail.com>
- * @since 3/9/15, 2:44 PM
- * @link http:/www.clarkt.com
- * @copyright Clark Tomlinson © 2015
- *
- */
-
-namespace OCA\Encryption;
-
-
-use OCA\Encryption\Crypto\Crypt;
-use OCP\IConfig;
-use OCP\ILogger;
-use OCP\IUserManager;
-use OCP\IUserSession;
-use OCP\PreConditionNotMetException;
-
-class Migrator {
-
-       /**
-        * @var bool
-        */
-       private $status = false;
-       /**
-        * @var IUserManager
-        */
-       private $user;
-       /**
-        * @var IConfig
-        */
-       private $config;
-       /**
-        * @var string
-        */
-       public static $migrationOpen = '0';
-       /**
-        * @var string
-        */
-       public static $migrationInProgress = '-1';
-       /**
-        * @var string
-        */
-       public static $migrationComplete = '1';
-       /**
-        * @var IUserManager
-        */
-       private $userManager;
-       /**
-        * @var ILogger
-        */
-       private $log;
-       /**
-        * @var Crypt
-        */
-       private $crypt;
-
-       /**
-        * Migrator constructor.
-        *
-        * @param IUserSession $userSession
-        * @param IConfig $config
-        * @param IUserManager $userManager
-        * @param ILogger $log
-        * @param Crypt $crypt
-        */
-       public function __construct(IUserSession $userSession, IConfig $config, IUserManager $userManager, ILogger $log, Crypt $crypt) {
-               $this->user = $userSession && $userSession->isLoggedIn() ? $userSession->getUser() : false;
-               $this->config = $config;
-               $this->userManager = $userManager;
-               $this->log = $log;
-               $this->crypt = $crypt;
-       }
-
-       /**
-        * @param $userId
-        * @return bool|string
-        */
-       public function getStatus($userId) {
-               if ($this->userManager->userExists($userId)) {
-                       $this->status = $this->config->getUserValue($userId, 'encryption', 'migrationStatus', false);
-
-                       if (!$this->status) {
-                               $this->config->setUserValue($userId, 'encryption', 'migrationStatus', self::$migrationOpen);
-                               $this->status = self::$migrationOpen;
-                       }
-               }
-
-               return $this->status;
-       }
-
-       /**
-        * @return bool
-        */
-       public function beginMigration() {
-               $status = $this->setMigrationStatus(self::$migrationInProgress, self::$migrationOpen);
-
-               if ($status) {
-                       $this->log->info('Encryption Library Start migration to encrypt for ' . $this->user->getUID());
-                       return $status;
-               }
-               $this->log->warning('Encryption Library Could not activate migration for ' . $this->user->getUID() . '. Probably another process already started the inital encryption');
-               return $status;
-       }
-
-       /**
-        * @param $status
-        * @param bool $preCondition
-        * @return bool
-        */
-       private function setMigrationStatus($status, $preCondition = false) {
-               // Convert to string if preCondition is set
-               $preCondition = ($preCondition === false) ? false : (string)$preCondition;
-
-               try {
-                       $this->config->setUserValue($this->user->getUID(), 'encryption', 'migrationStatus', (string)$status, $preCondition);
-                       return true;
-               } catch (PreConditionNotMetException $e) {
-                       return false;
-               }
-       }
-}
index 88350e96c5368564879d56e8a128add6d09781f9..457184b4b96123e635faed654ade6bcd8282b3d9 100644 (file)
 namespace OCA\Encryption;
 
 
-use OC\Files\View;
 use OCA\Encryption\Crypto\Crypt;
-use OCP\Encryption\IKeyStorage;
+use OCP\Encryption\Keys\IStorage;
 use OCP\IConfig;
 use OCP\IUser;
+use OCP\IUserSession;
+use OCP\PreConditionNotMetException;
 use OCP\Security\ISecureRandom;
 
 class Recovery {
@@ -58,20 +59,20 @@ class Recovery {
        private $keyStorage;
 
        /**
-        * @param IUser $user
+        * @param IUserSession $user
         * @param Crypt $crypt
         * @param ISecureRandom $random
         * @param KeyManager $keyManager
         * @param IConfig $config
-        * @param IKeyStorage $keyStorage
+        * @param IStorage $keyStorage
         */
-       public function __construct(IUser $user,
+       public function __construct(IUserSession $user,
                                                                Crypt $crypt,
                                                                ISecureRandom $random,
                                                                KeyManager $keyManager,
                                                                IConfig $config,
-                                                               IKeyStorage $keyStorage) {
-               $this->user = $user;
+                                                               IStorage $keyStorage) {
+               $this->user = $user && $user->isLoggedIn() ? $user->getUser() : false;
                $this->crypt = $crypt;
                $this->random = $random;
                $this->keyManager = $keyManager;
@@ -97,7 +98,7 @@ class Recovery {
                if (!$keyManager->recoveryKeyExists()) {
                        $keyPair = $this->crypt->createKeyPair();
 
-                       return $this->keyManager->storeKeyPair($password, $keyPair);
+                       return $this->keyManager->storeKeyPair($this->user->getUID(), $password, $keyPair);
                }
 
                if ($keyManager->checkRecoveryPassword($password)) {
@@ -131,4 +132,45 @@ class Recovery {
                // No idea new way to do this....
        }
 
+       /**
+        * @return bool
+        */
+       public function recoveryEnabledForUser() {
+               $recoveryMode = $this->config->getUserValue($this->user->getUID(),
+                       'encryption',
+                       'recoveryEnabled',
+                       0);
+
+               return ($recoveryMode === '1');
+       }
+       /**
+        * @param $enabled
+        * @return bool
+        */
+       public function setRecoveryForUser($enabled) {
+               $value = $enabled ? '1' : '0';
+
+               try {
+                       $this->config->setUserValue($this->user->getUID(),
+                               'encryption',
+                               'recoveryEnabled',
+                               $value);
+                       return true;
+               } catch (PreConditionNotMetException $e) {
+                       return false;
+               }
+       }
+
+       /**
+        * @param $recoveryPassword
+        */
+       public function recoverUsersFiles($recoveryPassword) {
+               // todo: get system private key here
+//             $this->keyManager->get
+               $privateKey = $this->crypt->decryptPrivateKey($encryptedKey,
+                       $recoveryPassword);
+
+               $this->recoverAllFiles('/', $privateKey);
+       }
+
 }
index 123d6973be99e63623355799052984527dea71ef..662a4b4b6afe78e103cadaaf9b32564432550711 100644 (file)
@@ -39,24 +39,24 @@ class Setup extends \OCA\Encryption\Setup {
        }
 
        /**
-        * @param $password
+        * @param $uid userid
+        * @param $password user password
         * @return bool
         */
-       public function setupUser($password) {
-               if ($this->keyManager->ready()) {
-                       $this->logger->debug('Encryption Library: User Account ' . $this->user->getUID() . ' Is not ready for encryption; configuration started');
-                       return $this->setupServerSide($password);
-               }
+       public function setupUser($uid, $password) {
+               return $this->setupServerSide($uid, $password);
        }
 
        /**
-        * @param $password
+        * @param $uid userid
+        * @param $password user password
         * @return bool
         */
-       private function setupServerSide($password) {
+       public function setupServerSide($uid, $password) {
                // Check if user already has keys
-               if (!$this->keyManager->userHasKeys($this->user->getUID())) {
-                       return $this->keyManager->storeKeyPair($password, $this->crypt->createKeyPair());
+               if (!$this->keyManager->userHasKeys($uid)) {
+                       return $this->keyManager->storeKeyPair($uid, $password,
+                               $this->crypt->createKeyPair());
                }
                return true;
        }
diff --git a/apps/encryption/lib/util.php b/apps/encryption/lib/util.php
new file mode 100644 (file)
index 0000000..5cc658a
--- /dev/null
@@ -0,0 +1,394 @@
+<?php
+/**
+ * @author Clark Tomlinson  <clark@owncloud.com>
+ * @since 3/17/15, 10:31 AM
+ * @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;
+
+
+use OC\Files\Filesystem;
+use OC\Files\View;
+use OCA\Encryption\Crypto\Crypt;
+use OCA\Files_Versions\Storage;
+use OCP\App;
+use OCP\IConfig;
+use OCP\ILogger;
+use OCP\IUser;
+use OCP\IUserSession;
+use OCP\PreConditionNotMetException;
+use OCP\Share;
+
+class Util {
+       /**
+        * @var View
+        */
+       private $files;
+       /**
+        * @var Filesystem
+        */
+       private $filesystem;
+       /**
+        * @var Crypt
+        */
+       private $crypt;
+       /**
+        * @var KeyManager
+        */
+       private $keyManager;
+       /**
+        * @var ILogger
+        */
+       private $logger;
+       /**
+        * @var bool|IUser
+        */
+       private $user;
+       /**
+        * @var IConfig
+        */
+       private $config;
+
+       /**
+        * Util constructor.
+        *
+        * @param View $files
+        * @param Filesystem $filesystem
+        * @param Crypt $crypt
+        * @param KeyManager $keyManager
+        * @param ILogger $logger
+        * @param IUserSession $userSession
+        * @param IConfig $config
+        */
+       public function __construct(
+               View $files,
+               Filesystem $filesystem,
+               Crypt $crypt,
+               KeyManager $keyManager,
+               ILogger $logger,
+               IUserSession $userSession,
+               IConfig $config
+       ) {
+               $this->files = $files;
+               $this->filesystem = $filesystem;
+               $this->crypt = $crypt;
+               $this->keyManager = $keyManager;
+               $this->logger = $logger;
+               $this->user = $userSession && $userSession->isLoggedIn() ? $userSession->getUser() : false;
+               $this->config = $config;
+       }
+
+       /**
+        * @param $dirPath
+        * @param bool $found
+        * @return array|bool
+        */
+       private function findEncryptedFiles($dirPath, &$found = false) {
+
+               if ($found === false) {
+                       $found = [
+                               'plain' => [],
+                               'encrypted' => [],
+                               'broken' => [],
+                       ];
+               }
+
+               if ($this->files->is_dir($dirPath) && $handle = $this->files->opendir($dirPath)) {
+                       if (is_resource($handle)) {
+                               while (($file = readdir($handle) !== false)) {
+                                       if ($file !== '.' && $file !== '..') {
+
+                                               // Skip stray part files
+                                               if ($this->isPartialFilePath($file)) {
+                                                       continue;
+                                               }
+
+                                               $filePath = $dirPath . '/' . $this->files->getRelativePath('/' . $file);
+                                               $relPath = $this->stripUserFilesPath($filePath);
+
+                                               // If the path is a directory, search its contents
+                                               if ($this->files->is_dir($filePath)) {
+                                                       // Recurse back
+                                                       $this->findEncryptedFiles($filePath);
+
+                                                       /*
+                                                        * If the path is a file,
+                                                        * determine where they got re-enabled :/
+                                                       */
+                                               } elseif ($this->files->is_file($filePath)) {
+                                                       $isEncryptedPath = $this->isEncryptedPath($filePath);
+
+                                                       /**
+                                                        * If the file is encrypted
+                                                        *
+                                                        * @note: if the userId is
+                                                        * empty or not set, file will
+                                                        * be detected as plain
+                                                        * @note: this is inefficient;
+                                                        * scanning every file like this
+                                                        * will eat server resources :(
+                                                        * fixMe: xxx find better way
+                                                        */
+                                                       if ($isEncryptedPath) {
+                                                               $fileKey = $this->keyManager->getFileKey($relPath);
+                                                               $shareKey = $this->keyManager->getShareKey($relPath);
+                                                               // If file is encrypted but now file key is available, throw exception
+                                                               if (!$fileKey || !$shareKey) {
+                                                                       $this->logger->error('Encryption library, no keys avilable to decrypt the file: ' . $file);
+                                                                       $found['broken'][] = [
+                                                                               'name' => $file,
+                                                                               'path' => $filePath,
+                                                                       ];
+                                                               } else {
+                                                                       $found['encrypted'][] = [
+                                                                               'name' => $file,
+                                                                               'path' => $filePath
+                                                                       ];
+                                                               }
+                                                       } else {
+                                                               $found['plain'][] = [
+                                                                       'name' => $file,
+                                                                       'path' => $filePath
+                                                               ];
+                                                       }
+                                               }
+                                       }
+
+                               }
+                       }
+               }
+
+               return $found;
+       }
+
+       /**
+        * @param $path
+        * @return bool
+        */
+       private function isPartialFilePath($path) {
+               $extension = pathinfo($path, PATHINFO_EXTENSION);
+
+               if ($extension === 'part') {
+                       return true;
+               }
+               return false;
+       }
+
+       /**
+        * @param $filePath
+        * @return bool|string
+        */
+       private function stripUserFilesPath($filePath) {
+               $split = $this->splitPath($filePath);
+
+               // It is not a file relative to data/user/files
+               if (count($split) < 4 || $split[2] !== 'files') {
+                       return false;
+               }
+
+               $sliced = array_slice($split, 3);
+
+               return implode('/', $sliced);
+
+       }
+
+       /**
+        * @param $filePath
+        * @return array
+        */
+       private function splitPath($filePath) {
+               $normalized = $this->filesystem->normalizePath($filePath);
+
+               return explode('/', $normalized);
+       }
+
+       /**
+        * @param $filePath
+        * @return bool
+        */
+       private function isEncryptedPath($filePath) {
+               $data = '';
+
+               // We only need 24 bytes from the last chunck
+               if ($this->files->file_exists($filePath)) {
+                       $handle = $this->files->fopen($filePath, 'r');
+                       if (is_resource($handle)) {
+                               // Suppress fseek warning, we handle the case that fseek
+                               // doesn't work in the else branch
+                               if (@fseek($handle, -24, SEEK_END) === 0) {
+                                       $data = fgets($handle);
+                               } else {
+                                       // if fseek failed on the storage we create a local copy
+                                       // from the file and read this one
+                                       fclose($handle);
+                                       $localFile = $this->files->getLocalFile($filePath);
+                                       $handle = fopen($localFile, 'r');
+
+                                       if (is_resource($handle) && fseek($handle,
+                                                       -24,
+                                                       SEEK_END) === 0
+                                       ) {
+                                               $data = fgets($handle);
+                                       }
+                               }
+                               fclose($handle);
+                               return $this->crypt->isCatfileContent($data);
+                       }
+               }
+       }
+
+       /**
+        * @return bool
+        */
+       public function recoveryEnabledForUser() {
+               $recoveryMode = $this->config->getUserValue($this->user->getUID(),
+                       'encryption',
+                       'recoveryEnabled',
+                       0);
+
+               return ($recoveryMode === '1');
+       }
+
+       /**
+        * @param $enabled
+        * @return bool
+        */
+       public function setRecoveryForUser($enabled) {
+               $value = $enabled ? '1' : '0';
+
+               try {
+                       $this->config->setUserValue($this->user->getUID(),
+                               'encryption',
+                               'recoveryEnabled',
+                               $value);
+                       return true;
+               } catch (PreConditionNotMetException $e) {
+                       return false;
+               }
+       }
+
+       /**
+        * @param $recoveryPassword
+        */
+       public function recoverUsersFiles($recoveryPassword) {
+               // todo: get system private key here
+//             $this->keyManager->get
+               $privateKey = $this->crypt->decryptPrivateKey($encryptedKey,
+                       $recoveryPassword);
+
+               $this->recoverAllFiles('/', $privateKey);
+       }
+
+       /**
+        * @param string $uid
+        * @return bool
+        */
+       public function userHasFiles($uid) {
+               return $this->files->file_exists($uid . '/files');
+       }
+
+       /**
+        * @param $path
+        * @param $privateKey
+        */
+       private function recoverAllFiles($path, $privateKey) {
+               // Todo relocate to storage
+               $dirContent = $this->files->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)) {
+                               $this->recoverAllFiles($filePath . '/', $privateKey);
+                       } else {
+                               $this->recoverFile($filePath, $privateKey);
+                       }
+               }
+
+       }
+
+       /**
+        * @param $filePath
+        * @param $privateKey
+        */
+       private function recoverFile($filePath, $privateKey) {
+               $sharingEnabled = Share::isEnabled();
+
+               // Find out who, if anyone, is sharing the file
+               if ($sharingEnabled) {
+                       $result = Share::getUsersSharingFile($filePath,
+                               $this->user->getUID(),
+                               true);
+                       $userIds = $result['users'];
+                       $userIds[] = 'public';
+               } else {
+                       $userIds = [
+                               $this->user->getUID(),
+                               $this->recoveryKeyId
+                       ];
+               }
+               $filteredUids = $this->filterShareReadyUsers($userIds);
+
+               // Decrypt file key
+               $encKeyFile = $this->keyManager->getFileKey($filePath);
+               $shareKey = $this->keyManager->getShareKey($filePath);
+               $plainKeyFile = $this->crypt->multiKeyDecrypt($encKeyFile,
+                       $shareKey,
+                       $privateKey);
+
+               // 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);
+
+               $this->keyManager->setFileKeys($multiEncryptionKey['data']);
+               $this->keyManager->setShareKeys($multiEncryptionKey['keys']);
+       }
+
+       /**
+        * @param $userIds
+        * @return array
+        */
+       private function filterShareReadyUsers($userIds) {
+               // This array will collect the filtered IDs
+               $readyIds = $unreadyIds = [];
+
+               // Loop though users and create array of UIDs that need new keyfiles
+               foreach ($userIds as $user) {
+                       // Check that the user is encryption capable, or is the
+                       // public system user (for public shares)
+                       if ($this->isUserReady($user)) {
+                               // construct array of ready UIDs for keymanager
+                               $readyIds[] = $user;
+                       } else {
+                               // Construct array of unready UIDs for keymanager
+                               $unreadyIds[] = $user;
+
+                               // Log warning; we cant do necessary setup here
+                               // because we don't have the user passphrase
+                               $this->logger->warning('Encryption Library ' . $this->user->getUID() . ' is not setup for encryption');
+                       }
+               }
+               return [
+                       'ready' => $readyIds,
+                       'unready' => $unreadyIds
+               ];
+       }
+
+}
index 0f5d56a3734bf596df3e0494b7d8e7b41705060b..d3acdfe2ba4b0f5b656f581e0308b3880b3ffcd0 100644 (file)
@@ -6,17 +6,17 @@
  * See the COPYING-README file.
  */
 
+use OCA\Encryption\KeyManager;
+
 \OC_Util::checkAdminUser();
 
 $tmpl = new OCP\Template('files_encryption', 'settings-admin');
 
 // Check if an adminRecovery account is enabled for recovering files after lost pwd
-$recoveryAdminEnabled = \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryAdminEnabled', '0');
-$session = new \OCA\Files_Encryption\Session(new \OC\Files\View('/'));
-$initStatus = $session->getInitialized();
+$recoveryAdminEnabled = \OC::$server->getConfig()->getAppValue('encryption', 'recoveryAdminEnabled', '0');
 
 $tmpl->assign('recoveryEnabled', $recoveryAdminEnabled);
-$tmpl->assign('initStatus', $initStatus);
+$tmpl->assign('initStatus', KeyManager::$cacheFactory->get('initStatus'));
 
 \OCP\Util::addscript('files_encryption', 'settings-admin');
 \OCP\Util::addscript('core', 'multiselect');
index 260e69a73bfcc399d53ae6e0febed847cb6412a1..01c5e1d2d07853adcc7df39c5cde22188182edea 100644 (file)
@@ -27,33 +27,42 @@ class KeyManagerTest extends TestCase {
         */
        private $dummyKeys;
 
+       /**
+        *
+        */
        public function setUp() {
                parent::setUp();
-               $keyStorageMock = $this->getMock('OCP\Encryption\IKeyStorage');
-               $cryptMock = $this->getMockBuilder('OCA\Encryption\Crypt')
+               $keyStorageMock = $this->getMock('OCP\Encryption\Keys\IStorage');
+               $keyStorageMock->method('getUserKey')
+                       ->will($this->returnValue(false));
+               $keyStorageMock->method('setUserKey')
+                       ->will($this->returnValue(true));
+               $cryptMock = $this->getMockBuilder('OCA\Encryption\Crypto\Crypt')
                        ->disableOriginalConstructor()
                        ->getMock();
                $configMock = $this->getMock('OCP\IConfig');
-               $userMock = $this->getMock('OCP\IUser');
-               $userMock->expects($this->once())
+               $userMock = $this->getMock('OCP\IUserSession');
+               $userMock
                        ->method('getUID')
                        ->will($this->returnValue('admin'));
+               $cacheMock = $this->getMock('OCP\ICacheFactory');
+               $logMock = $this->getMock('OCP\ILogger');
                $this->userId = 'admin';
-               $this->instance = new KeyManager($keyStorageMock, $cryptMock, $configMock, $userMock);
+               $this->instance = new KeyManager($keyStorageMock, $cryptMock, $configMock, $userMock, $cacheMock, $logMock);
 
                $this->dummyKeys = ['public' => 'randomweakpublickeyhere',
                        'private' => 'randomweakprivatekeyhere'];
        }
 
        /**
-        * @expectedException OC\Encryption\Exceptions\PrivateKeyMissingException
+        * @expectedException \OC\Encryption\Exceptions\PrivateKeyMissingException
         */
        public function testGetPrivateKey() {
                $this->assertFalse($this->instance->getPrivateKey($this->userId));
        }
 
        /**
-        * @expectedException OC\Encryption\Exceptions\PublicKeyMissingException
+        * @expectedException \OC\Encryption\Exceptions\PublicKeyMissingException
         */
        public function testGetPublicKey() {
                $this->assertFalse($this->instance->getPublicKey($this->userId));
@@ -73,18 +82,34 @@ class KeyManagerTest extends TestCase {
                $this->assertFalse($this->instance->checkRecoveryPassword('pass'));
        }
 
+       /**
+        *
+        */
        public function testSetPublicKey() {
 
                $this->assertTrue($this->instance->setPublicKey($this->userId, $this->dummyKeys['public']));
        }
 
+       /**
+        *
+        */
        public function testSetPrivateKey() {
                $this->assertTrue($this->instance->setPrivateKey($this->userId, $this->dummyKeys['private']));
        }
 
+       /**
+        *
+        */
        public function testUserHasKeys() {
                $this->assertFalse($this->instance->userHasKeys($this->userId));
        }
 
+       /**
+        *
+        */
+       public function testInit() {
+               $this->assertFalse($this->instance->init($this->userId, 'pass'));
+       }
+
 
 }
index a9d57b342094b30cc530e8a9a54312d9e7e2cc24..0d30b9865b912f1c637758cb61b259d5eee17ace 100644 (file)
@@ -51,8 +51,7 @@ class MigratorTest extends TestCase {
                parent::setUp();
 
                $cryptMock = $this->getMockBuilder('OCA\Encryption\Crypto\Crypt')->disableOriginalConstructor()->getMock();
-               $this->instance = new Migrator($this->getMock('OCP\IUser'),
-                       $this->getMock('OCP\IConfig'),
+               $this->instance = new Migrator($this->getMock('OCP\IConfig'),
                        $this->getMock('OCP\IUserManager'),
                        $this->getMock('OCP\ILogger'),
                        $cryptMock);
index 536e512bdb23626b9414e635ce430570f32fa048..4a29ffaaedfe13b1a54ec9f10e72575b7b6cf805 100644 (file)
@@ -34,8 +34,234 @@ class Hooks {
        // file for which we want to delete the keys after the delete operation was successful
        private static $unmountedFiles = array();
 
+       /**
+        * Startup encryption backend upon user login
+        * @note This method should never be called for users using client side encryption
+        */
+       public static function login($params) {
+
+               if (\OCP\App::isEnabled('files_encryption') === false) {
+                       return true;
+               }
+
+
+               $l = new \OC_L10N('files_encryption');
+
+               $view = new \OC\Files\View('/');
+
+               // ensure filesystem is loaded
+               if (!\OC\Files\Filesystem::$loaded) {
+                       \OC_Util::setupFS($params['uid']);
+               }
+
+               $privateKey = Keymanager::getPrivateKey($view, $params['uid']);
+
+               // if no private key exists, check server configuration
+               if (!$privateKey) {
+                       //check if all requirements are met
+                       if (!Helper::checkRequirements() || !Helper::checkConfiguration()) {
+                               $error_msg = $l->t("Missing requirements.");
+                               $hint = $l->t('Please make sure that OpenSSL together with the PHP extension is enabled and configured properly. For now, the encryption app has been disabled.');
+                               \OC_App::disable('files_encryption');
+                               \OCP\Util::writeLog('Encryption library', $error_msg . ' ' . $hint, \OCP\Util::ERROR);
+                               \OCP\Template::printErrorPage($error_msg, $hint);
+                       }
+               }
+
+               $util = new Util($view, $params['uid']);
+
+               // setup user, if user not ready force relogin
+               if (Helper::setupUser($util, $params['password']) === false) {
+                       return false;
+               }
+
+               $session = $util->initEncryption($params);
+
+               // Check if first-run file migration has already been performed
+               $ready = false;
+               $migrationStatus = $util->getMigrationStatus();
+               if ($migrationStatus === Util::MIGRATION_OPEN && $session !== false) {
+                       $ready = $util->beginMigration();
+               } elseif ($migrationStatus === Util::MIGRATION_IN_PROGRESS) {
+                       // refuse login as long as the initial encryption is running
+                       sleep(5);
+                       \OCP\User::logout();
+                       return false;
+               }
+
+               $result = true;
+
+               // If migration not yet done
+               if ($ready) {
+
+                       // Encrypt existing user files
+                       try {
+                               $result = $util->encryptAll('/' . $params['uid'] . '/' . 'files');
+                       } catch (\Exception $ex) {
+                               \OCP\Util::writeLog('Encryption library', 'Initial encryption failed! Error: ' . $ex->getMessage(), \OCP\Util::FATAL);
+                               $result = false;
+                       }
+
+                       if ($result) {
+                               \OC_Log::write(
+                                               'Encryption library', 'Encryption of existing files belonging to "' . $params['uid'] . '" completed'
+                                               , \OC_Log::INFO
+                                       );
+                               // Register successful migration in DB
+                               $util->finishMigration();
+                       } else  {
+                               \OCP\Util::writeLog('Encryption library', 'Initial encryption failed!', \OCP\Util::FATAL);
+                               $util->resetMigrationStatus();
+                               \OCP\User::logout();
+                       }
+               }
+
+               return $result;
+       }
+
+       /**
+        * remove keys from session during logout
+        */
+       public static function logout() {
+               $session = new Session(new \OC\Files\View());
+               $session->removeKeys();
+       }
+
+       /**
+        * setup encryption backend upon user created
+        * @note This method should never be called for users using client side encryption
+        */
+       public static function postCreateUser($params) {
+
+               if (\OCP\App::isEnabled('files_encryption')) {
+                       $view = new \OC\Files\View('/');
+                       $util = new Util($view, $params['uid']);
+                       Helper::setupUser($util, $params['password']);
+               }
+       }
+
+       /**
+        * cleanup encryption backend upon user deleted
+        * @note This method should never be called for users using client side encryption
+        */
+       public static function postDeleteUser($params) {
+
+               if (\OCP\App::isEnabled('files_encryption')) {
+                       Keymanager::deletePublicKey(new \OC\Files\View(), $params['uid']);
+               }
+       }
+
+       /**
+        * If the password can't be changed within ownCloud, than update the key password in advance.
+        */
+       public static function preSetPassphrase($params) {
+               if (\OCP\App::isEnabled('files_encryption')) {
+                       if ( ! \OC_User::canUserChangePassword($params['uid']) ) {
+                               self::setPassphrase($params);
+                       }
+               }
+       }
+
+       /**
+        * Change a user's encryption passphrase
+        * @param array $params keys: uid, password
+        */
+       public static function setPassphrase($params) {
+               if (\OCP\App::isEnabled('files_encryption') === false) {
+                       return true;
+               }
+
+               // Only attempt to change passphrase if server-side encryption
+               // is in use (client-side encryption does not have access to
+               // the necessary keys)
+               if (Crypt::mode() === 'server') {
+
+                       $view = new \OC\Files\View('/');
+                       $session = new Session($view);
+
+                       // Get existing decrypted private key
+                       $privateKey = $session->getPrivateKey();
+
+                       if ($params['uid'] === \OCP\User::getUser() && $privateKey) {
+
+                               // Encrypt private key with new user pwd as passphrase
+                               $encryptedPrivateKey = Crypt::symmetricEncryptFileContent($privateKey, $params['password'], Helper::getCipher());
+
+                               // Save private key
+                               if ($encryptedPrivateKey) {
+                                       Keymanager::setPrivateKey($encryptedPrivateKey, \OCP\User::getUser());
+                               } else {
+                                       \OCP\Util::writeLog('files_encryption', 'Could not update users encryption password', \OCP\Util::ERROR);
+                               }
+
+                               // NOTE: Session does not need to be updated as the
+                               // private key has not changed, only the passphrase
+                               // used to decrypt it has changed
 
 
+                       } else { // admin changed the password for a different user, create new keys and reencrypt file keys
+
+                               $user = $params['uid'];
+                               $util = new Util($view, $user);
+                               $recoveryPassword = isset($params['recoveryPassword']) ? $params['recoveryPassword'] : null;
+
+                               // we generate new keys if...
+                               // ...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)
+                                               || !$util->userKeysExists()
+                                               || !$view->file_exists($user . '/files')) {
+
+                                       // backup old keys
+                                       $util->backupAllKeys('recovery');
+
+                                       $newUserPassword = $params['password'];
+
+                                       // make sure that the users home is mounted
+                                       \OC\Files\Filesystem::initMountPoints($user);
+
+                                       $keypair = Crypt::createKeypair();
+
+                                       // Disable encryption proxy to prevent recursive calls
+                                       $proxyStatus = \OC_FileProxy::$enabled;
+                                       \OC_FileProxy::$enabled = false;
+
+                                       // Save public key
+                                       Keymanager::setPublicKey($keypair['publicKey'], $user);
+
+                                       // Encrypt private key with new password
+                                       $encryptedKey = Crypt::symmetricEncryptFileContent($keypair['privateKey'], $newUserPassword, Helper::getCipher());
+                                       if ($encryptedKey) {
+                                               Keymanager::setPrivateKey($encryptedKey, $user);
+
+                                               if ($recoveryPassword) { // if recovery key is set we can re-encrypt the key files
+                                                       $util = new Util($view, $user);
+                                                       $util->recoverUsersFiles($recoveryPassword);
+                                               }
+                                       } else {
+                                               \OCP\Util::writeLog('files_encryption', 'Could not update users encryption password', \OCP\Util::ERROR);
+                                       }
+
+                                       \OC_FileProxy::$enabled = $proxyStatus;
+                               }
+                       }
+               }
+       }
+
+       /**
+        * after password reset we create a new key pair for the user
+        *
+        * @param array $params
+        */
+       public static function postPasswordReset($params) {
+               $uid = $params['uid'];
+               $password = $params['password'];
+
+               $util = new Util(new \OC\Files\View(), $uid);
+               $util->replaceUserKeys($password);
+       }
+
        /*
         * check if files can be encrypted to every user.
         */
index 8c5169f229e39b0fa3992891f3823cfe885a72aa..6a2e45aa59de041555ca1923ee6db00dcdbd159c 100644 (file)
@@ -702,7 +702,7 @@ class Server extends SimpleContainer implements IServerContainer {
         *
         * @return \OCP\Security\ISecureRandom
         */
-       function getSecureRandom() {
+function getSecureRandom() {
                return $this->query('SecureRandom');
        }