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