diff --git a/lib/Command/RecreateMasterKey.php b/lib/Command/RecreateMasterKey.php index 11d3d31c..1b8fa3f0 100644 --- a/lib/Command/RecreateMasterKey.php +++ b/lib/Command/RecreateMasterKey.php @@ -21,25 +21,13 @@ namespace OCA\Encryption\Command; -use OC\Encryption\DecryptAll; -use OC\Encryption\Manager; use OC\Files\View; -use OCA\Encryption\Crypto\EncryptAll; -use OCA\Encryption\KeyManager; -use OCA\Encryption\Users\Setup; +use OCA\Encryption\Factory\EncDecAllFactory; use OCA\Encryption\Util; use OCP\App\IAppManager; use OCP\IAppConfig; -use OCP\IConfig; -use OCP\IL10N; -use OCP\ILogger; -use OCP\ISession; -use OCP\IUserManager; -use OCP\Mail\IMailer; -use OCP\Security\ISecureRandom; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\ProgressBar; -use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -47,18 +35,9 @@ class RecreateMasterKey extends Command { - /** @var Manager */ - protected $encryptionManager; - - /** @var IUserManager */ - protected $userManager; - /** @var View */ protected $rootView; - /** @var KeyManager */ - protected $keyManager; - /** @var Util */ protected $util; @@ -71,34 +50,8 @@ class RecreateMasterKey extends Command { /** @var IAppConfig */ protected $appConfig; - /** @var IConfig */ - protected $config; - - /** @var ISession */ - protected $session; - - /** @var QuestionHelper */ - protected $questionHelper; - - /** @var Setup */ - protected $userSetup; - - /** @var IMailer */ - protected $mailer; - - /** @var ISecureRandom */ - protected $secureRandom; - - /** @var IL10N */ - protected $l; - - /** @var ILogger */ - protected $logger; - - /** @var */ - protected $encryptAll; - - protected $decryptAll; + /** @var EncDecAllFactory */ + private $encDecAllFactory; /** @var array files which couldn't be decrypted */ protected $failed; @@ -106,42 +59,23 @@ class RecreateMasterKey extends Command { /** * RecreateMasterKey constructor. * - * @param IUserManager $userManager * @param View $rootView - * @param KeyManager $keyManager * @param Util $util + * @param \OC\Encryption\Util $encUtil * @param IAppManager $appManager * @param IAppConfig $appConfig - * @param IConfig $config - * @param ISession $session - * @param QuestionHelper $questionHelper - * @param Setup $userSetup - * @param IMailer $mailer - * @param ISecureRandom $secureRandom - * @param IL10N $l - * @param ILogger $logger + * @param EncDecAllFactory $encDecAllFactory */ - public function __construct(IUserManager $userManager, View $rootView, KeyManager $keyManager, Util $util, \OC\Encryption\Util $encUtil, - IAppManager $appManager, IAppConfig $appConfig, IConfig $config, ISession $session, - Manager $encryptionManager, QuestionHelper $questionHelper, Setup $userSetup, IMailer $mailer, - ISecureRandom $secureRandom, IL10N $l, ILogger $logger) { + public function __construct(View $rootView, Util $util, \OC\Encryption\Util $encUtil, + IAppManager $appManager, IAppConfig $appConfig, + EncDecAllFactory $encDecAllFactory) { parent::__construct(); - $this->userManager = $userManager; $this->rootView = $rootView; - $this->keyManager = $keyManager; $this->util = $util; $this->encUtil = $encUtil; $this->appManager = $appManager; $this->appConfig = $appConfig; - $this->config = $config; - $this->session = $session; - $this->encryptionManager = $encryptionManager; - $this->questionHelper = $questionHelper; - $this->userSetup = $userSetup; - $this->mailer = $mailer; - $this->secureRandom = $secureRandom; - $this->l = $l; - $this->logger = $logger; + $this->encDecAllFactory = $encDecAllFactory; } protected function configure() { @@ -166,14 +100,18 @@ protected function execute(InputInterface $input, OutputInterface $output) { $question = new ConfirmationQuestion( 'Warning: In order to re-create master key, the entire ownCloud filesystem will be decrypted and then encrypted using new master key.' . ' Do you want to continue? (y/n)', false); - if ($yes || $this->questionHelper->ask($input, $output, $question)) { + //$questionHelper = $this->getHelper('question'); + if ($yes || $this->getHelper('question')->ask($input, $output, $question)) { $output->writeln("Decryption started\n"); $progress = new ProgressBar($output); $progress->start(); $progress->setMessage("Decryption in progress..."); $progress->advance(); - $this->decryptAllUsers($input, $output); + //Get DecryptAll object from the factory + $decryptAll = $this->encDecAllFactory->getDecryptAllObj(); + $decryptAll->decryptAll($input, $output); + $progress->finish(); if (empty($this->failed)) { @@ -187,69 +125,44 @@ protected function execute(InputInterface $input, OutputInterface $output) { $this->rootView->deleteAll($filesEncryptionDir . '/files_encryption'); } - $this->appConfig->setValue('core', 'encryption_enabled', 'no'); - $this->appConfig->deleteKey('encryption', 'useMasterKey'); - $this->appConfig->deleteKey('encryption', 'masterKeyId'); - $this->appConfig->deleteKey('encryption', 'recoveryKeyId'); - $this->appConfig->deleteKey('encryption', 'publicShareKeyId'); - $this->appConfig->deleteKey('files_encryption', 'installed_version'); + $this->util->removeEncryptionAppSettings(); } $output->writeln("\nDecryption completed\n"); //Reencrypt again $this->appManager->enableApp('encryption'); $this->appConfig->setValue('core', 'encryption_enabled', 'yes'); - $this->appConfig->setValue('encryption', 'enabled', 'yes'); - $output->writeln("Encryption started\n"); + $this->appConfig->setValue('encryption', 'useMasterKey', '1'); $output->writeln("Waiting for creating new masterkey\n"); - $this->keyManager->setPublicShareKeyIDAndMasterKeyId(); - + //Get the EncryptAll object from factory + $encryptAll = $this->encDecAllFactory->getEncryptAllObj(); + if ($encryptAll->createMasterKey($input, $output) === false) { + $output->writeln("Error: masterkeys creation failed"); + return 1; + } $output->writeln("New masterkey created successfully\n"); - $this->appConfig->setValue('encryption', 'enabled', 'yes'); - $this->appConfig->setValue('encryption', 'useMasterKey', '1'); - - /** - * Call validateShareKey method, to check if public share exists, - * else create one. - */ - $this->keyManager->validateShareKey(); + $output->writeln("Encryption started\n"); /** - * Same here, check if public masterkey exists else - * create one. + * We are reusing the encryptAll code but not the decryptAll. The reason being + * decryptAll finishes by encrypting. Which is not what we want. This will make + * things out of scope for this command. We want first the entire oC FS to be + * decrypt. Then re-encrypt the entire oC FS with the new master key generated. */ - $this->keyManager->validateMasterKey(); - $this->encryptAllUsers($input, $output); + $encryptAll->encryptAll($input, $output); + $output->writeln("\nEncryption completed successfully\n"); $output->writeln("\nNote: All users are required to relogin.\n"); + return 0; } else { $output->writeln("The process is abandoned"); + return 2; } } else { $output->writeln("Master key is not enabled.\n"); + return 3; } } - - protected function decryptAllUsers(InputInterface $input, OutputInterface $output) { - $this->decryptAll = new DecryptAll($this->encryptionManager, $this->userManager, $this->rootView, $this->logger); - $this->decryptAll->decryptAll($input, $output); - } - - protected function encryptAllUsers(InputInterface $input, OutputInterface $output) { - /* - * We are reusing the encryptAll code but not the decryptAll. The reason being - * decryptAll finishes by encrypting. Which is not what we want. This will make - * things out of scope for this command. We want first the entire oC FS to be - * decrypt. Then re-encrypt the entire oC FS with the new master key generated. - * - */ - $this->encryptAll = new EncryptAll( - $this->userSetup, $this->userManager, $this->rootView, - $this->keyManager, $this->util, $this->config, - $this->mailer, $this->l, $this->questionHelper, - $this->secureRandom); - $this->encryptAll->encryptAll($input, $output); - } } diff --git a/lib/Crypto/EncryptAll.php b/lib/Crypto/EncryptAll.php index 24513bd9..6733be91 100644 --- a/lib/Crypto/EncryptAll.php +++ b/lib/Crypto/EncryptAll.php @@ -119,6 +119,27 @@ public function __construct( $this->userPasswords = []; } + /** + * Call this method only when no master key is created. + * + * @return bool true when masterkey and sharekey is created else false + */ + public function createMasterKey() { + $this->keyManager->setPublicShareKeyIDAndMasterKeyId(); + + /** + * Call validateShareKey method, to check if public share exists, + * else create one. + */ + $this->keyManager->validateShareKey(); + /** + * Same here, check if public masterkey exists else + * create one. + */ + $this->keyManager->validateMasterKey(); + return (!empty($this->keyManager->getPublicShareKey()) && !empty($this->keyManager->getPublicMasterKey())); + } + /** * start to encrypt all files * diff --git a/lib/Factory/EncDecAllFactory.php b/lib/Factory/EncDecAllFactory.php new file mode 100644 index 00000000..46243caa --- /dev/null +++ b/lib/Factory/EncDecAllFactory.php @@ -0,0 +1,171 @@ + + * + * @copyright Copyright (c) 2019, ownCloud GmbH + * @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 + * + */ + +namespace OCA\Encryption\Factory; + +use OC\Encryption\DecryptAll; +use OC\Encryption\Manager; +use OC\Files\View; +use OCA\Encryption\Crypto\Crypt; +use OCA\Encryption\Crypto\CryptHSM; +use OCA\Encryption\Crypto\EncryptAll; +use OCA\Encryption\KeyManager; +use OCA\Encryption\Session; +use OCA\Encryption\Users\Setup; +use OCA\Encryption\Util; +use OCP\Encryption\Keys\IStorage; +use OCP\IConfig; +use OCP\IL10N; +use OCP\ILogger; +use OCP\IUserManager; +use OCP\IUserSession; +use OCP\Mail\IMailer; +use OCP\Security\ISecureRandom; +use Symfony\Component\Console\Helper\QuestionHelper; + +class EncDecAllFactory { + /** @var Manager */ + private $encryptionManager; + + /** @var IUserManager */ + private $userManager; + + /** @var ILogger */ + private $logger; + + /** @var Util */ + private $encUtil; + + /** @var IConfig */ + private $config; + + /** @var IMailer */ + private $mailer; + + /** @var IL10N */ + private $l10n; + + /** @var QuestionHelper */ + private $questionHelper; + + /** @var ISecureRandom */ + private $secureRandom; + + /** @var IStorage */ + private $encStorage; + + /** @var IUserSession */ + private $userSession; + + /** @var Session */ + private $encSession; + + /** @var CryptHSM */ + private $cryptHSM; + + /** @var Crypt */ + private $crypt; + + /** + * EncDecAllFactory constructor. + * + * @param Manager $encryptionManager + * @param IUserManager $userManager + * @param ILogger $logger + * @param Util $encUtil + * @param IConfig $config + * @param IMailer $mailer + * @param IL10N $l10n + * @param QuestionHelper $questionHelper + * @param ISecureRandom $secureRandom + * @param IStorage $encStorage + * @param Session $encSession + * @param CryptHSM $cryptHSM + * @param Crypt $crypt + * @param IUserSession $userSession + */ + public function __construct(Manager $encryptionManager, IUserManager $userManager, + ILogger $logger, Util $encUtil, IConfig $config, IMailer $mailer, + IL10N $l10n, QuestionHelper $questionHelper, ISecureRandom $secureRandom, + IStorage $encStorage, Session $encSession, CryptHSM $cryptHSM, + Crypt $crypt, IUserSession $userSession) { + $this->encryptionManager = $encryptionManager; + $this->userManager = $userManager; + $this->logger = $logger; + $this->encUtil = $encUtil; + $this->config = $config; + $this->mailer = $mailer; + $this->l10n = $l10n; + $this->questionHelper = $questionHelper; + $this->secureRandom = $secureRandom; + $this->encStorage = $encStorage; + $this->encSession = $encSession; + $this->cryptHSM = $cryptHSM; + $this->crypt = $crypt; + $this->userSession = $userSession; + } + + /** + * Returns DecryptAll object + * + * @return DecryptAll + */ + public function getDecryptAllObj() { + $rootView = new View("/"); + return new DecryptAll($this->encryptionManager, $this->userManager, $rootView, $this->logger); + } + + /** + * Returns EncryptAll object + * + * @return EncryptAll + */ + public function getEncryptAllObj() { + $rootView = new View("/"); + + /** + * The new KeyManager object is used here because of two reasons: + * 1. Setup class depends on KeyManager, which depends on crypto engine + * 2. EncryptAll also depends on KeyManager, which depends on crypto engine + */ + $keyManager = new KeyManager($this->encStorage, $this->getCryptoEngine(), + $this->config, $this->userSession, $this->encSession, $this->logger, + $this->encUtil); + $userSetup = new Setup($this->logger, $this->userSession, $this->getCryptoEngine(), $keyManager); + return new EncryptAll($userSetup, $this->userManager, $rootView, + $keyManager, $this->encUtil, $this->config, $this->mailer, $this->l10n, + $this->questionHelper, $this->secureRandom); + } + + /** + * Returns CryptHSM if crypto engine set to + * hsm else returns Crypt + * + * @return Crypt|CryptHSM + */ + private function getCryptoEngine() { + if ($this->config->getAppValue('crypto.engine', 'internal', '') === 'hsm') { + return $this->cryptHSM; + } + + return $this->crypt; + } +} diff --git a/lib/Util.php b/lib/Util.php index 4f797a7a..dcf3582a 100644 --- a/lib/Util.php +++ b/lib/Util.php @@ -194,4 +194,16 @@ public function getStorage($path) { $storage = $this->files->getMount($path)->getStorage(); return $storage; } + + /** + * Deletes the encryption settings for the masterkey + */ + public function removeEncryptionAppSettings() { + $this->config->setAppValue('core', 'encryption_enabled', 'no'); + $this->config->deleteAppValue('encryption', 'useMasterKey'); + $this->config->deleteAppValue('encryption', 'masterKeyId'); + $this->config->deleteAppValue('encryption', 'recoveryKeyId'); + $this->config->deleteAppValue('encryption', 'publicShareKeyId'); + $this->config->deleteAppValue('files_encryption', 'installed_version'); + } } diff --git a/tests/unit/Command/RecreateMasterKeyTest.php b/tests/unit/Command/RecreateMasterKeyTest.php index 4d320aa9..8650ac94 100644 --- a/tests/unit/Command/RecreateMasterKeyTest.php +++ b/tests/unit/Command/RecreateMasterKeyTest.php @@ -21,108 +21,70 @@ namespace OCA\Encryption\Tests\Command; +use OC\Encryption\DecryptAll; use OC\Files\View; use OCA\Encryption\Command\RecreateMasterKey; -use OCA\Encryption\Users\Setup; -use OCP\IL10N; -use OCP\Mail\IMailer; -use OCP\Security\ISecureRandom; +use OCA\Encryption\Crypto\EncryptAll; +use OCA\Encryption\Factory\EncDecAllFactory; +use OCA\Encryption\Util; +use OCP\App\IAppManager; +use OCP\IAppConfig; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; use Test\TestCase; -class RecreateMasterKeyTest extends TestCase { - - /** @var Manager | \PHPUnit\Framework\MockObject\MockObject */ - protected $encryptionManager; +/** + * Class RecreateMasterKeyTest + * + * @package OCA\Encryption\Tests\Command + */ - /** @var IUserManager | \PHPUnit\Framework\MockObject\MockObject */ - protected $userManager; +class RecreateMasterKeyTest extends TestCase { /** @var View | \PHPUnit\Framework\MockObject\MockObject */ protected $rootView; - /** @var KeyManager | \PHPUnit\Framework\MockObject\MockObject */ - protected $keyManager; - /** @var Util | \PHPUnit\Framework\MockObject\MockObject */ protected $util; + /** @var \OC\Encryption\Util | \PHPUnit\Framework\MockObject\MockObject */ protected $encUitl; /** @var IAppManager | \PHPUnit\Framework\MockObject\MockObject */ - protected $IAppManager; + protected $appManager; /** @var IAppConfig | \PHPUnit\Framework\MockObject\MockObject */ protected $appConfig; - /** @var IConfig | \PHPUnit\Framework\MockObject\MockObject */ - protected $config; - - /** @var ISession | \PHPUnit\Framework\MockObject\MockObject */ - protected $session; - - /** @var \PHPUnit\Framework\MockObject\MockObject | \OCP\UserInterface */ - protected $userInterface; - /** @var \Symfony\Component\Console\Output\OutputInterface | \PHPUnit\Framework\MockObject\MockObject */ protected $output; /** @var \Symfony\Component\Console\Input\InputInterface | \PHPUnit\Framework\MockObject\MockObject */ protected $input; - protected $questionHelper; - - protected $userSetup; - - protected $mailer; - - protected $secureRandom; - - protected $l; - - protected $logger; - - protected $progressbar; - - protected $setupfs; + /** @var EncDecAllFactory | \PHPUnit\Framework\MockObject\MockObject */ + private $encdecAllFactory; /** @var RecreateMasterKey */ protected $recreateMasterKey; + private $commandTester; + public function setUp() { parent::setUp(); - $this->encryptionManager = $this->getMockBuilder('OC\Encryption\Manager') - ->disableOriginalConstructor()->getMock(); - $this->userManager = $this->getMockBuilder('OCP\IUserManager') - ->disableOriginalConstructor()->getMock(); $this->rootView = $this->getMockBuilder('OC\Files\View') ->disableOriginalConstructor()->getMock(); - $this->keyManager = $this->getMockBuilder('OCA\Encryption\KeyManager') - ->disableOriginalConstructor()->getMock(); $this->util = $this->getMockBuilder('OCA\Encryption\Util') ->disableOriginalConstructor()->getMock(); $this->encUitl = $this->getMockBuilder('OC\Encryption\Util') ->disableOriginalConstructor()->getMock(); - $this->IAppManager = $this->getMockBuilder('OCP\App\IAppManager') + $this->appManager = $this->getMockBuilder('OCP\App\IAppManager') ->disableOriginalConstructor()->getMock(); $this->appConfig = $this->getMockBuilder('OCP\IAppConfig') ->disableOriginalConstructor()->getMock(); - $this->config = $this->getMockBuilder('OCP\IConfig') - ->disableOriginalConstructor()->getMock(); - $this->session = $this->getMockBuilder('OCP\ISession') - ->disableOriginalConstructor()->getMock(); $this->questionHelper = $this->getMockBuilder('Symfony\Component\Console\Helper\QuestionHelper') ->disableOriginalConstructor()->getMock(); - $this->userSetup = $this->getMockBuilder(Setup::class) - ->disableOriginalConstructor()->getMock(); - $this->mailer = $this->getMockBuilder(IMailer::class) - ->disableOriginalConstructor()->getMock(); - $this->secureRandom = $this->getMockBuilder(ISecureRandom::class) - ->disableOriginalConstructor()->getMock(); - $this->l = $this->getMockBuilder(IL10N::class) - ->disableOriginalConstructor()->getMock(); - $this->logger = $this->getMockBuilder('OCP\ILogger') - ->disableOriginalConstructor()->getMock(); $this->input = $this->getMockBuilder('Symfony\Component\Console\Input\InputInterface') ->disableOriginalConstructor()->getMock(); $this->output = $this->getMockBuilder('Symfony\Component\Console\Output\OutputInterface') @@ -134,106 +96,91 @@ public function setUp() { $this->output->expects($this->any())->method('getFormatter') ->willReturn($this->createMock('\Symfony\Component\Console\Formatter\OutputFormatterInterface')); - $this->recreateMasterKey = new RecreateMasterKey($this->userManager, - $this->rootView, $this->keyManager, $this->util, $this->encUitl, - $this->IAppManager, $this->appConfig, $this->config, $this->session, - $this->encryptionManager, $this->questionHelper, - $this->userSetup, $this->mailer, $this->secureRandom, $this->l, $this->logger); + $this->encdecAllFactory = $this->createMock(EncDecAllFactory::class); + + $recreateMasterKeyCommand = new RecreateMasterKey($this->rootView, $this->util, + $this->encUitl, $this->appManager, $this->appConfig, $this->encdecAllFactory); - $this->invokePrivate($this->recreateMasterKey, 'input', [$this->input]); - $this->invokePrivate($this->recreateMasterKey, 'output', [$this->output]); + $this->commandTester = new CommandTester($recreateMasterKeyCommand); } - /** - * @dataProvider dataTestExecute - */ - public function testNewMasterKey($mastkerKeyEnabled) { - if ($mastkerKeyEnabled === true) { - $this->recreateMasterKey = $this->getMockBuilder('OCA\Encryption\Command\RecreateMasterKey') - ->setConstructorArgs( - [ - $this->userManager, - $this->rootView, $this->keyManager, $this->util, $this->encUitl, - $this->IAppManager, $this->appConfig, $this->config, $this->session, - $this->encryptionManager, $this->questionHelper, - $this->userSetup, $this->mailer, $this->secureRandom, $this->l, - $this->logger - ] - )->setMethods(['setupUserFS', 'encryptAllUsers', 'decryptAllUsers'])->getMock(); - - $this->questionHelper->expects($this->once())->method('ask') - ->willReturn(true); - - $this->util->expects($this->any())->method('isMasterKeyEnabled') - ->willReturn(true); - - $this->userManager->expects($this->any()) - ->method('getBackends') - ->willReturn([$this->userInterface]); - - $this->userInterface->expects($this->any()) - ->method('getUsers') - ->willReturn(['user1']); - - $this->rootView->expects($this->any())->method('is_dir') - ->willReturnCallback( - function ($path) { - if ($path === '/user1/files/foo') { - return true; - } - return false; - } - ); - - $this->encryptionManager->expects($this->any()) - ->method('isReadyForUser') - ->with('user1') - ->willReturn(true); - - $this->output->method('writeln') - ->will($this->onConsecutiveCalls( - "Decryption started\n", - "\nDecryption completed\n", - "Encryption started\n", - "Waiting for creating new masterkey\n", - "New masterkey created successfully\n", - "\nEncryption completed successfully\n", - "\n\Note: All users are required to relogin.\\n" - )); - $this->invokePrivate($this->recreateMasterKey, 'execute', [$this->input, $this->output]); - } else { - $this->recreateMasterKey = $this->getMockBuilder('OCA\Encryption\Command\RecreateMasterKey') - ->setConstructorArgs( - [ - $this->userManager, - $this->rootView, $this->keyManager, $this->util, $this->encUitl, - $this->IAppManager, $this->appConfig, $this->config, - $this->session, $this->encryptionManager, $this->questionHelper, - $this->userSetup, $this->mailer, $this->secureRandom, $this->l, - $this->logger - ] - )->setMethods(['setupUserFS'])->getMock(); - - $this->util->expects($this->once())->method('isMasterKeyEnabled') - ->willReturn($mastkerKeyEnabled); - - global $outputText; - $this->output->expects($this->at(0)) - ->method('writeln') - ->willReturnCallback(function ($value) { - global $outputText; - $outputText .= $value . "\n"; - }); - - $this->invokePrivate($this->recreateMasterKey, 'execute', [$this->input, $this->output]); - $this->assertSame("Master key is not enabled.", \trim($outputText, "\n")); - } + public function testRecreateMasterKey() { + $this->util->method('isMasterKeyEnabled') + ->willReturn(true); + + $decryptAll = $this->createMock(DecryptAll::class); + $decryptAll->expects($this->once()) + ->method('decryptAll'); + + $encryptAll = $this->createMock(EncryptAll::class); + $encryptAll->method('createMasterKey') + ->willReturn(true); + $encryptAll->expects($this->once()) + ->method('encryptAll'); + + $this->encdecAllFactory->method('getDecryptAllObj') + ->willReturn($decryptAll); + $this->encdecAllFactory->method('getEncryptAllObj') + ->willReturn($encryptAll); + + $this->commandTester->execute([ + '--yes' => 'y' + ]); + + $this->assertEquals(0, $this->commandTester->getStatusCode()); } - public function dataTestExecute() { - return [ - [true], - [false] - ]; + public function testMasterKeyRecreateFailed() { + $this->util->method('isMasterKeyEnabled') + ->willReturn(true); + + $decryptAll = $this->createMock(DecryptAll::class); + $decryptAll->expects($this->once()) + ->method('decryptAll'); + + $encryptAll = $this->createMock(EncryptAll::class); + $encryptAll->method('createMasterKey') + ->willReturn(false); + + $this->encdecAllFactory->method('getDecryptAllObj') + ->willReturn($decryptAll); + $this->encdecAllFactory->method('getEncryptAllObj') + ->willReturn($encryptAll); + + $this->commandTester->execute([ + '--yes' => 'y' + ]); + + $this->assertEquals(1, $this->commandTester->getStatusCode()); + } + + public function testMasterKeyNotEnabled() { + $this->util->method('isMasterKeyEnabled') + ->willReturn(false); + + $this->commandTester->execute([ + '--yes' => 'y' + ]); + + $this->assertEquals(3, $this->commandTester->getStatusCode()); + } + + public function testAbandonProcess() { + $this->util->method('isMasterKeyEnabled') + ->willReturn(true); + + $application = new Application(); + $recreateCmd = new RecreateMasterKey($this->rootView, $this->util, + $this->encUitl, $this->appManager, $this->appConfig, $this->encdecAllFactory); + $application->add($recreateCmd); + + $command = $application->find('encryption:recreate-master-key'); + + $commandTester = new CommandTester($command); + + $commandTester->setInputs(['n']); + + $commandTester->execute([]); + $this->assertEquals(2, $commandTester->getStatusCode()); } } diff --git a/tests/unit/Crypto/EncryptAllTest.php b/tests/unit/Crypto/EncryptAllTest.php index 5e52f08e..a2d071e9 100644 --- a/tests/unit/Crypto/EncryptAllTest.php +++ b/tests/unit/Crypto/EncryptAllTest.php @@ -441,4 +441,34 @@ public function testEncryptAlreadyEncryptedFile() { $result = $this->invokePrivate($this->encryptAll, 'encryptFile', ['/user1/files/bar.txt']); $this->assertFalse($result); } + + /** + * @dataProvider providesCreateMasterKeyData + * @param bool $isShareKeySet + * @param bool $isMasterkeySet + * @param bool $expectedResult + */ + public function testCreateMasterKey($isShareKeySet, $isMasterkeySet, $expectedResult) { + $this->keyManager->expects($this->once()) + ->method('setPublicShareKeyIDAndMasterKeyId'); + $this->keyManager->expects($this->once()) + ->method('validateShareKey'); + $this->keyManager->expects($this->once()) + ->method('validateMasterKey'); + $this->keyManager->method('getPublicShareKey') + ->willReturn($isShareKeySet); + $this->keyManager->method('getPublicMasterKey') + ->willReturn($isMasterkeySet); + $returnVal = $this->encryptAll->createMasterKey(); + $this->assertEquals($expectedResult, $returnVal); + } + + public function providesCreateMasterKeyData() { + return [ + [true, false, false], + [true, true, true], + [false, true, false], + [false, false, false], + ]; + } } diff --git a/tests/unit/Factory/EncDecAllFactoryTest.php b/tests/unit/Factory/EncDecAllFactoryTest.php new file mode 100644 index 00000000..f40d37e9 --- /dev/null +++ b/tests/unit/Factory/EncDecAllFactoryTest.php @@ -0,0 +1,117 @@ + + * + * @copyright Copyright (c) 2019, ownCloud GmbH + * @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 + * + */ + +namespace OCA\Encryption\Tests\Factory; + +use OC\Encryption\DecryptAll; +use OC\Encryption\Manager; +use OC\Files\View; +use OCA\Encryption\Crypto\Crypt; +use OCA\Encryption\Crypto\CryptHSM; +use OCA\Encryption\Crypto\EncryptAll; +use OCA\Encryption\Factory\EncDecAllFactory; +use OCA\Encryption\Session; +use OCA\Encryption\Util; +use OCP\Encryption\Keys\IStorage; +use OCP\IConfig; +use OCP\IL10N; +use OCP\ILogger; +use OCP\IUserManager; +use OCP\IUserSession; +use OCP\Mail\IMailer; +use OCP\Security\ISecureRandom; +use Symfony\Component\Console\Helper\QuestionHelper; +use Test\TestCase; + +class EncDecAllFactoryTest extends TestCase { + private $encryptionManager; + private $userManager; + private $rootView; + private $logger; + private $encUtil; + private $config; + private $mailer; + private $l10n; + private $questionHelper; + private $secureRandom; + private $encStorage; + private $encSession; + private $cryptHSM; + private $crypt; + private $userSession; + private $encdecAllFactory; + + public function setUp() { + parent::setUp(); + + $this->encryptionManager = $this->createMock(Manager::class); + $this->userManager = $this->createMock(IUserManager::class); + $this->rootView = $this->createMock(View::class); + $this->logger = $this->createMock(ILogger::class); + $this->encUtil = $this->createMock(Util::class); + $this->config = $this->createMock(IConfig::class); + $this->mailer = $this->createMock(IMailer::class); + $this->l10n = $this->createMock(IL10N::class); + $this->questionHelper = $this->createMock(QuestionHelper::class); + $this->secureRandom = $this->createMock(ISecureRandom::class); + $this->encStorage = $this->createMock(IStorage::class); + $this->encSession = $this->createMock(Session::class); + $this->cryptHSM = $this->createMock(CryptHSM::class); + $this->crypt = $this->createMock(Crypt::class); + $this->userSession = $this->createMock(IUserSession::class); + $this->encdecAllFactory = new EncDecAllFactory($this->encryptionManager, + $this->userManager, $this->logger, $this->encUtil, $this->config, + $this->mailer, $this->l10n, $this->questionHelper, $this->secureRandom, + $this->encStorage, $this->encSession, $this->cryptHSM, $this->crypt, + $this->userSession); + } + + public function testGetDecryptAllObj() { + $decAllObj = $this->encdecAllFactory->getDecryptAllObj(); + $this->assertInstanceOf(DecryptAll::class, $decAllObj); + } + + /** + * @dataProvider providesHSMData + * @param bool $hsmEnabled + */ + public function testGetEncryptAllObjWithHSM($hsmEnabled) { + $hsm = ''; + if ($hsmEnabled === true) { + $hsm = 'hsm'; + } + $this->config->method('getAppValue') + ->will($this->returnValueMap([ + ['encryption', 'recoveryKeyId', '', 'foo'], + ['crypto.engine', 'internal', '', $hsm] + ])); + + $encObject = $this->encdecAllFactory->getEncryptAllObj(); + $this->assertInstanceOf(EncryptAll::class, $encObject); + } + + public function providesHSMData() { + return [ + [true], + [false], + ]; + } +} diff --git a/tests/unit/UtilTest.php b/tests/unit/UtilTest.php index ea75cee5..3bd89db7 100644 --- a/tests/unit/UtilTest.php +++ b/tests/unit/UtilTest.php @@ -208,4 +208,19 @@ public function testGetStorage() { $this->assertEquals($return, $this->instance->getStorage($path)); } + + public function testRemoveEncAppSettings() { + $this->configMock->expects($this->once()) + ->method('setAppValue') + ->with('core', 'encryption_enabled', 'no'); + $this->configMock->method('deleteAppValue') + ->will($this->returnValueMap([ + ['encryption', 'useMasterKey', ''], + ['encryption', 'masterKeyId', ''], + ['encryption', 'recoveryKeyId', ''], + ['encryption', 'publicShareKeyId', ''], + ['files_encryption', 'installed_version', ''], + ])); + $this->instance->removeEncryptionAppSettings(); + } }