Browse Source

use password change logic to userhooks to avoid recursions

remotes/origin/poc-doctrine-migrations
Bjoern Schiessle 11 years ago
committed by Thomas Müller
parent
commit
4843e5ce30
  1. 6
      apps/encryption/appinfo/application.php
  2. 86
      apps/encryption/hooks/userhooks.php
  3. 75
      apps/encryption/lib/keymanager.php
  4. 11
      apps/encryption/lib/session.php

6
apps/encryption/appinfo/application.php

@ -77,7 +77,8 @@ class Application extends \OCP\AppFramework\App {
$container->query('UserSetup'), $container->query('UserSetup'),
$server->getUserSession(), $server->getUserSession(),
$container->query('Util'), $container->query('Util'),
new \OCA\Encryption\Session($server->getSession())),
new \OCA\Encryption\Session($server->getSession()),
$container->query('Recovery'))
]); ]);
$hookManager->fireHooks(); $hookManager->fireHooks();
@ -126,8 +127,7 @@ class Application extends \OCP\AppFramework\App {
$server->getConfig(), $server->getConfig(),
$server->getUserSession(), $server->getUserSession(),
new \OCA\Encryption\Session($server->getSession()), new \OCA\Encryption\Session($server->getSession()),
$server->getLogger(),
$c->query('Recovery')
$server->getLogger()
); );
}); });

86
apps/encryption/hooks/userhooks.php

@ -31,6 +31,7 @@ use OCP\ILogger;
use OCP\IUserSession; use OCP\IUserSession;
use OCA\Encryption\Util; use OCA\Encryption\Util;
use OCA\Encryption\Session; use OCA\Encryption\Session;
use OCA\Encryption\Recovery;
class UserHooks implements IHook { class UserHooks implements IHook {
/** /**
@ -57,6 +58,10 @@ class UserHooks implements IHook {
* @var Session * @var Session
*/ */
private $session; private $session;
/**
* @var Recovery
*/
private $recovery;
/** /**
* UserHooks constructor. * UserHooks constructor.
@ -67,13 +72,15 @@ class UserHooks implements IHook {
* @param IUserSession $user * @param IUserSession $user
* @param Util $util * @param Util $util
* @param Session $session * @param Session $session
* @param Recovery $recovery
*/ */
public function __construct(KeyManager $keyManager, public function __construct(KeyManager $keyManager,
ILogger $logger, ILogger $logger,
Setup $userSetup, Setup $userSetup,
IUserSession $user, IUserSession $user,
Util $util, Util $util,
Session $session) {
Session $session,
Recovery $recovery) {
$this->keyManager = $keyManager; $this->keyManager = $keyManager;
$this->logger = $logger; $this->logger = $logger;
@ -81,6 +88,7 @@ class UserHooks implements IHook {
$this->user = $user; $this->user = $user;
$this->util = $util; $this->util = $util;
$this->session = $session; $this->session = $session;
$this->recovery = $recovery;
} }
/** /**
@ -141,7 +149,7 @@ class UserHooks implements IHook {
* remove keys from session during logout * remove keys from session during logout
*/ */
public function logout() { public function logout() {
KeyManager::$session->clear();
$this->session->clear();
} }
/** /**
@ -180,17 +188,81 @@ class UserHooks implements IHook {
if (App::isEnabled('encryption')) { if (App::isEnabled('encryption')) {
if (!$this->user->getUser()->canChangePassword()) { 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 * after password reset we create a new key pair for the user
* *

75
apps/encryption/lib/keymanager.php

@ -23,7 +23,7 @@ namespace OCA\Encryption;
use OC\Encryption\Exceptions\DecryptionFailedException; use OC\Encryption\Exceptions\DecryptionFailedException;
use OC\Encryption\Exceptions\PrivateKeyMissingException;
use OCA\Encryption\Exceptions\PrivateKeyMissingException;
use OC\Encryption\Exceptions\PublicKeyMissingException; use OC\Encryption\Exceptions\PublicKeyMissingException;
use OCA\Encryption\Crypto\Crypt; use OCA\Encryption\Crypto\Crypt;
use OCP\Encryption\Keys\IStorage; use OCP\Encryption\Keys\IStorage;
@ -92,7 +92,6 @@ class KeyManager {
* @param IUserSession $userSession * @param IUserSession $userSession
* @param Session $session * @param Session $session
* @param ILogger $log * @param ILogger $log
* @param Recovery $recovery
*/ */
public function __construct( public function __construct(
IStorage $keyStorage, IStorage $keyStorage,
@ -100,8 +99,7 @@ class KeyManager {
IConfig $config, IConfig $config,
IUserSession $userSession, IUserSession $userSession,
Session $session, Session $session,
ILogger $log,
Recovery $recovery
ILogger $log
) { ) {
$this->session = $session; $this->session = $session;
@ -141,7 +139,6 @@ class KeyManager {
$this->keyId = $userSession && $userSession->isLoggedIn() ? $userSession->getUser()->getUID() : false; $this->keyId = $userSession && $userSession->isLoggedIn() ? $userSession->getUser()->getUID() : false;
$this->log = $log; $this->log = $log;
$this->recovery = $recovery;
} }
/** /**
@ -329,74 +326,6 @@ class KeyManager {
return $this->keyStorage->getFileKey($path, $keyId); 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 * @param $userId
* @return bool * @return bool

11
apps/encryption/lib/session.php

@ -100,4 +100,15 @@ class Session {
$this->session->set('privateKey', $key); $this->session->set('privateKey', $key);
} }
/**
* remove keys from session
*/
public function clear() {
$this->session->remove('publicSharePrivateKey');
$this->session->remove('privateKey');
$this->session->remove('encryptionInitialized');
}
} }
Loading…
Cancel
Save