parent
63e7fe608a
commit
39733c8da1
@ -0,0 +1,33 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/19/15, 9:52 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
use OCA\Encryption\AppInfo\Encryption; |
||||
|
||||
if (!OC::$CLI) { |
||||
$di = \OC::$server; |
||||
$app = new Encryption('encryption', |
||||
[], |
||||
$di->getEncryptionManager(), |
||||
$di->getConfig()); |
||||
|
||||
$app->boot(); |
||||
} |
||||
|
||||
@ -0,0 +1,182 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 3/11/15, 11:03 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
namespace OCA\Encryption\AppInfo; |
||||
|
||||
|
||||
use OCA\Encryption\Crypto\Crypt; |
||||
use OCA\Encryption\HookManager; |
||||
use OCA\Encryption\Hooks\AppHooks; |
||||
use OCA\Encryption\Hooks\FileSystemHooks; |
||||
use OCA\Encryption\Hooks\ShareHooks; |
||||
use OCA\Encryption\Hooks\UserHooks; |
||||
use OCA\Encryption\KeyManager; |
||||
use OCA\Encryption\Migrator; |
||||
use OCA\Encryption\Recovery; |
||||
use OCA\Encryption\Users\Setup; |
||||
use OCP\App; |
||||
use OCP\AppFramework\IAppContainer; |
||||
use OCP\Encryption\IManager; |
||||
use OCP\IConfig; |
||||
|
||||
|
||||
class Encryption extends \OCP\AppFramework\App { |
||||
/** |
||||
* @var IManager |
||||
*/ |
||||
private $encryptionManager; |
||||
/** |
||||
* @var IConfig |
||||
*/ |
||||
private $config; |
||||
|
||||
/** |
||||
* @param $appName |
||||
* @param array $urlParams |
||||
* @param IManager $encryptionManager |
||||
* @param IConfig $config |
||||
*/ |
||||
public function __construct($appName, $urlParams = array(), IManager $encryptionManager, IConfig $config) { |
||||
parent::__construct($appName, $urlParams); |
||||
$this->encryptionManager = $encryptionManager; |
||||
$this->config = $config; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function boot() { |
||||
$this->registerServices(); |
||||
$this->registerHooks(); |
||||
$this->registerEncryptionModule(); |
||||
$this->registerSettings(); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function registerHooks() { |
||||
if (!$this->config->getSystemValue('maintenance', false)) { |
||||
|
||||
$container = $this->getContainer(); |
||||
$server = $container->getServer(); |
||||
// Register our hooks and fire them. |
||||
$hookManager = new HookManager(); |
||||
|
||||
$hookManager->registerHook([ |
||||
new UserHooks($container->query('KeyManager'), |
||||
$server->getLogger(), |
||||
$container->query('UserSetup'), |
||||
$container->query('Migrator'), |
||||
$server->getUserSession()), |
||||
// new ShareHooks(), |
||||
// new FileSystemHooks(), |
||||
// new AppHooks() |
||||
]); |
||||
|
||||
$hookManager->fireHooks(); |
||||
|
||||
} else { |
||||
// Logout user if we are in maintenance to force re-login |
||||
$this->getContainer()->getServer()->getUserSession()->logout(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function registerEncryptionModule() { |
||||
// $this->encryptionManager->registerEncryptionModule(new \OCA\Encryption\Crypto\Encryption()); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function registerServices() { |
||||
$container = $this->getContainer(); |
||||
|
||||
$container->registerService('Crypt', |
||||
function (IAppContainer $c) { |
||||
$server = $c->getServer(); |
||||
return new Crypt($server->getLogger(), |
||||
$server->getUserSession(), |
||||
$server->getConfig()); |
||||
}); |
||||
|
||||
$container->registerService('KeyManager', |
||||
function (IAppContainer $c) { |
||||
$server = $c->getServer(); |
||||
|
||||
return new KeyManager($server->getEncryptionKeyStorage(), |
||||
$c->query('Crypt'), |
||||
$server->getConfig(), |
||||
$server->getUserSession()); |
||||
}); |
||||
|
||||
|
||||
$container->registerService('Recovery', |
||||
function (IAppContainer $c) { |
||||
$server = $c->getServer(); |
||||
|
||||
return new Recovery( |
||||
$server->getUserSession(), |
||||
$c->query('Crypt'), |
||||
$server->getSecureRandom(), |
||||
$c->query('KeyManager'), |
||||
$server->getConfig(), |
||||
$server->getEncryptionKeyStorage()); |
||||
}); |
||||
|
||||
$container->registerService('UserSetup', |
||||
function (IAppContainer $c) { |
||||
$server = $c->getServer(); |
||||
return new Setup($server->getLogger(), |
||||
$server->getUserSession(), |
||||
$c->query('Crypt'), |
||||
$c->query('KeyManager')); |
||||
}); |
||||
|
||||
$container->registerService('Migrator', |
||||
function (IAppContainer $c) { |
||||
$server = $c->getServer(); |
||||
|
||||
return new Migrator($server->getUserSession(), |
||||
$server->getConfig(), |
||||
$server->getUserManager(), |
||||
$server->getLogger(), |
||||
$c->query('Crypt')); |
||||
}); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function registerSettings() { |
||||
|
||||
// script('encryption', 'encryption'); |
||||
// script('encryption', 'detect-migration'); |
||||
|
||||
|
||||
// Register settings scripts |
||||
App::registerAdmin('encryption', 'settings/settings-admin'); |
||||
App::registerPersonal('encryption', 'settings/settings-personal'); |
||||
} |
||||
} |
||||
@ -0,0 +1,36 @@ |
||||
<?xml version="1.0"?> |
||||
<info> |
||||
<id>encryption</id> |
||||
<description> |
||||
This application encrypts all files accessed by ownCloud at rest, |
||||
wherever they are stored. As an example, with this application |
||||
enabled, external cloud based Amazon S3 storage will be encrypted, |
||||
protecting this data on storage outside of the control of the Admin. |
||||
When this application is enabled for the first time, all files are |
||||
encrypted as users log in and are prompted for their password. The |
||||
recommended recovery key option enables recovery of files in case |
||||
the key is lost. |
||||
Note that this app encrypts all files that are touched by ownCloud, |
||||
so external storage providers and applications such as SharePoint |
||||
will see new files encrypted when they are accessed. Encryption is |
||||
based on AES 128 or 256 bit keys. More information is available in |
||||
the Encryption documentation |
||||
</description> |
||||
<name>Encryption</name> |
||||
<license>AGPL</license> |
||||
<author>Bjoern Schiessle, Clark Tomlinson</author> |
||||
<requiremin>8</requiremin> |
||||
<shipped>true</shipped> |
||||
<documentation> |
||||
<user>user-encryption</user> |
||||
<admin>admin-encryption</admin> |
||||
</documentation> |
||||
<rememberlogin>false</rememberlogin> |
||||
<types> |
||||
<filesystem/> |
||||
</types> |
||||
<dependencies> |
||||
<lib>openssl</lib> |
||||
</dependencies> |
||||
|
||||
</info> |
||||
@ -0,0 +1,39 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/19/15, 11:22 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
|
||||
use OCP\AppFramework\App; |
||||
|
||||
(new App('encryption'))->registerRoutes($this, array('routes' => array( |
||||
|
||||
[ |
||||
'name' => 'recovery#adminRecovery', |
||||
'url' => '/ajax/adminRecovery', |
||||
'verb' => 'POST' |
||||
], |
||||
[ |
||||
'name' => 'recovery#userRecovery', |
||||
'url' => '/ajax/userRecovery', |
||||
'verb' => 'POST' |
||||
] |
||||
|
||||
|
||||
))); |
||||
@ -0,0 +1,106 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/19/15, 11:25 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption\Controller; |
||||
|
||||
|
||||
use OCA\Encryption\Recovery; |
||||
use OCP\AppFramework\Controller; |
||||
use OCP\IConfig; |
||||
use OCP\IL10N; |
||||
use OCP\IRequest; |
||||
use OCP\JSON; |
||||
use Symfony\Component\HttpFoundation\JsonResponse; |
||||
|
||||
class RecoveryController extends Controller { |
||||
/** |
||||
* @var IConfig |
||||
*/ |
||||
private $config; |
||||
/** |
||||
* @var IL10N |
||||
*/ |
||||
private $l; |
||||
/** |
||||
* @var Recovery |
||||
*/ |
||||
private $recovery; |
||||
|
||||
/** |
||||
* @param string $AppName |
||||
* @param IRequest $request |
||||
* @param IConfig $config |
||||
* @param IL10N $l10n |
||||
* @param Recovery $recovery |
||||
*/ |
||||
public function __construct($AppName, IRequest $request, IConfig $config, IL10N $l10n, Recovery $recovery) { |
||||
parent::__construct($AppName, $request); |
||||
$this->config = $config; |
||||
$this->l = $l10n; |
||||
$this->recovery = $recovery; |
||||
} |
||||
|
||||
public function adminRecovery($recoveryPassword, $confirmPassword, $adminEnableRecovery) { |
||||
// Check if both passwords are the same |
||||
if (empty($recoveryPassword)) { |
||||
$errorMessage = $this->l->t('Missing recovery key password'); |
||||
return new JsonResponse(['data' => ['message' => $errorMessage]], 500); |
||||
} |
||||
|
||||
if (empty($confirmPassword)) { |
||||
$errorMessage = $this->l->t('Please repeat the recovery key password'); |
||||
return new JsonResponse(['data' => ['message' => $errorMessage]], 500); |
||||
} |
||||
|
||||
if ($recoveryPassword !== $confirmPassword) { |
||||
$errorMessage = $this->l->t('Repeated recovery key password does not match the provided recovery key password'); |
||||
return new JsonResponse(['data' => ['message' => $errorMessage]], 500); |
||||
} |
||||
|
||||
// Enable recoveryAdmin |
||||
$recoveryKeyId = $this->config->getAppValue('encryption', 'recoveryKeyId'); |
||||
|
||||
if (isset($adminEnableRecovery) && $adminEnableRecovery === '1') { |
||||
if ($this->recovery->enableAdminRecovery($recoveryKeyId, $recoveryPassword)) { |
||||
return new JsonResponse(['data' => array('message' => $this->l->t('Recovery key successfully enabled'))]); |
||||
} |
||||
return new JsonResponse(['data' => array('message' => $this->l->t('Could not enable recovery key. Please check your recovery key password!'))]); |
||||
} elseif (isset($adminEnableRecovery) && $adminEnableRecovery === '0') { |
||||
if ($this->recovery->disableAdminRecovery($recoveryKeyId, $recoveryPassword)) { |
||||
return new JsonResponse(['data' => array('message' => $this->l->t('Recovery key successfully disabled'))]); |
||||
} |
||||
return new JsonResponse(['data' => array('message' => $this->l->t('Could not disable recovery key. Please check your recovery key password!'))]); |
||||
} |
||||
} |
||||
|
||||
public function userRecovery($userEnableRecovery) { |
||||
if (isset($userEnableRecovery) && ($userEnableRecovery === '0' || $userEnableRecovery === '1')) { |
||||
$userId = $this->user->getUID(); |
||||
if ($userEnableRecovery === '1') { |
||||
// Todo xxx figure out if we need keyid's here or what. |
||||
return $this->recovery->addRecoveryKeys(); |
||||
} |
||||
// Todo xxx see :98 |
||||
return $this->recovery->removeRecoveryKeys(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,37 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/19/15, 10:02 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption\Hooks; |
||||
|
||||
use OCA\Encryption\Hooks\Contracts\IHook; |
||||
use OCP\Util; |
||||
|
||||
class AppHooks implements IHook { |
||||
/** |
||||
* Connects Hooks |
||||
* |
||||
* @return null |
||||
*/ |
||||
public function addHooks() { |
||||
Util::connectHook('OC_App', 'pre_disable', 'OCA\Encryption\Hooks', 'preDisable'); |
||||
Util::connectHook('OC_App', 'post_disable', 'OCA\Encryption\Hooks', 'postEnable'); |
||||
} |
||||
} |
||||
@ -0,0 +1,32 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/19/15, 10:03 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption\Hooks\Contracts; |
||||
|
||||
|
||||
interface IHook { |
||||
/** |
||||
* Connects Hooks |
||||
* |
||||
* @return null |
||||
*/ |
||||
public function addHooks(); |
||||
} |
||||
@ -0,0 +1,46 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/19/15, 10:02 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption\Hooks; |
||||
|
||||
|
||||
use OCA\Encryption\Hooks\Contracts\IHook; |
||||
use OCP\Util; |
||||
|
||||
class FileSystemHooks implements IHook { |
||||
|
||||
/** |
||||
* Connects Hooks |
||||
* |
||||
* @return null |
||||
*/ |
||||
public function addHooks() { |
||||
Util::connectHook('OC_Filesystem', 'rename', 'OCA\Encryption\Hooks', 'preRename'); |
||||
Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Encryption\Hooks', 'postRenameOrCopy'); |
||||
Util::connectHook('OC_Filesystem', 'copy', 'OCA\Encryption\Hooks', 'preCopy'); |
||||
Util::connectHook('OC_Filesystem', 'post_copy', 'OCA\Encryption\Hooks', 'postRenameOrCopy'); |
||||
Util::connectHook('OC_Filesystem', 'post_delete', 'OCA\Encryption\Hooks', 'postDelete'); |
||||
Util::connectHook('OC_Filesystem', 'delete', 'OCA\Encryption\Hooks', 'preDelete'); |
||||
Util::connectHook('\OC\Core\LostPassword\Controller\LostController', 'post_passwordReset', 'OCA\Encryption\Hooks', 'postPasswordReset'); |
||||
Util::connectHook('OC_Filesystem', 'post_umount', 'OCA\Encryption\Hooks', 'postUnmount'); |
||||
Util::connectHook('OC_Filesystem', 'umount', 'OCA\Encryption\Hooks', 'preUnmount'); |
||||
} |
||||
} |
||||
@ -0,0 +1,40 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/19/15, 10:02 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption\Hooks; |
||||
|
||||
|
||||
use OCA\Encryption\Hooks\Contracts\IHook; |
||||
use OCP\Util; |
||||
|
||||
class ShareHooks implements IHook { |
||||
|
||||
/** |
||||
* Connects Hooks |
||||
* |
||||
* @return null |
||||
*/ |
||||
public function addHooks() { |
||||
Util::connectHook('OCP\Share', 'pre_shared', 'OCA\Encryption\Hooks', 'preShared'); |
||||
Util::connectHook('OCP\Share', 'post_shared', 'OCA\Encryption\Hooks', 'postShared'); |
||||
Util::connectHook('OCP\Share', 'post_unshare', 'OCA\Encryption\Hooks', 'postUnshare'); |
||||
} |
||||
} |
||||
@ -0,0 +1,304 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/19/15, 10:02 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption\Hooks; |
||||
|
||||
|
||||
use OCA\Encryption\Hooks\Contracts\IHook; |
||||
use OCA\Encryption\KeyManager; |
||||
use OCA\Encryption\Migrator; |
||||
use OCA\Encryption\RequirementsChecker; |
||||
use OCA\Encryption\Users\Setup; |
||||
use OCP\App; |
||||
use OCP\ILogger; |
||||
use OCP\IUserSession; |
||||
use OCP\Util; |
||||
use Test\User; |
||||
|
||||
class UserHooks implements IHook { |
||||
/** |
||||
* @var KeyManager |
||||
*/ |
||||
private $keyManager; |
||||
/** |
||||
* @var ILogger |
||||
*/ |
||||
private $logger; |
||||
/** |
||||
* @var Setup |
||||
*/ |
||||
private $userSetup; |
||||
/** |
||||
* @var Migrator |
||||
*/ |
||||
private $migrator; |
||||
/** |
||||
* @var IUserSession |
||||
*/ |
||||
private $user; |
||||
|
||||
/** |
||||
* UserHooks constructor. |
||||
* |
||||
* @param KeyManager $keyManager |
||||
* @param ILogger $logger |
||||
* @param Setup $userSetup |
||||
* @param Migrator $migrator |
||||
* @param IUserSession $user |
||||
*/ |
||||
public function __construct( |
||||
KeyManager $keyManager, ILogger $logger, Setup $userSetup, Migrator $migrator, IUserSession $user) { |
||||
|
||||
$this->keyManager = $keyManager; |
||||
$this->logger = $logger; |
||||
$this->userSetup = $userSetup; |
||||
$this->migrator = $migrator; |
||||
$this->user = $user; |
||||
} |
||||
|
||||
/** |
||||
* Connects Hooks |
||||
* |
||||
* @return null |
||||
*/ |
||||
public function addHooks() { |
||||
Util::connectHook('OC_User', 'post_login', $this, 'login'); |
||||
Util::connectHook('OC_User', 'logout', $this, 'logout'); |
||||
Util::connectHook('OC_User', 'post_setPassword', $this, 'setPassphrase'); |
||||
Util::connectHook('OC_User', 'pre_setPassword', $this, 'preSetPassphrase'); |
||||
Util::connectHook('OC_User', 'post_createUser', $this, 'postCreateUser'); |
||||
Util::connectHook('OC_User', 'post_deleteUser', $this, 'postDeleteUser'); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Startup encryption backend upon user login |
||||
* |
||||
* @note This method should never be called for users using client side encryption |
||||
*/ |
||||
public function login($params) { |
||||
|
||||
if (!App::isEnabled('encryption')) { |
||||
return true; |
||||
} |
||||
|
||||
// ensure filesystem is loaded |
||||
// Todo: update? |
||||
if (!\OC\Files\Filesystem::$loaded) { |
||||
\OC_Util::setupFS($params['uid']); |
||||
} |
||||
|
||||
// setup user, if user not ready force relogin |
||||
if (!$this->userSetup->setupUser($params['password'])) { |
||||
return false; |
||||
} |
||||
|
||||
$cache = $this->keyManager->init(); |
||||
|
||||
// Check if first-run file migration has already been performed |
||||
$ready = false; |
||||
$migrationStatus = $this->migrator->getStatus($params['uid']); |
||||
if ($migrationStatus === Migrator::$migrationOpen && $cache !== false) { |
||||
$ready = $this->migrator->beginMigration(); |
||||
} elseif ($migrationStatus === Migrator::$migrationInProgress) { |
||||
// refuse login as long as the initial encryption is running |
||||
sleep(5); |
||||
$this->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 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 function postCreateUser($params) { |
||||
|
||||
if (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 function postDeleteUser($params) { |
||||
|
||||
if (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 function preSetPassphrase($params) { |
||||
if (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 function setPassphrase($params) { |
||||
if (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 function postPasswordReset($params) { |
||||
$uid = $params['uid']; |
||||
$password = $params['password']; |
||||
|
||||
$util = new Util(new \OC\Files\View(), $uid); |
||||
$util->replaceUserKeys($password); |
||||
} |
||||
} |
||||
@ -0,0 +1,116 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <fallen013@gmail.com> |
||||
* @since 3/6/15, 2:28 PM |
||||
* @link http:/www.clarkt.com |
||||
* @copyright Clark Tomlinson © 2015 |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption\Crypto; |
||||
|
||||
|
||||
use OCP\Encryption\IEncryptionModule; |
||||
|
||||
class Encryption extends Crypt implements IEncryptionModule { |
||||
|
||||
/** |
||||
* @return string defining the technical unique id |
||||
*/ |
||||
public function getId() { |
||||
// TODO: Implement getId() method. |
||||
} |
||||
|
||||
/** |
||||
* In comparison to getKey() this function returns a human readable (maybe translated) name |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function getDisplayName() { |
||||
// TODO: Implement getDisplayName() method. |
||||
} |
||||
|
||||
/** |
||||
* start receiving chunks from a file. This is the place where you can |
||||
* perform some initial step before starting encrypting/decrypting the |
||||
* chunks |
||||
* |
||||
* @param string $path to the file |
||||
* @param array $header contains the header data read from the file |
||||
* @param array $accessList who has access to the file contains the key 'users' and 'public' |
||||
* |
||||
* $return array $header contain data as key-value pairs which should be |
||||
* written to the header, in case of a write operation |
||||
* or if no additional data is needed return a empty array |
||||
*/ |
||||
public function begin($path, $header, $accessList) { |
||||
// TODO: Implement begin() method. |
||||
} |
||||
|
||||
/** |
||||
* last chunk received. This is the place where you can perform some final |
||||
* operation and return some remaining data if something is left in your |
||||
* buffer. |
||||
* |
||||
* @param string $path to the file |
||||
* @return string remained data which should be written to the file in case |
||||
* of a write operation |
||||
*/ |
||||
public function end($path) { |
||||
// TODO: Implement end() method. |
||||
} |
||||
|
||||
/** |
||||
* encrypt data |
||||
* |
||||
* @param string $data you want to encrypt |
||||
* @return mixed encrypted data |
||||
*/ |
||||
public function encrypt($data) { |
||||
// Todo: xxx Update Signature and usages |
||||
$this->symmetricEncryptFileContent($data); |
||||
} |
||||
|
||||
/** |
||||
* decrypt data |
||||
* |
||||
* @param string $data you want to decrypt |
||||
* @param string $user decrypt as user (null for public access) |
||||
* @return mixed decrypted data |
||||
*/ |
||||
public function decrypt($data, $user) { |
||||
// Todo: xxx Update Usages? |
||||
$this->symmetricDecryptFileContent($data, $user); |
||||
} |
||||
|
||||
/** |
||||
* update encrypted file, e.g. give additional users access to the file |
||||
* |
||||
* @param string $path path to the file which should be updated |
||||
* @param array $accessList who has access to the file contains the key 'users' and 'public' |
||||
* @return boolean |
||||
*/ |
||||
public function update($path, $accessList) { |
||||
// TODO: Implement update() method. |
||||
} |
||||
|
||||
/** |
||||
* should the file be encrypted or not |
||||
* |
||||
* @param string $path |
||||
* @return boolean |
||||
*/ |
||||
public function shouldEncrypt($path) { |
||||
// TODO: Implement shouldEncrypt() method. |
||||
} |
||||
|
||||
/** |
||||
* calculate unencrypted size |
||||
* |
||||
* @param string $path to file |
||||
* @return integer unencrypted size |
||||
*/ |
||||
public function calculateUnencryptedSize($path) { |
||||
// TODO: Implement calculateUnencryptedSize() method. |
||||
} |
||||
} |
||||
@ -0,0 +1,355 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/19/15, 1:42 PM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption\Crypto; |
||||
|
||||
|
||||
use OC\Encryption\Exceptions\DecryptionFailedException; |
||||
use OC\Encryption\Exceptions\EncryptionFailedException; |
||||
use OC\Encryption\Exceptions\GenericEncryptionException; |
||||
use OCP\IConfig; |
||||
use OCP\ILogger; |
||||
use OCP\IUser; |
||||
use OCP\IUserSession; |
||||
|
||||
class Crypt { |
||||
|
||||
const ENCRYPTION_UKNOWN_ERROR = -1; |
||||
const ENCRYPTION_NOT_INIALIZED_ERROR = 1; |
||||
const ENCRYPTIION_PRIVATE_KEY_NOT_VALID_ERROR = 2; |
||||
const ENCRYPTION_NO_SHARE_KEY_FOUND = 3; |
||||
|
||||
const BLOCKSIZE = 8192; |
||||
const DEFAULT_CIPHER = 'AES-256-CFB'; |
||||
|
||||
const HEADERSTART = 'HBEGIN'; |
||||
const HEADEREND = 'HEND'; |
||||
/** |
||||
* @var ILogger |
||||
*/ |
||||
private $logger; |
||||
/** |
||||
* @var IUser |
||||
*/ |
||||
private $user; |
||||
/** |
||||
* @var IConfig |
||||
*/ |
||||
private $config; |
||||
|
||||
/** |
||||
* @param ILogger $logger |
||||
* @param IUserSession $userSession |
||||
* @param IConfig $config |
||||
*/ |
||||
public function __construct(ILogger $logger, IUserSession $userSession, IConfig $config) { |
||||
$this->logger = $logger; |
||||
$this->user = $userSession && $userSession->isLoggedIn() ? $userSession->getUser() : false; |
||||
$this->config = $config; |
||||
} |
||||
|
||||
/** |
||||
* @param null $user |
||||
* @return string |
||||
*/ |
||||
public function mode($user = null) { |
||||
return 'server'; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function createKeyPair() { |
||||
|
||||
$log = $this->logger; |
||||
$res = $this->getOpenSSLPKey(); |
||||
|
||||
if (!$res) { |
||||
$log->error("Encryption Library could'nt generate users key-pair for {$this->user->getUID()}", ['app' => 'encryption']); |
||||
|
||||
if (openssl_error_string()) { |
||||
$log->error('Encryption library openssl_pkey_new() fails: ' . openssl_error_string(), ['app' => 'encryption']); |
||||
} |
||||
} elseif (openssl_pkey_export($res, $privateKey, null, $this->getOpenSSLConfig())) { |
||||
$keyDetails = openssl_pkey_get_details($res); |
||||
$publicKey = $keyDetails['key']; |
||||
|
||||
return [ |
||||
'publicKey' => $publicKey, |
||||
'privateKey' => $privateKey |
||||
]; |
||||
} |
||||
$log->error('Encryption library couldn\'t export users private key, please check your servers openSSL configuration.' . $user->getUID(), ['app' => 'encryption']); |
||||
if (openssl_error_string()) { |
||||
$log->error('Encryption Library:' . openssl_error_string(), ['app' => 'encryption']); |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @return resource |
||||
*/ |
||||
public function getOpenSSLPKey() { |
||||
$config = $this->getOpenSSLConfig(); |
||||
return openssl_pkey_new($config); |
||||
} |
||||
|
||||
/** |
||||
* @return array |
||||
*/ |
||||
private function getOpenSSLConfig() { |
||||
$config = ['private_key_bits' => 4096]; |
||||
$config = array_merge(\OC::$server->getConfig()->getSystemValue('openssl', []), $config); |
||||
return $config; |
||||
} |
||||
|
||||
/** |
||||
* @param $plainContent |
||||
* @param $passphrase |
||||
* @return bool|string |
||||
* @throws GenericEncryptionException |
||||
*/ |
||||
public function symmetricEncryptFileContent($plainContent, $passphrase) { |
||||
|
||||
if (!$plainContent) { |
||||
$this->logger->error('Encryption Library, symmetrical encryption failed no content given', ['app' => 'encryption']); |
||||
return false; |
||||
} |
||||
|
||||
$iv = $this->generateIv(); |
||||
|
||||
try { |
||||
$encryptedContent = $this->encrypt($plainContent, $iv, $passphrase, $this->getCipher()); |
||||
// combine content to encrypt the IV identifier and actual IV |
||||
$catFile = $this->concatIV($encryptedContent, $iv); |
||||
$padded = $this->addPadding($catFile); |
||||
|
||||
return $padded; |
||||
} catch (EncryptionFailedException $e) { |
||||
$message = 'Could not encrypt file content (code: ' . $e->getCode() . '): '; |
||||
$this->logger->error('files_encryption' . $message . $e->getMessage(), ['app' => 'encryption']); |
||||
return false; |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* @param $plainContent |
||||
* @param $iv |
||||
* @param string $passphrase |
||||
* @param string $cipher |
||||
* @return string |
||||
* @throws EncryptionFailedException |
||||
*/ |
||||
private function encrypt($plainContent, $iv, $passphrase = '', $cipher = self::DEFAULT_CIPHER) { |
||||
$encryptedContent = openssl_encrypt($plainContent, $cipher, $passphrase, false, $iv); |
||||
|
||||
if (!$encryptedContent) { |
||||
$error = 'Encryption (symmetric) of content failed'; |
||||
$this->logger->error($error . openssl_error_string(), ['app' => 'encryption']); |
||||
throw new EncryptionFailedException($error); |
||||
} |
||||
|
||||
return $encryptedContent; |
||||
} |
||||
|
||||
/** |
||||
* @return mixed|string |
||||
*/ |
||||
public function getCipher() { |
||||
$cipher = $this->config->getSystemValue('cipher', self::DEFAULT_CIPHER); |
||||
if ($cipher !== 'AES-256-CFB' || $cipher !== 'AES-128-CFB') { |
||||
$this->logger->warning('Wrong cipher defined in config.php only AES-128-CFB and AES-256-CFB are supported. Fall back' . self::DEFAULT_CIPHER, ['app' => 'encryption']); |
||||
$cipher = self::DEFAULT_CIPHER; |
||||
} |
||||
|
||||
return $cipher; |
||||
} |
||||
|
||||
/** |
||||
* @param $encryptedContent |
||||
* @param $iv |
||||
* @return string |
||||
*/ |
||||
private function concatIV($encryptedContent, $iv) { |
||||
return $encryptedContent . '00iv00' . $iv; |
||||
} |
||||
|
||||
/** |
||||
* @param $data |
||||
* @return string |
||||
*/ |
||||
private function addPadding($data) { |
||||
return $data . 'xx'; |
||||
} |
||||
|
||||
/** |
||||
* @param $recoveryKey |
||||
* @param $password |
||||
* @return bool|string |
||||
*/ |
||||
public function decryptPrivateKey($recoveryKey, $password) { |
||||
|
||||
$header = $this->parseHeader($recoveryKey); |
||||
$cipher = $this->getCipher($header); |
||||
|
||||
// If we found a header we need to remove it from the key we want to decrypt |
||||
if (!empty($header)) { |
||||
$recoveryKey = substr($recoveryKey, strpos($recoveryKey, self::HEADEREND) + strlen(self::HEADERSTART)); |
||||
} |
||||
|
||||
$plainKey = $this->symmetricDecryptFileContent($recoveryKey, $password, $cipher); |
||||
|
||||
// Check if this is a valid private key |
||||
$res = openssl_get_privatekey($plainKey); |
||||
if (is_resource($res)) { |
||||
$sslInfo = openssl_pkey_get_details($res); |
||||
if (!isset($sslInfo['key'])) { |
||||
return false; |
||||
} |
||||
} else { |
||||
return false; |
||||
} |
||||
|
||||
return $plainKey; |
||||
} |
||||
|
||||
/** |
||||
* @param $keyFileContents |
||||
* @param string $passphrase |
||||
* @param string $cipher |
||||
* @return bool|string |
||||
* @throws DecryptionFailedException |
||||
*/ |
||||
public function symmetricDecryptFileContent($keyFileContents, $passphrase = '', $cipher = self::DEFAULT_CIPHER) { |
||||
// Remove Padding |
||||
$noPadding = $this->removePadding($keyFileContents); |
||||
|
||||
$catFile = $this->splitIv($noPadding); |
||||
|
||||
$plainContent = $this->decrypt($catFile['encrypted'], $catFile['iv'], $passphrase, $cipher); |
||||
|
||||
if ($plainContent) { |
||||
return $plainContent; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @param $padded |
||||
* @return bool|string |
||||
*/ |
||||
private function removePadding($padded) { |
||||
if (substr($padded, -2) === 'xx') { |
||||
return substr($padded, 0, -2); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @param $catFile |
||||
* @return array |
||||
*/ |
||||
private function splitIv($catFile) { |
||||
// Fetch encryption metadata from end of file |
||||
$meta = substr($catFile, -22); |
||||
|
||||
// Fetch IV from end of file |
||||
$iv = substr($meta, -16); |
||||
|
||||
// Remove IV and IV Identifier text to expose encrypted content |
||||
|
||||
$encrypted = substr($catFile, 0, -22); |
||||
|
||||
return [ |
||||
'encrypted' => $encrypted, |
||||
'iv' => $iv |
||||
]; |
||||
} |
||||
|
||||
/** |
||||
* @param $encryptedContent |
||||
* @param $iv |
||||
* @param string $passphrase |
||||
* @param string $cipher |
||||
* @return string |
||||
* @throws DecryptionFailedException |
||||
*/ |
||||
private function decrypt($encryptedContent, $iv, $passphrase = '', $cipher = self::DEFAULT_CIPHER) { |
||||
$plainContent = openssl_decrypt($encryptedContent, $cipher, $passphrase, false, $iv); |
||||
|
||||
if ($plainContent) { |
||||
return $plainContent; |
||||
} else { |
||||
throw new DecryptionFailedException('Encryption library: Decryption (symmetric) of content failed'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @param $data |
||||
* @return array |
||||
*/ |
||||
private function parseHeader($data) { |
||||
$result = []; |
||||
|
||||
if (substr($data, 0, strlen(self::HEADERSTART)) === self::HEADERSTART) { |
||||
$endAt = strpos($data, self::HEADEREND); |
||||
$header = substr($data, 0, $endAt + strlen(self::HEADEREND)); |
||||
|
||||
// +1 not to start with an ':' which would result in empty element at the beginning |
||||
$exploded = explode(':', substr($header, strlen(self::HEADERSTART) + 1)); |
||||
|
||||
$element = array_shift($exploded); |
||||
|
||||
while ($element != self::HEADEREND) { |
||||
$result[$element] = array_shift($exploded); |
||||
$element = array_shift($exploded); |
||||
} |
||||
} |
||||
|
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
* @throws GenericEncryptionException |
||||
*/ |
||||
private function generateIv() { |
||||
$random = openssl_random_pseudo_bytes(12, $strong); |
||||
if ($random) { |
||||
if (!$strong) { |
||||
// If OpenSSL indicates randomness is insecure log error |
||||
$this->logger->error('Encryption Library: Insecure symmetric key was generated using openssl_random_psudo_bytes()', ['app' => 'encryption']); |
||||
} |
||||
|
||||
/* |
||||
* We encode the iv purely for string manipulation |
||||
* purposes -it gets decoded before use |
||||
*/ |
||||
return base64_encode($random); |
||||
} |
||||
// If we ever get here we've failed anyway no need for an else |
||||
throw new GenericEncryptionException('Generating IV Failed'); |
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,64 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/19/15, 10:13 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption; |
||||
|
||||
|
||||
use OCA\Encryption\Hooks\Contracts\IHook; |
||||
|
||||
class HookManager { |
||||
|
||||
private $hookInstances = []; |
||||
|
||||
/** |
||||
* @param array|IHook $instances |
||||
* - This accepts either a single instance of IHook or an array of instances of IHook |
||||
* @return bool |
||||
*/ |
||||
public function registerHook($instances) { |
||||
if (is_array($instances)) { |
||||
foreach ($instances as $instance) { |
||||
if (!$instance instanceof IHook) { |
||||
return false; |
||||
} |
||||
$this->hookInstances[] = $instance; |
||||
return true; |
||||
} |
||||
|
||||
} |
||||
$this->hookInstances[] = $instances; |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function fireHooks() { |
||||
foreach ($this->hookInstances as $instance) { |
||||
/** |
||||
* @var $instance IHook |
||||
*/ |
||||
$instance->addHooks(); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,217 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/19/15, 1:20 PM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption; |
||||
|
||||
|
||||
use OC\Encryption\Exceptions\PrivateKeyMissingException; |
||||
use OC\Encryption\Exceptions\PublicKeyMissingException; |
||||
use OCA\Encryption\Crypto\Crypt; |
||||
use OCP\Encryption\IKeyStorage; |
||||
use OCP\IConfig; |
||||
use OCP\IUser; |
||||
use OCP\IUserSession; |
||||
|
||||
class KeyManager { |
||||
|
||||
/** |
||||
* @var IKeyStorage |
||||
*/ |
||||
private $keyStorage; |
||||
|
||||
/** |
||||
* @var Crypt |
||||
*/ |
||||
private $crypt; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $recoveryKeyId; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $publicShareKeyId; |
||||
/** |
||||
* @var string UserID |
||||
*/ |
||||
private $keyId; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $publicKeyId = '.public'; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $privateKeyId = '.private'; |
||||
/** |
||||
* @var IConfig |
||||
*/ |
||||
private $config; |
||||
|
||||
/** |
||||
* @param IKeyStorage $keyStorage |
||||
* @param Crypt $crypt |
||||
* @param IConfig $config |
||||
* @param IUserSession $userSession |
||||
*/ |
||||
public function __construct(IKeyStorage $keyStorage, Crypt $crypt, IConfig $config, IUserSession $userSession) { |
||||
|
||||
$this->keyStorage = $keyStorage; |
||||
$this->crypt = $crypt; |
||||
$this->config = $config; |
||||
$this->recoveryKeyId = $this->config->getAppValue('encryption', 'recoveryKeyId'); |
||||
$this->publicShareKeyId = $this->config->getAppValue('encryption', 'publicShareKeyId'); |
||||
$this->keyId = $userSession && $userSession->isLoggedIn() ? $userSession->getUser()->getUID() : false; |
||||
|
||||
} |
||||
|
||||
/** |
||||
* @param $userId |
||||
* @return mixed |
||||
* @throws PrivateKeyMissingException |
||||
*/ |
||||
public function getPrivateKey($userId) { |
||||
$privateKey = $this->keyStorage->getUserKey($userId, $this->privateKeyId); |
||||
|
||||
if (strlen($privateKey) !== 0) { |
||||
return $privateKey; |
||||
} |
||||
throw new PrivateKeyMissingException(); |
||||
} |
||||
|
||||
/** |
||||
* @param $userId |
||||
* @return mixed |
||||
* @throws PublicKeyMissingException |
||||
*/ |
||||
public function getPublicKey($userId) { |
||||
$publicKey = $this->keyStorage->getUserKey($userId, $this->publicKeyId); |
||||
|
||||
if (strlen($publicKey) !== 0) { |
||||
return $publicKey; |
||||
} |
||||
throw new PublicKeyMissingException(); |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function recoveryKeyExists() { |
||||
return (strlen($this->keyStorage->getSystemUserKey($this->recoveryKeyId)) !== 0); |
||||
} |
||||
|
||||
/** |
||||
* @param $userId |
||||
* @return bool |
||||
*/ |
||||
public function userHasKeys($userId) { |
||||
try { |
||||
$this->getPrivateKey($userId); |
||||
$this->getPublicKey($userId); |
||||
} catch (PrivateKeyMissingException $e) { |
||||
return false; |
||||
} catch (PublicKeyMissingException $e) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* @param $password |
||||
* @return bool |
||||
*/ |
||||
public function checkRecoveryPassword($password) { |
||||
$recoveryKey = $this->keyStorage->getSystemUserKey($this->recoveryKeyId); |
||||
$decryptedRecoveryKey = $this->crypt->decryptPrivateKey($recoveryKey, $password); |
||||
|
||||
if ($decryptedRecoveryKey) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @param $userId |
||||
* @param $key |
||||
* @return bool |
||||
*/ |
||||
public function setPublicKey($userId, $key) { |
||||
return $this->keyStorage->setUserKey($userId, $this->publicKeyId, $key); |
||||
} |
||||
|
||||
/** |
||||
* @param $userId |
||||
* @param $key |
||||
* @return bool |
||||
*/ |
||||
public function setPrivateKey($userId, $key) { |
||||
return $this->keyStorage->setUserKey($userId, $this->privateKeyId, $key); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @param $password |
||||
* @param $keyPair |
||||
* @return bool |
||||
*/ |
||||
public function storeKeyPair($password, $keyPair) { |
||||
// Save Public Key |
||||
$this->setPublicKey($this->keyId, $keyPair['publicKey']); |
||||
|
||||
$encryptedKey = $this->crypt->symmetricEncryptFileContent($keyPair['privateKey'], $password); |
||||
|
||||
if ($encryptedKey) { |
||||
$this->setPrivateKey($this->keyId, $encryptedKey); |
||||
$this->config->setAppValue('encryption', 'recoveryAdminEnabled', 1); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function ready() { |
||||
return $this->keyStorage->ready(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @return \OCP\ICache |
||||
* @throws PrivateKeyMissingException |
||||
*/ |
||||
public function init() { |
||||
try { |
||||
$privateKey = $this->getPrivateKey($this->keyId); |
||||
} catch (PrivateKeyMissingException $e) { |
||||
return false; |
||||
} |
||||
|
||||
$cache = \OC::$server->getMemCacheFactory(); |
||||
|
||||
$cacheInstance = $cache->create('Encryption'); |
||||
$cacheInstance->set('privateKey', $privateKey); |
||||
|
||||
return $cacheInstance; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,123 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <fallen013@gmail.com> |
||||
* @since 3/9/15, 2:44 PM |
||||
* @link http:/www.clarkt.com |
||||
* @copyright Clark Tomlinson © 2015 |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption; |
||||
|
||||
|
||||
use OCA\Encryption\Crypto\Crypt; |
||||
use OCP\IConfig; |
||||
use OCP\ILogger; |
||||
use OCP\IUserManager; |
||||
use OCP\IUserSession; |
||||
use OCP\PreConditionNotMetException; |
||||
|
||||
class Migrator { |
||||
|
||||
/** |
||||
* @var bool |
||||
*/ |
||||
private $status = false; |
||||
/** |
||||
* @var IUserManager |
||||
*/ |
||||
private $user; |
||||
/** |
||||
* @var IConfig |
||||
*/ |
||||
private $config; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public static $migrationOpen = '0'; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public static $migrationInProgress = '-1'; |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public static $migrationComplete = '1'; |
||||
/** |
||||
* @var IUserManager |
||||
*/ |
||||
private $userManager; |
||||
/** |
||||
* @var ILogger |
||||
*/ |
||||
private $log; |
||||
/** |
||||
* @var Crypt |
||||
*/ |
||||
private $crypt; |
||||
|
||||
/** |
||||
* Migrator constructor. |
||||
* |
||||
* @param IUserSession $userSession |
||||
* @param IConfig $config |
||||
* @param IUserManager $userManager |
||||
* @param ILogger $log |
||||
* @param Crypt $crypt |
||||
*/ |
||||
public function __construct(IUserSession $userSession, IConfig $config, IUserManager $userManager, ILogger $log, Crypt $crypt) { |
||||
$this->user = $userSession && $userSession->isLoggedIn() ? $userSession->getUser() : false; |
||||
$this->config = $config; |
||||
$this->userManager = $userManager; |
||||
$this->log = $log; |
||||
$this->crypt = $crypt; |
||||
} |
||||
|
||||
/** |
||||
* @param $userId |
||||
* @return bool|string |
||||
*/ |
||||
public function getStatus($userId) { |
||||
if ($this->userManager->userExists($userId)) { |
||||
$this->status = $this->config->getUserValue($userId, 'encryption', 'migrationStatus', false); |
||||
|
||||
if (!$this->status) { |
||||
$this->config->setUserValue($userId, 'encryption', 'migrationStatus', self::$migrationOpen); |
||||
$this->status = self::$migrationOpen; |
||||
} |
||||
} |
||||
|
||||
return $this->status; |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function beginMigration() { |
||||
$status = $this->setMigrationStatus(self::$migrationInProgress, self::$migrationOpen); |
||||
|
||||
if ($status) { |
||||
$this->log->info('Encryption Library Start migration to encrypt for ' . $this->user->getUID()); |
||||
return $status; |
||||
} |
||||
$this->log->warning('Encryption Library Could not activate migration for ' . $this->user->getUID() . '. Probably another process already started the inital encryption'); |
||||
return $status; |
||||
} |
||||
|
||||
/** |
||||
* @param $status |
||||
* @param bool $preCondition |
||||
* @return bool |
||||
*/ |
||||
private function setMigrationStatus($status, $preCondition = false) { |
||||
// Convert to string if preCondition is set |
||||
$preCondition = ($preCondition === false) ? false : (string)$preCondition; |
||||
|
||||
try { |
||||
$this->config->setUserValue($this->user->getUID(), 'encryption', 'migrationStatus', (string)$status, $preCondition); |
||||
return true; |
||||
} catch (PreConditionNotMetException $e) { |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,134 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/19/15, 11:45 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption; |
||||
|
||||
|
||||
use OC\Files\View; |
||||
use OCA\Encryption\Crypto\Crypt; |
||||
use OCP\Encryption\IKeyStorage; |
||||
use OCP\IConfig; |
||||
use OCP\IUser; |
||||
use OCP\Security\ISecureRandom; |
||||
|
||||
class Recovery { |
||||
|
||||
|
||||
/** |
||||
* @var null|IUser |
||||
*/ |
||||
protected $user; |
||||
/** |
||||
* @var Crypt |
||||
*/ |
||||
protected $crypt; |
||||
/** |
||||
* @var ISecureRandom |
||||
*/ |
||||
private $random; |
||||
/** |
||||
* @var KeyManager |
||||
*/ |
||||
private $keyManager; |
||||
/** |
||||
* @var IConfig |
||||
*/ |
||||
private $config; |
||||
/** |
||||
* @var IEncryptionKeyStorage |
||||
*/ |
||||
private $keyStorage; |
||||
|
||||
/** |
||||
* @param IUser $user |
||||
* @param Crypt $crypt |
||||
* @param ISecureRandom $random |
||||
* @param KeyManager $keyManager |
||||
* @param IConfig $config |
||||
* @param IKeyStorage $keyStorage |
||||
*/ |
||||
public function __construct(IUser $user, |
||||
Crypt $crypt, |
||||
ISecureRandom $random, |
||||
KeyManager $keyManager, |
||||
IConfig $config, |
||||
IKeyStorage $keyStorage) { |
||||
$this->user = $user; |
||||
$this->crypt = $crypt; |
||||
$this->random = $random; |
||||
$this->keyManager = $keyManager; |
||||
$this->config = $config; |
||||
$this->keyStorage = $keyStorage; |
||||
} |
||||
|
||||
/** |
||||
* @param $recoveryKeyId |
||||
* @param $password |
||||
* @return bool |
||||
*/ |
||||
public function enableAdminRecovery($recoveryKeyId, $password) { |
||||
$appConfig = $this->config; |
||||
|
||||
if ($recoveryKeyId === null) { |
||||
$recoveryKeyId = $this->random->getLowStrengthGenerator(); |
||||
$appConfig->setAppValue('encryption', 'recoveryKeyId', $recoveryKeyId); |
||||
} |
||||
|
||||
$keyManager = $this->keyManager; |
||||
|
||||
if (!$keyManager->recoveryKeyExists()) { |
||||
$keyPair = $this->crypt->createKeyPair(); |
||||
|
||||
return $this->keyManager->storeKeyPair($password, $keyPair); |
||||
} |
||||
|
||||
if ($keyManager->checkRecoveryPassword($password)) { |
||||
$appConfig->setAppValue('encryption', 'recoveryAdminEnabled', 1); |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @param $recoveryPassword |
||||
* @return bool |
||||
*/ |
||||
public function disableAdminRecovery($recoveryPassword) { |
||||
$keyManager = $this->keyManager; |
||||
|
||||
if ($keyManager->checkRecoveryPassword($recoveryPassword)) { |
||||
// Set recoveryAdmin as disabled |
||||
$this->config->setAppValue('encryption', 'recoveryAdminEnabled', 0); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public function addRecoveryKeys($keyId) { |
||||
// No idea new way to do this.... |
||||
} |
||||
|
||||
public function removeRecoveryKeys() { |
||||
// No idea new way to do this.... |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,38 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <fallen013@gmail.com> |
||||
* @since 3/6/15, 11:30 AM |
||||
* @link http:/www.clarkt.com |
||||
* @copyright Clark Tomlinson © 2015 |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption; |
||||
|
||||
|
||||
use OCP\ILogger; |
||||
use OCP\IUser; |
||||
use OCP\IUserSession; |
||||
|
||||
class Setup { |
||||
/** |
||||
* @var ILogger |
||||
*/ |
||||
protected $logger; |
||||
/** |
||||
* @var IUser |
||||
*/ |
||||
protected $user; |
||||
|
||||
/** |
||||
* Setup constructor. |
||||
* |
||||
* @param ILogger $logger |
||||
* @param IUserSession $userSession |
||||
*/ |
||||
public function __construct(ILogger $logger, IUserSession $userSession) { |
||||
$this->logger = $logger; |
||||
$this->user = $userSession && $userSession->isLoggedIn() ? $userSession->getUser()->getUID() : false; |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,63 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <fallen013@gmail.com> |
||||
* @since 3/6/15, 11:36 AM |
||||
* @link http:/www.clarkt.com |
||||
* @copyright Clark Tomlinson © 2015 |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption\Users; |
||||
|
||||
|
||||
use OCA\Encryption\Crypto\Crypt; |
||||
use OCA\Encryption\KeyManager; |
||||
use OCP\ILogger; |
||||
use OCP\IUserSession; |
||||
|
||||
class Setup extends \OCA\Encryption\Setup { |
||||
/** |
||||
* @var Crypt |
||||
*/ |
||||
private $crypt; |
||||
/** |
||||
* @var KeyManager |
||||
*/ |
||||
private $keyManager; |
||||
|
||||
|
||||
/** |
||||
* @param ILogger $logger |
||||
* @param IUserSession $userSession |
||||
* @param Crypt $crypt |
||||
* @param KeyManager $keyManager |
||||
*/ |
||||
public function __construct(ILogger $logger, IUserSession $userSession, Crypt $crypt, KeyManager $keyManager) { |
||||
parent::__construct($logger, $userSession); |
||||
$this->crypt = $crypt; |
||||
$this->keyManager = $keyManager; |
||||
} |
||||
|
||||
/** |
||||
* @param $password |
||||
* @return bool |
||||
*/ |
||||
public function setupUser($password) { |
||||
if ($this->keyManager->ready()) { |
||||
$this->logger->debug('Encryption Library: User Account ' . $this->user->getUID() . ' Is not ready for encryption; configuration started'); |
||||
return $this->setupServerSide($password); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @param $password |
||||
* @return bool |
||||
*/ |
||||
private function setupServerSide($password) { |
||||
// Check if user already has keys |
||||
if (!$this->keyManager->userHasKeys($this->user->getUID())) { |
||||
return $this->keyManager->storeKeyPair($password, $this->crypt->createKeyPair()); |
||||
} |
||||
return true; |
||||
} |
||||
} |
||||
@ -0,0 +1,24 @@ |
||||
<?php |
||||
/** |
||||
* Copyright (c) 2011 Robin Appelman <icewind@owncloud.com> |
||||
* This file is licensed under the Affero General Public License version 3 or |
||||
* later. |
||||
* See the COPYING-README file. |
||||
*/ |
||||
|
||||
\OC_Util::checkAdminUser(); |
||||
|
||||
$tmpl = new OCP\Template('files_encryption', 'settings-admin'); |
||||
|
||||
// Check if an adminRecovery account is enabled for recovering files after lost pwd |
||||
$recoveryAdminEnabled = \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryAdminEnabled', '0'); |
||||
$session = new \OCA\Files_Encryption\Session(new \OC\Files\View('/')); |
||||
$initStatus = $session->getInitialized(); |
||||
|
||||
$tmpl->assign('recoveryEnabled', $recoveryAdminEnabled); |
||||
$tmpl->assign('initStatus', $initStatus); |
||||
|
||||
\OCP\Util::addscript('files_encryption', 'settings-admin'); |
||||
\OCP\Util::addscript('core', 'multiselect'); |
||||
|
||||
return $tmpl->fetchPage(); |
||||
@ -0,0 +1,41 @@ |
||||
<?php |
||||
/** |
||||
* Copyright (c) 2013 Sam Tuke <samtuke@owncloud.com> |
||||
* This file is licensed under the Affero General Public License version 3 or |
||||
* later. |
||||
* See the COPYING-README file. |
||||
*/ |
||||
|
||||
// Add CSS stylesheet |
||||
\OC_Util::addStyle('files_encryption', 'settings-personal'); |
||||
|
||||
$tmpl = new OCP\Template('files_encryption', 'settings-personal'); |
||||
|
||||
$user = \OCP\USER::getUser(); |
||||
$view = new \OC\Files\View('/'); |
||||
$util = new \OCA\Files_Encryption\Util($view, $user); |
||||
$session = new \OCA\Files_Encryption\Session($view); |
||||
|
||||
$privateKeySet = $session->getPrivateKey() !== false; |
||||
// did we tried to initialize the keys for this session? |
||||
$initialized = $session->getInitialized(); |
||||
|
||||
$recoveryAdminEnabled = \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryAdminEnabled'); |
||||
$recoveryEnabledForUser = $util->recoveryEnabledForUser(); |
||||
|
||||
$result = false; |
||||
|
||||
if ($recoveryAdminEnabled || !$privateKeySet) { |
||||
|
||||
\OCP\Util::addscript('files_encryption', 'settings-personal'); |
||||
|
||||
$tmpl->assign('recoveryEnabled', $recoveryAdminEnabled); |
||||
$tmpl->assign('recoveryEnabledForUser', $recoveryEnabledForUser); |
||||
$tmpl->assign('privateKeySet', $privateKeySet); |
||||
$tmpl->assign('initialized', $initialized); |
||||
|
||||
$result = $tmpl->fetchPage(); |
||||
} |
||||
|
||||
return $result; |
||||
|
||||
@ -0,0 +1,90 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <fallen013@gmail.com> |
||||
* @since 3/5/15, 10:53 AM |
||||
* @link http:/www.clarkt.com |
||||
* @copyright Clark Tomlinson © 2015 |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption\Tests; |
||||
|
||||
|
||||
use OCA\Encryption\KeyManager; |
||||
use Test\TestCase; |
||||
|
||||
class KeyManagerTest extends TestCase { |
||||
/** |
||||
* @var KeyManager |
||||
*/ |
||||
private $instance; |
||||
/** |
||||
* @var |
||||
*/ |
||||
private $userId; |
||||
/** |
||||
* @var |
||||
*/ |
||||
private $dummyKeys; |
||||
|
||||
public function setUp() { |
||||
parent::setUp(); |
||||
$keyStorageMock = $this->getMock('OCP\Encryption\IKeyStorage'); |
||||
$cryptMock = $this->getMockBuilder('OCA\Encryption\Crypt') |
||||
->disableOriginalConstructor() |
||||
->getMock(); |
||||
$configMock = $this->getMock('OCP\IConfig'); |
||||
$userMock = $this->getMock('OCP\IUser'); |
||||
$userMock->expects($this->once()) |
||||
->method('getUID') |
||||
->will($this->returnValue('admin')); |
||||
$this->userId = 'admin'; |
||||
$this->instance = new KeyManager($keyStorageMock, $cryptMock, $configMock, $userMock); |
||||
|
||||
$this->dummyKeys = ['public' => 'randomweakpublickeyhere', |
||||
'private' => 'randomweakprivatekeyhere']; |
||||
} |
||||
|
||||
/** |
||||
* @expectedException OC\Encryption\Exceptions\PrivateKeyMissingException |
||||
*/ |
||||
public function testGetPrivateKey() { |
||||
$this->assertFalse($this->instance->getPrivateKey($this->userId)); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException OC\Encryption\Exceptions\PublicKeyMissingException |
||||
*/ |
||||
public function testGetPublicKey() { |
||||
$this->assertFalse($this->instance->getPublicKey($this->userId)); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function testRecoveryKeyExists() { |
||||
$this->assertFalse($this->instance->recoveryKeyExists()); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function testCheckRecoveryKeyPassword() { |
||||
$this->assertFalse($this->instance->checkRecoveryPassword('pass')); |
||||
} |
||||
|
||||
public function testSetPublicKey() { |
||||
|
||||
$this->assertTrue($this->instance->setPublicKey($this->userId, $this->dummyKeys['public'])); |
||||
} |
||||
|
||||
public function testSetPrivateKey() { |
||||
$this->assertTrue($this->instance->setPrivateKey($this->userId, $this->dummyKeys['private'])); |
||||
} |
||||
|
||||
public function testUserHasKeys() { |
||||
$this->assertFalse($this->instance->userHasKeys($this->userId)); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,62 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <fallen013@gmail.com> |
||||
* @since 3/9/15, 2:56 PM |
||||
* @link http:/www.clarkt.com |
||||
* @copyright Clark Tomlinson © 2015 |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption\Tests; |
||||
|
||||
|
||||
use OCA\Encryption\Migrator; |
||||
use Test\TestCase; |
||||
|
||||
class MigratorTest extends TestCase { |
||||
|
||||
/** |
||||
* @var Migrator |
||||
*/ |
||||
private $instance; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function testGetStatus() { |
||||
$this->assertFalse($this->instance->getStatus('admin')); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function testBeginMigration() { |
||||
$this->assertTrue($this->instance->beginMigration()); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function testSetMigrationStatus() { |
||||
$this->assertTrue(\Test_Helper::invokePrivate($this->instance, |
||||
'setMigrationStatus', |
||||
['0', '-1']) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
protected function setUp() { |
||||
parent::setUp(); |
||||
|
||||
$cryptMock = $this->getMockBuilder('OCA\Encryption\Crypto\Crypt')->disableOriginalConstructor()->getMock(); |
||||
$this->instance = new Migrator($this->getMock('OCP\IUser'), |
||||
$this->getMock('OCP\IConfig'), |
||||
$this->getMock('OCP\IUserManager'), |
||||
$this->getMock('OCP\ILogger'), |
||||
$cryptMock); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,51 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <fallen013@gmail.com> |
||||
* @since 3/6/15, 10:36 AM |
||||
* @link http:/www.clarkt.com |
||||
* @copyright Clark Tomlinson © 2015 |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Encryption\Tests; |
||||
|
||||
|
||||
use OCA\Encryption\RequirementsChecker; |
||||
use Test\TestCase; |
||||
|
||||
class RequirementsCheckerTest extends TestCase { |
||||
/** |
||||
* @var RequirementsChecker |
||||
*/ |
||||
private $instance; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
protected function setUp() { |
||||
parent::setUp(); |
||||
$log = $this->getMock('OCP\ILogger'); |
||||
$crypt = $this->getMockBuilder('OCA\Encryption\Crypt') |
||||
->disableOriginalConstructor() |
||||
->getMock(); |
||||
$crypt |
||||
->method('getOpenSSLPkey') |
||||
->will($this->returnValue(true)); |
||||
$this->instance = new RequirementsChecker($crypt, $log); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function testCanCheckConfigration() { |
||||
$this->assertTrue($this->instance->checkConfiguration()); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function testCanCheckRequiredExtensions() { |
||||
$this->assertTrue($this->instance->checkExtensions()); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,28 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/25/15, 9:38 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\Encryption\Exceptions; |
||||
|
||||
|
||||
class DecryptionFailedException extends GenericEncryptionException { |
||||
|
||||
} |
||||
@ -0,0 +1,28 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/25/15, 9:38 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\Encryption\Exceptions; |
||||
|
||||
|
||||
class EmptyEncryptionDataException extends GenericEncryptionException{ |
||||
|
||||
} |
||||
@ -0,0 +1,28 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/25/15, 9:37 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\Encryption\Exceptions; |
||||
|
||||
|
||||
class EncryptionFailedException extends GenericEncryptionException{ |
||||
|
||||
} |
||||
@ -0,0 +1,28 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/25/15, 9:35 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\Encryption\Exceptions; |
||||
|
||||
|
||||
class EncryptionHeaderToLargeException extends GenericEncryptionException { |
||||
|
||||
} |
||||
@ -0,0 +1,27 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/25/15, 9:30 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
namespace OC\Encryption\Exceptions; |
||||
|
||||
|
||||
class GenericEncryptionException extends \Exception { |
||||
|
||||
} |
||||
@ -0,0 +1,28 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/25/15, 9:39 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\Encryption\Exceptions; |
||||
|
||||
|
||||
class PrivateKeyMissingException extends GenericEncryptionException{ |
||||
|
||||
} |
||||
@ -0,0 +1,28 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/25/15, 9:39 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\Encryption\Exceptions; |
||||
|
||||
|
||||
class PublicKeyMissingException extends GenericEncryptionException { |
||||
|
||||
} |
||||
@ -0,0 +1,28 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/25/15, 9:35 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\Encryption\Exceptions; |
||||
|
||||
|
||||
interface UnexpectedBlockSize { |
||||
|
||||
} |
||||
@ -0,0 +1,28 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/25/15, 9:34 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\Encryption\Exceptions; |
||||
|
||||
|
||||
class UnexpectedEndOfEncryptionHeaderException extends GenericEncryptionException { |
||||
|
||||
} |
||||
@ -0,0 +1,28 @@ |
||||
<?php |
||||
/** |
||||
* @author Clark Tomlinson <clark@owncloud.com> |
||||
* @since 2/25/15, 9:36 AM |
||||
* @copyright Copyright (c) 2015, ownCloud, Inc. |
||||
* @license AGPL-3.0 |
||||
* |
||||
* This code is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, version 3, |
||||
* as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License, version 3, |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/> |
||||
* |
||||
*/ |
||||
|
||||
|
||||
namespace OC\Encryption\Exceptions; |
||||
|
||||
|
||||
class UnknownCipherException extends GenericEncryptionException{ |
||||
|
||||
} |
||||
Loading…
Reference in new issue