summaryrefslogtreecommitdiffstats
path: root/apps/files_encryption
diff options
context:
space:
mode:
authorClark Tomlinson <fallen013@gmail.com>2015-03-24 17:29:10 -0400
committerThomas Müller <thomas.mueller@tmit.eu>2015-04-07 13:30:27 +0200
commit0c2f9ca849ef41232511cf576cc9a9de2caa43f0 (patch)
treea75194b573985da4a68684cb5a74c9891db34696 /apps/files_encryption
parent506222567e71fc0d77fa77ee7805c93fa7655b6c (diff)
downloadnextcloud-server-0c2f9ca849ef41232511cf576cc9a9de2caa43f0.tar.gz
nextcloud-server-0c2f9ca849ef41232511cf576cc9a9de2caa43f0.zip
Updating keystorage movement and fixing hooks
Diffstat (limited to 'apps/files_encryption')
-rw-r--r--apps/files_encryption/lib/hooks.php226
1 files changed, 226 insertions, 0 deletions
diff --git a/apps/files_encryption/lib/hooks.php b/apps/files_encryption/lib/hooks.php
index 536e512bdb2..4a29ffaaedf 100644
--- a/apps/files_encryption/lib/hooks.php
+++ b/apps/files_encryption/lib/hooks.php
@@ -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.
*/