$server->getUserSession(), | $server->getUserSession(), | ||||
$container->query('Util'), | $container->query('Util'), | ||||
new \OCA\Encryption\Session($server->getSession()), | new \OCA\Encryption\Session($server->getSession()), | ||||
$container->query('Crypt'), | |||||
$container->query('Recovery')) | $container->query('Recovery')) | ||||
]); | ]); | ||||
} | } | ||||
} | } | ||||
/** | |||||
* @NoAdminRequired | |||||
*/ | |||||
public function userSetRecovery($userEnableRecovery) { | public function userSetRecovery($userEnableRecovery) { | ||||
if ($userEnableRecovery === '0' || $userEnableRecovery === '1') { | if ($userEnableRecovery === '0' || $userEnableRecovery === '1') { | ||||
use OCP\Util as OCUtil; | use OCP\Util as OCUtil; | ||||
use OCA\Encryption\Hooks\Contracts\IHook; | use OCA\Encryption\Hooks\Contracts\IHook; | ||||
use OCA\Encryption\KeyManager; | use OCA\Encryption\KeyManager; | ||||
use OCA\Encryption\Crypto\Crypt; | |||||
use OCA\Encryption\Users\Setup; | use OCA\Encryption\Users\Setup; | ||||
use OCP\App; | use OCP\App; | ||||
use OCP\ILogger; | use OCP\ILogger; | ||||
* @var Recovery | * @var Recovery | ||||
*/ | */ | ||||
private $recovery; | private $recovery; | ||||
/** | |||||
* @var Crypt | |||||
*/ | |||||
private $crypt; | |||||
/** | /** | ||||
* UserHooks constructor. | * UserHooks constructor. | ||||
* @param IUserSession $user | * @param IUserSession $user | ||||
* @param Util $util | * @param Util $util | ||||
* @param Session $session | * @param Session $session | ||||
* @param Crypt $crypt | |||||
* @param Recovery $recovery | * @param Recovery $recovery | ||||
*/ | */ | ||||
public function __construct(KeyManager $keyManager, | public function __construct(KeyManager $keyManager, | ||||
IUserSession $user, | IUserSession $user, | ||||
Util $util, | Util $util, | ||||
Session $session, | Session $session, | ||||
Crypt $crypt, | |||||
Recovery $recovery) { | Recovery $recovery) { | ||||
$this->keyManager = $keyManager; | $this->keyManager = $keyManager; | ||||
$this->util = $util; | $this->util = $util; | ||||
$this->session = $session; | $this->session = $session; | ||||
$this->recovery = $recovery; | $this->recovery = $recovery; | ||||
$this->crypt = $crypt; | |||||
} | } | ||||
/** | /** | ||||
// Save private key | // Save private key | ||||
if ($encryptedPrivateKey) { | if ($encryptedPrivateKey) { | ||||
$this->setPrivateKey($this->user->getUser()->getUID(), | |||||
$this->keyManager->setPrivateKey($this->user->getUser()->getUID(), | |||||
$encryptedPrivateKey); | $encryptedPrivateKey); | ||||
} else { | } else { | ||||
$this->log->error('Encryption could not update users encryption password'); | $this->log->error('Encryption could not update users encryption password'); | ||||
// ...we have a recovery password and the user enabled the recovery key | // ...we have a recovery password and the user enabled the recovery key | ||||
// ...encryption was activated for the first time (no keys exists) | // ...encryption was activated for the first time (no keys exists) | ||||
// ...the user doesn't have any files | // ...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 | // backup old keys | ||||
$this->backupAllKeys('recovery'); | |||||
//$this->backupAllKeys('recovery'); | |||||
$newUserPassword = $params['password']; | $newUserPassword = $params['password']; | ||||
$keyPair = $this->crypt->createKeyPair(); | $keyPair = $this->crypt->createKeyPair(); | ||||
// Save public key | // Save public key | ||||
$this->setPublicKey($user, $keyPair['publicKey']); | |||||
$this->keyManager->setPublicKey($user, $keyPair['publicKey']); | |||||
// Encrypt private key with new password | // Encrypt private key with new password | ||||
$encryptedKey = $this->crypt->symmetricEncryptFileContent($keyPair['privateKey'], | $encryptedKey = $this->crypt->symmetricEncryptFileContent($keyPair['privateKey'], | ||||
$newUserPassword); | $newUserPassword); | ||||
if ($encryptedKey) { | 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 | if ($recoveryPassword) { // if recovery key is set we can re-encrypt the key files | ||||
$this->recovery->recoverUsersFiles($recoveryPassword); | |||||
$this->recovery->recoverUsersFiles($recoveryPassword, $user); | |||||
} | } | ||||
} else { | } else { | ||||
$this->log->error('Encryption Could not update users encryption password'); | $this->log->error('Encryption Could not update users encryption password'); |
if ($encryptedKey) { | if ($encryptedKey) { | ||||
$this->setPrivateKey($uid, $encryptedKey); | $this->setPrivateKey($uid, $encryptedKey); | ||||
$this->config->setAppValue('encryption', 'recoveryAdminEnabled', 0); | |||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
throw new FileKeyMissingException(); | 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 | * delete share key | ||||
* | * |
} | } | ||||
/** | /** | ||||
* check if recovery is enabled for user | |||||
* | |||||
* @param string $user if no user is given we check the current logged-in user | |||||
* | |||||
* @return bool | * @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', | 'encryption', | ||||
'recoveryEnabled', | 'recoveryEnabled', | ||||
0); | 0); | ||||
return ($recoveryMode === '1'); | 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 | * @param string $value | ||||
* @return bool | * @return bool | ||||
} | } | ||||
/** | /** | ||||
* @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, | $privateKey = $this->crypt->decryptPrivateKey($encryptedKey, | ||||
$recoveryPassword); | $recoveryPassword); | ||||
$this->recoverAllFiles('/', $privateKey); | |||||
$this->recoverAllFiles('/' . $user . '/files/', $privateKey); | |||||
} | } | ||||
/** | /** | ||||
* @param $privateKey | * @param $privateKey | ||||
*/ | */ | ||||
private function recoverAllFiles($path, $privateKey) { | private function recoverAllFiles($path, $privateKey) { | ||||
$dirContent = $this->files->getDirectoryContent($path); | |||||
$dirContent = $this->view->getDirectoryContent($path); | |||||
foreach ($dirContent as $item) { | foreach ($dirContent as $item) { | ||||
// Get relative path from encryption/keyfiles | // 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); | $this->recoverAllFiles($filePath . '/', $privateKey); | ||||
} else { | } else { | ||||
$this->recoverFile($filePath, $privateKey); | $this->recoverFile($filePath, $privateKey); | ||||
} | } | ||||
/** | /** | ||||
* @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']); | |||||
} | } | ||||
exit(); | exit(); | ||||
} | } | ||||
if (\OC_App::isEnabled('files_encryption')) { | |||||
if (\OC_App::isEnabled('encryption')) { | |||||
//handle the recovery case | //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; | $validRecoveryPassword = false; | ||||
$recoveryEnabledForUser = false; | $recoveryEnabledForUser = false; | ||||
if ($recoveryAdminEnabled) { | if ($recoveryAdminEnabled) { | ||||
$validRecoveryPassword = $util->checkRecoveryPassword($recoveryPassword); | |||||
$recoveryEnabledForUser = $util->recoveryEnabledForUser(); | |||||
$validRecoveryPassword = $keyManager->checkRecoveryPassword($recoveryPassword); | |||||
$recoveryEnabledForUser = $recovery->isRecoveryEnabledForUser(); | |||||
} | } | ||||
if ($recoveryEnabledForUser && $recoveryPassword === '') { | if ($recoveryEnabledForUser && $recoveryPassword === '') { |
$groupsInfo->setSorting($groupsInfo::SORT_USERCOUNT); | $groupsInfo->setSorting($groupsInfo::SORT_USERCOUNT); | ||||
list($adminGroup, $groups) = $groupsInfo->get(); | 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) { | if($isAdmin) { | ||||
$subadmins = OC_SubAdmin::getAllSubAdmins(); | $subadmins = OC_SubAdmin::getAllSubAdmins(); |