From 4843e5ce301c4ac1e4cccf21b7d33e5e2a2b3042 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Tue, 31 Mar 2015 12:01:51 +0200 Subject: [PATCH] use password change logic to userhooks to avoid recursions --- apps/encryption/appinfo/application.php | 6 +- apps/encryption/hooks/userhooks.php | 86 +++++++++++++++++++++++-- apps/encryption/lib/keymanager.php | 75 +-------------------- apps/encryption/lib/session.php | 11 ++++ 4 files changed, 95 insertions(+), 83 deletions(-) diff --git a/apps/encryption/appinfo/application.php b/apps/encryption/appinfo/application.php index 21d7f3e737f..be432b1a5a8 100644 --- a/apps/encryption/appinfo/application.php +++ b/apps/encryption/appinfo/application.php @@ -77,7 +77,8 @@ class Application extends \OCP\AppFramework\App { $container->query('UserSetup'), $server->getUserSession(), $container->query('Util'), - new \OCA\Encryption\Session($server->getSession())), + new \OCA\Encryption\Session($server->getSession()), + $container->query('Recovery')) ]); $hookManager->fireHooks(); @@ -126,8 +127,7 @@ class Application extends \OCP\AppFramework\App { $server->getConfig(), $server->getUserSession(), new \OCA\Encryption\Session($server->getSession()), - $server->getLogger(), - $c->query('Recovery') + $server->getLogger() ); }); diff --git a/apps/encryption/hooks/userhooks.php b/apps/encryption/hooks/userhooks.php index 27780cccfbf..330d8a873ba 100644 --- a/apps/encryption/hooks/userhooks.php +++ b/apps/encryption/hooks/userhooks.php @@ -31,6 +31,7 @@ use OCP\ILogger; use OCP\IUserSession; use OCA\Encryption\Util; use OCA\Encryption\Session; +use OCA\Encryption\Recovery; class UserHooks implements IHook { /** @@ -57,6 +58,10 @@ class UserHooks implements IHook { * @var Session */ private $session; + /** + * @var Recovery + */ + private $recovery; /** * UserHooks constructor. @@ -67,13 +72,15 @@ class UserHooks implements IHook { * @param IUserSession $user * @param Util $util * @param Session $session + * @param Recovery $recovery */ public function __construct(KeyManager $keyManager, ILogger $logger, Setup $userSetup, IUserSession $user, Util $util, - Session $session) { + Session $session, + Recovery $recovery) { $this->keyManager = $keyManager; $this->logger = $logger; @@ -81,6 +88,7 @@ class UserHooks implements IHook { $this->user = $user; $this->util = $util; $this->session = $session; + $this->recovery = $recovery; } /** @@ -141,7 +149,7 @@ class UserHooks implements IHook { * remove keys from session during logout */ public function logout() { - KeyManager::$session->clear(); + $this->session->clear(); } /** @@ -180,17 +188,81 @@ class UserHooks implements IHook { if (App::isEnabled('encryption')) { if (!$this->user->getUser()->canChangePassword()) { - if (App::isEnabled('encryption') === false) { - return true; + $this->setPassphrase($params); + } + } + } + + /** + * Change a user's encryption passphrase + * + * @param array $params keys: uid, password + * @param IUserSession $user + * @param Util $util + * @return bool + */ + public function setPassphrase($params) { + + // Get existing decrypted private key + $privateKey = $this->session->getPrivateKey(); + + if ($params['uid'] === $this->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($this->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(); + + // 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 + $this->recovery->recoverUsersFiles($recoveryPassword); + } + } else { + $this->log->error('Encryption Could not update users encryption password'); } - $this->keyManager->setPassphrase($params, - $this->user, - $this->util); } } } + /** * after password reset we create a new key pair for the user * diff --git a/apps/encryption/lib/keymanager.php b/apps/encryption/lib/keymanager.php index 6c5f2348027..87b19fe35ea 100644 --- a/apps/encryption/lib/keymanager.php +++ b/apps/encryption/lib/keymanager.php @@ -23,7 +23,7 @@ namespace OCA\Encryption; use OC\Encryption\Exceptions\DecryptionFailedException; -use OC\Encryption\Exceptions\PrivateKeyMissingException; +use OCA\Encryption\Exceptions\PrivateKeyMissingException; use OC\Encryption\Exceptions\PublicKeyMissingException; use OCA\Encryption\Crypto\Crypt; use OCP\Encryption\Keys\IStorage; @@ -92,7 +92,6 @@ class KeyManager { * @param IUserSession $userSession * @param Session $session * @param ILogger $log - * @param Recovery $recovery */ public function __construct( IStorage $keyStorage, @@ -100,8 +99,7 @@ class KeyManager { IConfig $config, IUserSession $userSession, Session $session, - ILogger $log, - Recovery $recovery + ILogger $log ) { $this->session = $session; @@ -141,7 +139,6 @@ class KeyManager { $this->keyId = $userSession && $userSession->isLoggedIn() ? $userSession->getUser()->getUID() : false; $this->log = $log; - $this->recovery = $recovery; } /** @@ -329,74 +326,6 @@ class KeyManager { return $this->keyStorage->getFileKey($path, $keyId); } - /** - * Change a user's encryption passphrase - * - * @param array $params keys: uid, password - * @param IUserSession $user - * @param Util $util - * @return bool - */ - public function setPassphrase($params, IUserSession $user, Util $util) { - - // Get existing decrypted private key - $privateKey = $this->session->getPrivateKey(); - - 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(); - - // 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 - $this->recovery->recoverUsersFiles($recoveryPassword); - } - } else { - $this->log->error('Encryption Could not update users encryption password'); - } - } - } - } - /** * @param $userId * @return bool diff --git a/apps/encryption/lib/session.php b/apps/encryption/lib/session.php index e049a8fe403..8da11e522ce 100644 --- a/apps/encryption/lib/session.php +++ b/apps/encryption/lib/session.php @@ -100,4 +100,15 @@ class Session { $this->session->set('privateKey', $key); } + + /** + * remove keys from session + */ + public function clear() { + $this->session->remove('publicSharePrivateKey'); + $this->session->remove('privateKey'); + $this->session->remove('encryptionInitialized'); + + } + } \ No newline at end of file -- 2.39.5