388 lines
12 KiB
PHP
388 lines
12 KiB
PHP
<?php
|
|
/**
|
|
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
|
*
|
|
* @author Bjoern Schiessle <bjoern@schiessle.org>
|
|
* @author Björn Schießle <bjoern@schiessle.org>
|
|
* @author Joas Schilling <coding@schilljs.com>
|
|
* @author Kenneth Newwood <kenneth@newwood.name>
|
|
* @author Morris Jobke <hey@morrisjobke.de>
|
|
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
|
*
|
|
* @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\Tests\Crypto;
|
|
|
|
use OC\Files\View;
|
|
use OCA\Encryption\Crypto\EncryptAll;
|
|
use OCA\Encryption\KeyManager;
|
|
use OCA\Encryption\Users\Setup;
|
|
use OCA\Encryption\Util;
|
|
use OCP\Files\FileInfo;
|
|
use OCP\IConfig;
|
|
use OCP\IL10N;
|
|
use OCP\IUserManager;
|
|
use OCP\Mail\IMailer;
|
|
use OCP\Security\ISecureRandom;
|
|
use OCP\UserInterface;
|
|
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
|
|
use Symfony\Component\Console\Helper\ProgressBar;
|
|
use Symfony\Component\Console\Helper\QuestionHelper;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
use Test\TestCase;
|
|
|
|
class EncryptAllTest extends TestCase {
|
|
|
|
/** @var \PHPUnit_Framework_MockObject_MockObject | \OCA\Encryption\KeyManager */
|
|
protected $keyManager;
|
|
|
|
/** @var \PHPUnit_Framework_MockObject_MockObject | \OCA\Encryption\Util */
|
|
protected $util;
|
|
|
|
/** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\IUserManager */
|
|
protected $userManager;
|
|
|
|
/** @var \PHPUnit_Framework_MockObject_MockObject | \OCA\Encryption\Users\Setup */
|
|
protected $setupUser;
|
|
|
|
/** @var \PHPUnit_Framework_MockObject_MockObject | \OC\Files\View */
|
|
protected $view;
|
|
|
|
/** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\IConfig */
|
|
protected $config;
|
|
|
|
/** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\Mail\IMailer */
|
|
protected $mailer;
|
|
|
|
/** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\IL10N */
|
|
protected $l;
|
|
|
|
/** @var \PHPUnit_Framework_MockObject_MockObject | \Symfony\Component\Console\Helper\QuestionHelper */
|
|
protected $questionHelper;
|
|
|
|
/** @var \PHPUnit_Framework_MockObject_MockObject | \Symfony\Component\Console\Input\InputInterface */
|
|
protected $inputInterface;
|
|
|
|
/** @var \PHPUnit_Framework_MockObject_MockObject | \Symfony\Component\Console\Output\OutputInterface */
|
|
protected $outputInterface;
|
|
|
|
/** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\UserInterface */
|
|
protected $userInterface;
|
|
|
|
/** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\Security\ISecureRandom */
|
|
protected $secureRandom;
|
|
|
|
/** @var EncryptAll */
|
|
protected $encryptAll;
|
|
|
|
protected function setUp(): void {
|
|
parent::setUp();
|
|
$this->setupUser = $this->getMockBuilder(Setup::class)
|
|
->disableOriginalConstructor()->getMock();
|
|
$this->keyManager = $this->getMockBuilder(KeyManager::class)
|
|
->disableOriginalConstructor()->getMock();
|
|
$this->util = $this->getMockBuilder(Util::class)
|
|
->disableOriginalConstructor()->getMock();
|
|
$this->userManager = $this->getMockBuilder(IUserManager::class)
|
|
->disableOriginalConstructor()->getMock();
|
|
$this->view = $this->getMockBuilder(View::class)
|
|
->disableOriginalConstructor()->getMock();
|
|
$this->config = $this->getMockBuilder(IConfig::class)
|
|
->disableOriginalConstructor()->getMock();
|
|
$this->mailer = $this->getMockBuilder(IMailer::class)
|
|
->disableOriginalConstructor()->getMock();
|
|
$this->l = $this->getMockBuilder(IL10N::class)
|
|
->disableOriginalConstructor()->getMock();
|
|
$this->questionHelper = $this->getMockBuilder(QuestionHelper::class)
|
|
->disableOriginalConstructor()->getMock();
|
|
$this->inputInterface = $this->getMockBuilder(InputInterface::class)
|
|
->disableOriginalConstructor()->getMock();
|
|
$this->outputInterface = $this->getMockBuilder(OutputInterface::class)
|
|
->disableOriginalConstructor()->getMock();
|
|
$this->userInterface = $this->getMockBuilder(UserInterface::class)
|
|
->disableOriginalConstructor()->getMock();
|
|
|
|
|
|
$this->outputInterface->expects($this->any())->method('getFormatter')
|
|
->willReturn($this->createMock(OutputFormatterInterface::class));
|
|
|
|
$this->userManager->expects($this->any())->method('getBackends')->willReturn([$this->userInterface]);
|
|
$this->userInterface->expects($this->any())->method('getUsers')->willReturn(['user1', 'user2']);
|
|
|
|
$this->secureRandom = $this->getMockBuilder(ISecureRandom::class)->disableOriginalConstructor()->getMock();
|
|
$this->secureRandom->expects($this->any())->method('generate')->willReturn('12345678');
|
|
|
|
|
|
$this->encryptAll = new EncryptAll(
|
|
$this->setupUser,
|
|
$this->userManager,
|
|
$this->view,
|
|
$this->keyManager,
|
|
$this->util,
|
|
$this->config,
|
|
$this->mailer,
|
|
$this->l,
|
|
$this->questionHelper,
|
|
$this->secureRandom
|
|
);
|
|
}
|
|
|
|
public function testEncryptAll() {
|
|
/** @var EncryptAll | \PHPUnit_Framework_MockObject_MockObject $encryptAll */
|
|
$encryptAll = $this->getMockBuilder(EncryptAll::class)
|
|
->setConstructorArgs(
|
|
[
|
|
$this->setupUser,
|
|
$this->userManager,
|
|
$this->view,
|
|
$this->keyManager,
|
|
$this->util,
|
|
$this->config,
|
|
$this->mailer,
|
|
$this->l,
|
|
$this->questionHelper,
|
|
$this->secureRandom
|
|
]
|
|
)
|
|
->setMethods(['createKeyPairs', 'encryptAllUsersFiles', 'outputPasswords'])
|
|
->getMock();
|
|
|
|
$this->util->expects($this->any())->method('isMasterKeyEnabled')->willReturn(false);
|
|
$encryptAll->expects($this->at(0))->method('createKeyPairs')->with();
|
|
$encryptAll->expects($this->at(1))->method('outputPasswords')->with();
|
|
$encryptAll->expects($this->at(2))->method('encryptAllUsersFiles')->with();
|
|
|
|
$encryptAll->encryptAll($this->inputInterface, $this->outputInterface);
|
|
|
|
}
|
|
|
|
public function testEncryptAllWithMasterKey() {
|
|
/** @var EncryptAll | \PHPUnit_Framework_MockObject_MockObject $encryptAll */
|
|
$encryptAll = $this->getMockBuilder(EncryptAll::class)
|
|
->setConstructorArgs(
|
|
[
|
|
$this->setupUser,
|
|
$this->userManager,
|
|
$this->view,
|
|
$this->keyManager,
|
|
$this->util,
|
|
$this->config,
|
|
$this->mailer,
|
|
$this->l,
|
|
$this->questionHelper,
|
|
$this->secureRandom
|
|
]
|
|
)
|
|
->setMethods(['createKeyPairs', 'encryptAllUsersFiles', 'outputPasswords'])
|
|
->getMock();
|
|
|
|
$this->util->expects($this->any())->method('isMasterKeyEnabled')->willReturn(true);
|
|
$encryptAll->expects($this->never())->method('createKeyPairs');
|
|
$this->keyManager->expects($this->once())->method('validateMasterKey');
|
|
$encryptAll->expects($this->at(0))->method('encryptAllUsersFiles')->with();
|
|
$encryptAll->expects($this->never())->method('outputPasswords');
|
|
|
|
$encryptAll->encryptAll($this->inputInterface, $this->outputInterface);
|
|
|
|
}
|
|
|
|
public function testCreateKeyPairs() {
|
|
/** @var EncryptAll | \PHPUnit_Framework_MockObject_MockObject $encryptAll */
|
|
$encryptAll = $this->getMockBuilder(EncryptAll::class)
|
|
->setConstructorArgs(
|
|
[
|
|
$this->setupUser,
|
|
$this->userManager,
|
|
$this->view,
|
|
$this->keyManager,
|
|
$this->util,
|
|
$this->config,
|
|
$this->mailer,
|
|
$this->l,
|
|
$this->questionHelper,
|
|
$this->secureRandom
|
|
]
|
|
)
|
|
->setMethods(['setupUserFS', 'generateOneTimePassword'])
|
|
->getMock();
|
|
|
|
|
|
// set protected property $output
|
|
$this->invokePrivate($encryptAll, 'output', [$this->outputInterface]);
|
|
|
|
$this->keyManager->expects($this->exactly(2))->method('userHasKeys')
|
|
->willReturnCallback(
|
|
function ($user) {
|
|
if ($user === 'user1') {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
);
|
|
|
|
$encryptAll->expects($this->once())->method('setupUserFS')->with('user1');
|
|
$encryptAll->expects($this->once())->method('generateOneTimePassword')->with('user1')->willReturn('password');
|
|
$this->setupUser->expects($this->once())->method('setupUser')->with('user1', 'password');
|
|
|
|
$this->invokePrivate($encryptAll, 'createKeyPairs');
|
|
|
|
$userPasswords = $this->invokePrivate($encryptAll, 'userPasswords');
|
|
|
|
// we only expect the skipped user, because generateOneTimePassword which
|
|
// would set the user with the new password was mocked.
|
|
// This method will be tested separately
|
|
$this->assertSame(1, count($userPasswords));
|
|
$this->assertSame('', $userPasswords['user2']);
|
|
}
|
|
|
|
public function testEncryptAllUsersFiles() {
|
|
/** @var EncryptAll | \PHPUnit_Framework_MockObject_MockObject $encryptAll */
|
|
$encryptAll = $this->getMockBuilder(EncryptAll::class)
|
|
->setConstructorArgs(
|
|
[
|
|
$this->setupUser,
|
|
$this->userManager,
|
|
$this->view,
|
|
$this->keyManager,
|
|
$this->util,
|
|
$this->config,
|
|
$this->mailer,
|
|
$this->l,
|
|
$this->questionHelper,
|
|
$this->secureRandom
|
|
]
|
|
)
|
|
->setMethods(['encryptUsersFiles'])
|
|
->getMock();
|
|
|
|
$this->util->expects($this->any())->method('isMasterKeyEnabled')->willReturn(false);
|
|
|
|
// set protected property $output
|
|
$this->invokePrivate($encryptAll, 'output', [$this->outputInterface]);
|
|
$this->invokePrivate($encryptAll, 'userPasswords', [['user1' => 'pwd1', 'user2' => 'pwd2']]);
|
|
|
|
$encryptAll->expects($this->at(0))->method('encryptUsersFiles')->with('user1');
|
|
$encryptAll->expects($this->at(1))->method('encryptUsersFiles')->with('user2');
|
|
|
|
$this->invokePrivate($encryptAll, 'encryptAllUsersFiles');
|
|
|
|
}
|
|
|
|
public function testEncryptUsersFiles() {
|
|
/** @var EncryptAll | \PHPUnit_Framework_MockObject_MockObject $encryptAll */
|
|
$encryptAll = $this->getMockBuilder(EncryptAll::class)
|
|
->setConstructorArgs(
|
|
[
|
|
$this->setupUser,
|
|
$this->userManager,
|
|
$this->view,
|
|
$this->keyManager,
|
|
$this->util,
|
|
$this->config,
|
|
$this->mailer,
|
|
$this->l,
|
|
$this->questionHelper,
|
|
$this->secureRandom
|
|
]
|
|
)
|
|
->setMethods(['encryptFile', 'setupUserFS'])
|
|
->getMock();
|
|
|
|
$this->util->expects($this->any())->method('isMasterKeyEnabled')->willReturn(false);
|
|
|
|
$this->view->expects($this->at(0))->method('getDirectoryContent')
|
|
->with('/user1/files')->willReturn(
|
|
[
|
|
['name' => 'foo', 'type'=>'dir'],
|
|
['name' => 'bar', 'type'=>'file'],
|
|
]
|
|
);
|
|
|
|
$this->view->expects($this->at(3))->method('getDirectoryContent')
|
|
->with('/user1/files/foo')->willReturn(
|
|
[
|
|
['name' => 'subfile', 'type'=>'file']
|
|
]
|
|
);
|
|
|
|
$this->view->expects($this->any())->method('is_dir')
|
|
->willReturnCallback(
|
|
function($path) {
|
|
if ($path === '/user1/files/foo') {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
);
|
|
|
|
$encryptAll->expects($this->at(1))->method('encryptFile')->with('/user1/files/bar');
|
|
$encryptAll->expects($this->at(2))->method('encryptFile')->with('/user1/files/foo/subfile');
|
|
|
|
$this->outputInterface->expects($this->any())
|
|
->method('getFormatter')
|
|
->willReturn($this->createMock(OutputFormatterInterface::class));
|
|
$progressBar = new ProgressBar($this->outputInterface);
|
|
|
|
$this->invokePrivate($encryptAll, 'encryptUsersFiles', ['user1', $progressBar, '']);
|
|
|
|
}
|
|
|
|
public function testGenerateOneTimePassword() {
|
|
$password = $this->invokePrivate($this->encryptAll, 'generateOneTimePassword', ['user1']);
|
|
$this->assertTrue(is_string($password));
|
|
$this->assertSame(8, strlen($password));
|
|
|
|
$userPasswords = $this->invokePrivate($this->encryptAll, 'userPasswords');
|
|
$this->assertSame(1, count($userPasswords));
|
|
$this->assertSame($password, $userPasswords['user1']);
|
|
}
|
|
|
|
/**
|
|
* @dataProvider dataTestEncryptFile
|
|
* @param $isEncrypted
|
|
*/
|
|
public function testEncryptFile($isEncrypted) {
|
|
$fileInfo = $this->createMock(FileInfo::class);
|
|
$fileInfo->expects($this->any())->method('isEncrypted')
|
|
->willReturn($isEncrypted);
|
|
$this->view->expects($this->any())->method('getFileInfo')
|
|
->willReturn($fileInfo);
|
|
|
|
|
|
if($isEncrypted) {
|
|
$this->view->expects($this->never())->method('copy');
|
|
$this->view->expects($this->never())->method('rename');
|
|
} else {
|
|
$this->view->expects($this->once())->method('copy');
|
|
$this->view->expects($this->once())->method('rename');
|
|
}
|
|
|
|
$this->assertTrue(
|
|
$this->invokePrivate($this->encryptAll, 'encryptFile', ['foo.txt'])
|
|
);
|
|
}
|
|
|
|
public function dataTestEncryptFile() {
|
|
return [
|
|
[true],
|
|
[false],
|
|
];
|
|
}
|
|
|
|
}
|