Merge pull request #5174 from nextcloud/new-encryption-default
Use the master key by default
This commit is contained in:
commit
ad1d4d363f
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
*
|
||||
* @author Joas Schilling <coding@schilljs.com>
|
||||
* @author Robin Appelman <robin@icewind.nl>
|
||||
* @author Thomas Müller <thomas.mueller@tmit.eu>
|
||||
*
|
||||
* @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\DAV\Tests\unit\Connector\Sabre\RequestTest;
|
||||
|
||||
use OC\Files\View;
|
||||
use Test\Traits\EncryptionTrait;
|
||||
|
||||
/**
|
||||
* Class EncryptionMasterKeyUploadTest
|
||||
*
|
||||
* @group DB
|
||||
*
|
||||
* @package OCA\DAV\Tests\Unit\Connector\Sabre\RequestTest
|
||||
*/
|
||||
class EncryptionMasterKeyUploadTest extends UploadTest {
|
||||
use EncryptionTrait;
|
||||
|
||||
protected function setupUser($name, $password) {
|
||||
$this->createUser($name, $password);
|
||||
$tmpFolder = \OC::$server->getTempManager()->getTemporaryFolder();
|
||||
$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
|
||||
// we use the master key
|
||||
\OC::$server->getConfig()->setAppValue('encryption', 'useMasterKey', '1');
|
||||
$this->setupForUser($name, $password);
|
||||
$this->loginWithEncryption($name);
|
||||
return new View('/' . $name . '/files');
|
||||
}
|
||||
}
|
|
@ -41,6 +41,8 @@ class EncryptionUploadTest extends UploadTest {
|
|||
$this->createUser($name, $password);
|
||||
$tmpFolder = \OC::$server->getTempManager()->getTemporaryFolder();
|
||||
$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
|
||||
// we use per-user keys
|
||||
\OC::$server->getConfig()->setAppValue('encryption', 'useMasterKey', '0');
|
||||
$this->setupForUser($name, $password);
|
||||
$this->loginWithEncryption($name);
|
||||
return new View('/' . $name . '/files');
|
||||
|
|
|
@ -31,4 +31,5 @@ $app = new Application([], $encryptionSystemReady);
|
|||
if ($encryptionSystemReady) {
|
||||
$app->registerEncryptionModule();
|
||||
$app->registerHooks();
|
||||
$app->setUp();
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<user>user-encryption</user>
|
||||
<admin>admin-encryption</admin>
|
||||
</documentation>
|
||||
<version>1.7.1</version>
|
||||
<version>2.0.0</version>
|
||||
<types>
|
||||
<filesystem/>
|
||||
</types>
|
||||
|
@ -33,6 +33,13 @@
|
|||
</settings>
|
||||
<commands>
|
||||
<command>OCA\Encryption\Command\EnableMasterKey</command>
|
||||
<command>OCA\Encryption\Command\DisableMasterKey</command>
|
||||
<command>OCA\Encryption\Command\MigrateKeys</command>
|
||||
</commands>
|
||||
|
||||
<repair-steps>
|
||||
<post-migration>
|
||||
<step>OCA\Encryption\Migration\SetMasterKeyStatus</step>
|
||||
</post-migration>
|
||||
</repair-steps>
|
||||
</info>
|
||||
|
|
|
@ -67,7 +67,11 @@ class Application extends \OCP\AppFramework\App {
|
|||
$session = $this->getContainer()->query('Session');
|
||||
$session->setStatus(Session::RUN_MIGRATION);
|
||||
}
|
||||
if ($this->encryptionManager->isEnabled() && $encryptionSystemReady) {
|
||||
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
if ($this->encryptionManager->isEnabled()) {
|
||||
/** @var Setup $setup */
|
||||
$setup = $this->getContainer()->query('UserSetup');
|
||||
$setup->setupSystem();
|
||||
|
@ -77,7 +81,6 @@ class Application extends \OCP\AppFramework\App {
|
|||
/**
|
||||
* register hooks
|
||||
*/
|
||||
|
||||
public function registerHooks() {
|
||||
if (!$this->config->getSystemValue('maintenance', false)) {
|
||||
|
||||
|
@ -193,7 +196,8 @@ class Application extends \OCP\AppFramework\App {
|
|||
$c->getAppName(),
|
||||
$server->getRequest(),
|
||||
$server->getL10N($c->getAppName()),
|
||||
$c->query('Session')
|
||||
$c->query('Session'),
|
||||
$server->getEncryptionManager()
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace OCA\Encryption\Command;
|
||||
|
||||
|
||||
use OCA\Encryption\Util;
|
||||
use OCP\IConfig;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
|
||||
class DisableMasterKey extends Command {
|
||||
|
||||
/** @var Util */
|
||||
protected $util;
|
||||
|
||||
/** @var IConfig */
|
||||
protected $config;
|
||||
|
||||
/** @var QuestionHelper */
|
||||
protected $questionHelper;
|
||||
|
||||
/**
|
||||
* @param Util $util
|
||||
* @param IConfig $config
|
||||
* @param QuestionHelper $questionHelper
|
||||
*/
|
||||
public function __construct(Util $util,
|
||||
IConfig $config,
|
||||
QuestionHelper $questionHelper) {
|
||||
|
||||
$this->util = $util;
|
||||
$this->config = $config;
|
||||
$this->questionHelper = $questionHelper;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure() {
|
||||
$this
|
||||
->setName('encryption:disable-master-key')
|
||||
->setDescription('Disable the master key and use per-user keys instead. Only available for fresh installations with no existing encrypted data! There is no way to enable it again.');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
|
||||
$isMasterKeyEnabled = $this->util->isMasterKeyEnabled();
|
||||
|
||||
if(!$isMasterKeyEnabled) {
|
||||
$output->writeln('Master key already disabled');
|
||||
} else {
|
||||
$question = new ConfirmationQuestion(
|
||||
'Warning: Only perform this operation for a fresh installations with no existing encrypted data! '
|
||||
. 'There is no way to enable the master key again. '
|
||||
. 'We strongly recommend to keep the master key, it provides significant performance improvements '
|
||||
. 'and is easier to handle for both, users and administrators. '
|
||||
. 'Do you really want to switch to per-user keys? (y/n) ', false);
|
||||
if ($this->questionHelper->ask($input, $output, $question)) {
|
||||
$this->config->setAppValue('encryption', 'useMasterKey', '0');
|
||||
$output->writeln('Master key successfully disabled.');
|
||||
} else {
|
||||
$output->writeln('aborted.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -28,6 +28,7 @@ namespace OCA\Encryption\Controller;
|
|||
use OCA\Encryption\Session;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\Encryption\IManager;
|
||||
use OCP\IL10N;
|
||||
use OCP\IRequest;
|
||||
|
||||
|
@ -39,20 +40,26 @@ class StatusController extends Controller {
|
|||
/** @var Session */
|
||||
private $session;
|
||||
|
||||
/** @var IManager */
|
||||
private $encryptionManager;
|
||||
|
||||
/**
|
||||
* @param string $AppName
|
||||
* @param IRequest $request
|
||||
* @param IL10N $l10n
|
||||
* @param Session $session
|
||||
* @param IManager $encryptionManager
|
||||
*/
|
||||
public function __construct($AppName,
|
||||
IRequest $request,
|
||||
IL10N $l10n,
|
||||
Session $session
|
||||
Session $session,
|
||||
IManager $encryptionManager
|
||||
) {
|
||||
parent::__construct($AppName, $request);
|
||||
$this->l = $l10n;
|
||||
$this->session = $session;
|
||||
$this->encryptionManager = $encryptionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,9 +85,15 @@ class StatusController extends Controller {
|
|||
break;
|
||||
case Session::NOT_INITIALIZED:
|
||||
$status = 'interactionNeeded';
|
||||
if ($this->encryptionManager->isEnabled()) {
|
||||
$message = (string)$this->l->t(
|
||||
'Encryption App is enabled, but your keys are not initialized. Please log-out and log-in again.'
|
||||
);
|
||||
} else {
|
||||
$message = (string)$this->l->t(
|
||||
'Please enable server side encryption in the admin settings in order to use the encryption module.'
|
||||
);
|
||||
}
|
||||
break;
|
||||
case Session::INIT_SUCCESSFUL:
|
||||
$status = 'success';
|
||||
|
|
|
@ -569,4 +569,13 @@ class Encryption implements IEncryptionModule {
|
|||
public function isReadyForUser($user) {
|
||||
return $this->keyManager->userHasKeys($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* We only need a detailed access list if the master key is not enabled
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function needDetailedAccessList() {
|
||||
return !$this->util->isMasterKeyEnabled();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -179,8 +179,8 @@ class KeyManager {
|
|||
return;
|
||||
}
|
||||
|
||||
$masterKey = $this->getPublicMasterKey();
|
||||
if (empty($masterKey)) {
|
||||
$publicMasterKey = $this->getPublicMasterKey();
|
||||
if (empty($publicMasterKey)) {
|
||||
$keyPair = $this->crypt->createKeyPair();
|
||||
|
||||
// Save public key
|
||||
|
@ -193,6 +193,15 @@ class KeyManager {
|
|||
$header = $this->crypt->generateHeader();
|
||||
$this->setSystemPrivateKey($this->masterKeyId, $header . $encryptedKey);
|
||||
}
|
||||
|
||||
if (!$this->session->isPrivateKeySet()) {
|
||||
$masterKey = $this->getSystemPrivateKey($this->masterKeyId);
|
||||
$decryptedMasterKey = $this->crypt->decryptPrivateKey($masterKey, $this->getMasterKeyPassword(), $this->masterKeyId);
|
||||
$this->session->setPrivateKey($decryptedMasterKey);
|
||||
}
|
||||
|
||||
// after the encryption key is available we are ready to go
|
||||
$this->session->setStatus(Session::INIT_SUCCESSFUL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace OCA\Encryption\Migration;
|
||||
|
||||
|
||||
use OCP\IConfig;
|
||||
use OCP\Migration\IOutput;
|
||||
use OCP\Migration\IRepairStep;
|
||||
|
||||
/**
|
||||
* Class SetPasswordColumn
|
||||
*
|
||||
* @package OCA\Files_Sharing\Migration
|
||||
*/
|
||||
class SetMasterKeyStatus implements IRepairStep {
|
||||
|
||||
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
|
||||
|
||||
public function __construct(IConfig $config) {
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the step's name
|
||||
*
|
||||
* @return string
|
||||
* @since 9.1.0
|
||||
*/
|
||||
public function getName() {
|
||||
return 'Write default encryption module configuration to the database';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
*/
|
||||
public function run(IOutput $output) {
|
||||
if (!$this->shouldRun()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if no config for the master key is set we set it explicitly to '0' in
|
||||
// order not to break old installations because the default changed to '1'.
|
||||
$configAlreadySet = $this->config->getAppValue('encryption', 'useMasterKey', false);
|
||||
if ($configAlreadySet === false) {
|
||||
$this->config->setAppValue('encryption', 'useMasterKey', '0');
|
||||
}
|
||||
}
|
||||
|
||||
protected function shouldRun() {
|
||||
$appVersion = $this->config->getAppValue('encryption', 'installed_version', '0.0.0');
|
||||
return version_compare($appVersion, '2.0.0', '<');
|
||||
}
|
||||
|
||||
}
|
|
@ -136,7 +136,7 @@ class Util {
|
|||
* @return bool
|
||||
*/
|
||||
public function isMasterKeyEnabled() {
|
||||
$userMasterKey = $this->config->getAppValue('encryption', 'useMasterKey', '0');
|
||||
$userMasterKey = $this->config->getAppValue('encryption', 'useMasterKey', '1');
|
||||
return ($userMasterKey === '1');
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ style('encryption', 'settings-admin');
|
|||
?>
|
||||
<form id="ocDefaultEncryptionModule" class="sub-section">
|
||||
<h3><?php p($l->t("Default encryption module")); ?></h3>
|
||||
<?php if(!$_["initStatus"]): ?>
|
||||
<?php if(!$_["initStatus"] && $_['masterKeyEnabled'] === false): ?>
|
||||
<?php p($l->t("Encryption app is enabled but your keys are not initialized, please log-out and log-in again")); ?>
|
||||
<?php else: ?>
|
||||
<p id="encryptHomeStorageSetting">
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace OCA\Encryption\Tests\Controller;
|
|||
|
||||
use OCA\Encryption\Controller\StatusController;
|
||||
use OCA\Encryption\Session;
|
||||
use OCP\Encryption\IManager;
|
||||
use OCP\IRequest;
|
||||
use Test\TestCase;
|
||||
|
||||
|
@ -41,6 +42,9 @@ class StatusControllerTest extends TestCase {
|
|||
/** @var \OCA\Encryption\Session | \PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $sessionMock;
|
||||
|
||||
/** @var IManager | \PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $encryptionManagerMock;
|
||||
|
||||
/** @var StatusController */
|
||||
protected $controller;
|
||||
|
||||
|
@ -59,11 +63,13 @@ class StatusControllerTest extends TestCase {
|
|||
->will($this->returnCallback(function($message) {
|
||||
return $message;
|
||||
}));
|
||||
$this->encryptionManagerMock = $this->createMock(IManager::class);
|
||||
|
||||
$this->controller = new StatusController('encryptionTest',
|
||||
$this->requestMock,
|
||||
$this->l10nMock,
|
||||
$this->sessionMock);
|
||||
$this->sessionMock,
|
||||
$this->encryptionManagerMock);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ class UtilTest extends TestCase {
|
|||
*/
|
||||
public function testIsMasterKeyEnabled($value, $expect) {
|
||||
$this->configMock->expects($this->once())->method('getAppValue')
|
||||
->with('encryption', 'useMasterKey', '0')->willReturn($value);
|
||||
->with('encryption', 'useMasterKey', '1')->willReturn($value);
|
||||
$this->assertSame($expect,
|
||||
$this->instance->isMasterKeyEnabled()
|
||||
);
|
||||
|
|
|
@ -36,8 +36,10 @@ class EncryptedSizePropagationTest extends SizePropagationTest {
|
|||
$this->createUser($name, $password);
|
||||
$tmpFolder = \OC::$server->getTempManager()->getTemporaryFolder();
|
||||
$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
|
||||
$this->config->setAppValue('encryption', 'useMasterKey', '0');
|
||||
$this->setupForUser($name, $password);
|
||||
$this->loginWithEncryption($name);
|
||||
return new View('/' . $name . '/files');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -168,6 +168,14 @@ class Update {
|
|||
*/
|
||||
public function update($path) {
|
||||
|
||||
$encryptionModule = $this->encryptionManager->getEncryptionModule();
|
||||
|
||||
// if the encryption module doesn't encrypt the files on a per-user basis
|
||||
// we have nothing to do here.
|
||||
if ($encryptionModule->needDetailedAccessList() === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if a folder was shared, get a list of all (sub-)folders
|
||||
if ($this->view->is_dir($path)) {
|
||||
$allFiles = $this->util->getAllFiles($path);
|
||||
|
@ -175,7 +183,7 @@ class Update {
|
|||
$allFiles = array($path);
|
||||
}
|
||||
|
||||
$encryptionModule = $this->encryptionManager->getEncryptionModule();
|
||||
|
||||
|
||||
foreach ($allFiles as $file) {
|
||||
$usersSharing = $this->file->getAccessList($file);
|
||||
|
|
|
@ -254,7 +254,10 @@ class Encryption extends Wrapper {
|
|||
$sharePath = dirname($sharePath);
|
||||
}
|
||||
|
||||
$accessList = [];
|
||||
if ($this->encryptionModule->needDetailedAccessList()) {
|
||||
$accessList = $this->file->getAccessList($sharePath);
|
||||
}
|
||||
$this->newHeader = $this->encryptionModule->begin($this->fullPath, $this->uid, $mode, $this->header, $accessList);
|
||||
|
||||
if (
|
||||
|
|
|
@ -182,4 +182,14 @@ interface IEncryptionModule {
|
|||
*/
|
||||
public function isReadyForUser($user);
|
||||
|
||||
/**
|
||||
* Does the encryption module needs a detailed list of users with access to the file?
|
||||
* For example if the encryption module uses per-user encryption keys and needs to know
|
||||
* the users with access to the file to encrypt/decrypt it.
|
||||
*
|
||||
* @since 13.0.0
|
||||
* @return bool
|
||||
*/
|
||||
public function needDetailedAccessList();
|
||||
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ use OCP\AppFramework\Http\DataResponse;
|
|||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\BackgroundJob\IJobList;
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
use OCP\Encryption\IEncryptionModule;
|
||||
use OCP\Encryption\IManager;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IL10N;
|
||||
|
@ -99,9 +101,14 @@ class UsersController extends Controller {
|
|||
private $keyManager;
|
||||
/** @var IJobList */
|
||||
private $jobList;
|
||||
|
||||
/** @var IUserMountCache */
|
||||
private $userMountCache;
|
||||
|
||||
/** @var IManager */
|
||||
private $encryptionManager;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $appName
|
||||
* @param IRequest $request
|
||||
|
@ -124,6 +131,7 @@ class UsersController extends Controller {
|
|||
* @param Manager $keyManager
|
||||
* @param IJobList $jobList
|
||||
* @param IUserMountCache $userMountCache
|
||||
* @param IManager $encryptionManager
|
||||
*/
|
||||
public function __construct($appName,
|
||||
IRequest $request,
|
||||
|
@ -145,7 +153,8 @@ class UsersController extends Controller {
|
|||
ICrypto $crypto,
|
||||
Manager $keyManager,
|
||||
IJobList $jobList,
|
||||
IUserMountCache $userMountCache) {
|
||||
IUserMountCache $userMountCache,
|
||||
IManager $encryptionManager) {
|
||||
parent::__construct($appName, $request);
|
||||
$this->userManager = $userManager;
|
||||
$this->groupManager = $groupManager;
|
||||
|
@ -165,6 +174,7 @@ class UsersController extends Controller {
|
|||
$this->keyManager = $keyManager;
|
||||
$this->jobList = $jobList;
|
||||
$this->userMountCache = $userMountCache;
|
||||
$this->encryptionManager = $encryptionManager;
|
||||
|
||||
// check for encryption state - TODO see formatUserForIndex
|
||||
$this->isEncryptionAppEnabled = $appManager->isEnabledForUser('encryption');
|
||||
|
@ -200,6 +210,17 @@ class UsersController extends Controller {
|
|||
// user also has recovery mode enabled
|
||||
$restorePossible = true;
|
||||
}
|
||||
} else {
|
||||
$modules = $this->encryptionManager->getEncryptionModules();
|
||||
$restorePossible = true;
|
||||
foreach ($modules as $id => $module) {
|
||||
/* @var IEncryptionModule $instance */
|
||||
$instance = call_user_func($module['callback']);
|
||||
if ($instance->needDetailedAccessList()) {
|
||||
$restorePossible = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// recovery is possible if encryption is disabled (plain files are
|
||||
|
|
|
@ -20,6 +20,8 @@ use OCP\AppFramework\Http\DataResponse;
|
|||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\BackgroundJob\IJobList;
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
use OCP\Encryption\IEncryptionModule;
|
||||
use OCP\Encryption\IManager;
|
||||
use OCP\IAvatar;
|
||||
use OCP\IAvatarManager;
|
||||
use OCP\IConfig;
|
||||
|
@ -82,6 +84,10 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
private $securityManager;
|
||||
/** @var IUserMountCache |\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $userMountCache;
|
||||
/** @var IManager | \PHPUnit_Framework_MockObject_MockObject */
|
||||
private $encryptionManager;
|
||||
/** @var IEncryptionModule | \PHPUnit_Framework_MockObject_MockObject */
|
||||
private $encryptionModule;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
@ -104,6 +110,7 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
$this->crypto = $this->createMock(ICrypto::class);
|
||||
$this->securityManager = $this->getMockBuilder(\OC\Security\IdentityProof\Manager::class)->disableOriginalConstructor()->getMock();
|
||||
$this->jobList = $this->createMock(IJobList::class);
|
||||
$this->encryptionManager = $this->createMock(IManager::class);
|
||||
$this->l = $this->createMock(IL10N::class);
|
||||
$this->l->method('t')
|
||||
->will($this->returnCallback(function ($text, $parameters = []) {
|
||||
|
@ -111,6 +118,10 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
}));
|
||||
$this->userMountCache = $this->createMock(IUserMountCache::class);
|
||||
|
||||
$this->encryptionModule = $this->createMock(IEncryptionModule::class);
|
||||
$this->encryptionManager->expects($this->any())->method('getEncryptionModules')
|
||||
->willReturn(['encryptionModule' => ['callback' => function() { return $this->encryptionModule;}]]);
|
||||
|
||||
/*
|
||||
* Set default avatar behaviour for whole test suite
|
||||
*/
|
||||
|
@ -154,8 +165,8 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
$this->crypto,
|
||||
$this->securityManager,
|
||||
$this->jobList,
|
||||
$this->userMountCache
|
||||
|
||||
$this->userMountCache,
|
||||
$this->encryptionManager
|
||||
);
|
||||
} else {
|
||||
return $this->getMockBuilder(UsersController::class)
|
||||
|
@ -182,6 +193,7 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
$this->securityManager,
|
||||
$this->jobList,
|
||||
$this->userMountCache,
|
||||
$this->encryptionManager
|
||||
]
|
||||
)->setMethods($mockedMethods)->getMock();
|
||||
}
|
||||
|
@ -1689,9 +1701,17 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
$this->assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
public function testRestoreNotPossibleWithoutAdminRestore() {
|
||||
/**
|
||||
* @dataProvider dataTestRestoreNotPossibleWithoutAdminRestore
|
||||
*
|
||||
* @param bool $masterKeyEnabled
|
||||
*/
|
||||
public function testRestoreNotPossibleWithoutAdminRestore($masterKeyEnabled) {
|
||||
list($user, $expectedResult) = $this->mockUser();
|
||||
|
||||
// without the master key enabled we use per-user keys
|
||||
$this->encryptionModule->expects($this->once())->method('needDetailedAccessList')->willReturn(!$masterKeyEnabled);
|
||||
|
||||
$this->appManager
|
||||
->method('isEnabledForUser')
|
||||
->with(
|
||||
|
@ -1699,7 +1719,8 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
)
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$expectedResult['isRestoreDisabled'] = true;
|
||||
// without the master key enabled we use per-user keys -> restore is disabled
|
||||
$expectedResult['isRestoreDisabled'] = !$masterKeyEnabled;
|
||||
|
||||
$subadmin = $this->getMockBuilder('\OC\SubAdmin')
|
||||
->disableOriginalConstructor()
|
||||
|
@ -1718,6 +1739,13 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
$this->assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
public function dataTestRestoreNotPossibleWithoutAdminRestore() {
|
||||
return [
|
||||
[true],
|
||||
[false]
|
||||
];
|
||||
}
|
||||
|
||||
public function testRestoreNotPossibleWithoutUserRestore() {
|
||||
list($user, $expectedResult) = $this->mockUser();
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ class EncryptionTest extends Storage {
|
|||
protected function buildMockModule() {
|
||||
$this->encryptionModule = $this->getMockBuilder('\OCP\Encryption\IEncryptionModule')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(['getId', 'getDisplayName', 'begin', 'end', 'encrypt', 'decrypt', 'update', 'shouldEncrypt', 'getUnencryptedBlockSize', 'isReadable', 'encryptAll', 'prepareDecryptAll', 'isReadyForUser'])
|
||||
->setMethods(['getId', 'getDisplayName', 'begin', 'end', 'encrypt', 'decrypt', 'update', 'shouldEncrypt', 'getUnencryptedBlockSize', 'isReadable', 'encryptAll', 'prepareDecryptAll', 'isReadyForUser', 'needDetailedAccessList'])
|
||||
->getMock();
|
||||
|
||||
$this->encryptionModule->expects($this->any())->method('getId')->willReturn('UNIT_TEST_MODULE');
|
||||
|
@ -225,6 +225,7 @@ class EncryptionTest extends Storage {
|
|||
$this->encryptionModule->expects($this->any())->method('shouldEncrypt')->willReturn(true);
|
||||
$this->encryptionModule->expects($this->any())->method('getUnencryptedBlockSize')->willReturn(8192);
|
||||
$this->encryptionModule->expects($this->any())->method('isReadable')->willReturn(true);
|
||||
$this->encryptionModule->expects($this->any())->method('needDetailedAccessList')->willReturn(false);
|
||||
return $this->encryptionModule;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,8 @@ class EncryptionTest extends \Test\TestCase {
|
|||
/**
|
||||
* @dataProvider dataProviderStreamOpen()
|
||||
*/
|
||||
public function testStreamOpen($mode,
|
||||
public function testStreamOpen($isMasterKeyUsed,
|
||||
$mode,
|
||||
$fullPath,
|
||||
$fileExists,
|
||||
$expectedSharePath,
|
||||
|
@ -69,6 +70,7 @@ class EncryptionTest extends \Test\TestCase {
|
|||
// build mocks
|
||||
$encryptionModuleMock = $this->getMockBuilder('\OCP\Encryption\IEncryptionModule')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$encryptionModuleMock->expects($this->any())->method('needDetailedAccessList')->willReturn(!$isMasterKeyUsed);
|
||||
$encryptionModuleMock->expects($this->once())
|
||||
->method('getUnencryptedBlockSize')->willReturn(99);
|
||||
$encryptionModuleMock->expects($this->once())
|
||||
|
@ -80,12 +82,15 @@ class EncryptionTest extends \Test\TestCase {
|
|||
|
||||
$fileMock = $this->getMockBuilder('\OC\Encryption\File')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
if ($isMasterKeyUsed) {
|
||||
$fileMock->expects($this->never())->method('getAccessList');
|
||||
} else {
|
||||
$fileMock->expects($this->once())->method('getAccessList')
|
||||
->will($this->returnCallback(function ($sharePath) use ($expectedSharePath) {
|
||||
$this->assertSame($expectedSharePath, $sharePath);
|
||||
return array();
|
||||
}));
|
||||
|
||||
}
|
||||
$utilMock = $this->getMockBuilder('\OC\Encryption\Util')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$utilMock->expects($this->any())
|
||||
|
@ -152,11 +157,14 @@ class EncryptionTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function dataProviderStreamOpen() {
|
||||
return array(
|
||||
array('r', '/foo/bar/test.txt', true, '/foo/bar/test.txt', null, null, true),
|
||||
array('r', '/foo/bar/test.txt', false, '/foo/bar', null, null, true),
|
||||
array('w', '/foo/bar/test.txt', true, '/foo/bar/test.txt', 8192, 0, false),
|
||||
);
|
||||
return [
|
||||
[false, 'r', '/foo/bar/test.txt', true, '/foo/bar/test.txt', null, null, true],
|
||||
[false, 'r', '/foo/bar/test.txt', false, '/foo/bar', null, null, true],
|
||||
[false, 'w', '/foo/bar/test.txt', true, '/foo/bar/test.txt', 8192, 0, false],
|
||||
[true, 'r', '/foo/bar/test.txt', true, '/foo/bar/test.txt', null, null, true],
|
||||
[true, 'r', '/foo/bar/test.txt', false, '/foo/bar', null, null, true],
|
||||
[true, 'w', '/foo/bar/test.txt', true, '/foo/bar/test.txt', 8192, 0, false],
|
||||
];
|
||||
}
|
||||
|
||||
public function testWriteRead() {
|
||||
|
@ -311,7 +319,7 @@ class EncryptionTest extends \Test\TestCase {
|
|||
protected function buildMockModule() {
|
||||
$encryptionModule = $this->getMockBuilder('\OCP\Encryption\IEncryptionModule')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(['getId', 'getDisplayName', 'begin', 'end', 'encrypt', 'decrypt', 'update', 'shouldEncrypt', 'getUnencryptedBlockSize', 'isReadable', 'encryptAll', 'prepareDecryptAll', 'isReadyForUser'])
|
||||
->setMethods(['getId', 'getDisplayName', 'begin', 'end', 'encrypt', 'decrypt', 'update', 'shouldEncrypt', 'getUnencryptedBlockSize', 'isReadable', 'encryptAll', 'prepareDecryptAll', 'isReadyForUser', 'needDetailedAccessList'])
|
||||
->getMock();
|
||||
|
||||
$encryptionModule->expects($this->any())->method('getId')->willReturn('UNIT_TEST_MODULE');
|
||||
|
@ -319,6 +327,7 @@ class EncryptionTest extends \Test\TestCase {
|
|||
$encryptionModule->expects($this->any())->method('begin')->willReturn([]);
|
||||
$encryptionModule->expects($this->any())->method('end')->willReturn('');
|
||||
$encryptionModule->expects($this->any())->method('isReadable')->willReturn(true);
|
||||
$encryptionModule->expects($this->any())->method('needDetailedAccessList')->willReturn(false);
|
||||
$encryptionModule->expects($this->any())->method('encrypt')->willReturnCallback(function($data) {
|
||||
// simulate different block size by adding some padding to the data
|
||||
if (isset($data[6125])) {
|
||||
|
|
|
@ -64,6 +64,7 @@ trait EncryptionTrait {
|
|||
/** @var Setup $userSetup */
|
||||
$userSetup = $container->query('UserSetup');
|
||||
$userSetup->setupUser($name, $password);
|
||||
$this->encryptionApp->setUp();
|
||||
$keyManager->init($name, $password);
|
||||
}
|
||||
|
||||
|
@ -99,6 +100,7 @@ trait EncryptionTrait {
|
|||
if ($this->config) {
|
||||
$this->config->setAppValue('core', 'encryption_enabled', $this->encryptionWasEnabled);
|
||||
$this->config->setAppValue('core', 'default_encryption_module', $this->originalEncryptionModule);
|
||||
$this->config->deleteAppValue('encryption', 'useMasterKey');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue