Merge pull request #2411 from nextcloud/fix-encryption-home-storage

check if the file should really be encrypted before we update the file cache
This commit is contained in:
Morris Jobke 2016-12-05 15:38:13 +01:00 committed by GitHub
commit 1253d1008a
2 changed files with 124 additions and 2 deletions

View File

@ -444,7 +444,7 @@ class Encryption extends Wrapper {
} }
// encryption disabled on write of new file and write to existing unencrypted file -> don't encrypt // encryption disabled on write of new file and write to existing unencrypted file -> don't encrypt
if (!$encryptionEnabled || !$this->mount->getOption('encrypt', true)) { if (!$encryptionEnabled || !$this->shouldEncrypt($path)) {
if (!$targetExists || !$targetIsEncrypted) { if (!$targetExists || !$targetIsEncrypted) {
$shouldEncrypt = false; $shouldEncrypt = false;
} }
@ -651,7 +651,7 @@ class Encryption extends Wrapper {
* @param bool $isRename * @param bool $isRename
*/ */
private function updateEncryptedVersion(Storage $sourceStorage, $sourceInternalPath, $targetInternalPath, $isRename) { private function updateEncryptedVersion(Storage $sourceStorage, $sourceInternalPath, $targetInternalPath, $isRename) {
$isEncrypted = $this->encryptionManager->isEnabled() && $this->mount->getOption('encrypt', true) ? 1 : 0; $isEncrypted = $this->encryptionManager->isEnabled() && $this->shouldEncrypt($targetInternalPath) ? 1 : 0;
$cacheInformation = [ $cacheInformation = [
'encrypted' => (bool)$isEncrypted, 'encrypted' => (bool)$isEncrypted,
]; ];
@ -954,6 +954,7 @@ class Encryption extends Wrapper {
throw $e; throw $e;
} }
} }
return $encryptionModule; return $encryptionModule;
} }
@ -991,4 +992,31 @@ class Encryption extends Wrapper {
return substr($normalized, 0, strlen('/files_versions/')) === '/files_versions/'; return substr($normalized, 0, strlen('/files_versions/')) === '/files_versions/';
} }
/**
* check if the given storage should be encrypted or not
*
* @param $path
* @return bool
*/
protected function shouldEncrypt($path) {
$fullPath = $this->getFullPath($path);
$mountPointConfig = $this->mount->getOption('encrypt', true);
if ($mountPointConfig === false) {
return false;
}
try {
$encryptionModule = $this->getEncryptionModule($fullPath);
} catch (ModuleDoesNotExistsException $e) {
return false;
}
if ($encryptionModule === null) {
$encryptionModule = $this->encryptionManager->getEncryptionModule();
}
return $encryptionModule->shouldEncrypt($fullPath);
}
} }

View File

@ -2,13 +2,21 @@
namespace Test\Files\Storage\Wrapper; namespace Test\Files\Storage\Wrapper;
use OC\Encryption\Exceptions\ModuleDoesNotExistsException;
use OC\Encryption\Update;
use OC\Encryption\Util; use OC\Encryption\Util;
use OC\Files\Storage\Temporary; use OC\Files\Storage\Temporary;
use OC\Files\Storage\Wrapper\Encryption;
use OC\Files\View; use OC\Files\View;
use OC\Log; use OC\Log;
use OC\Memcache\ArrayCache; use OC\Memcache\ArrayCache;
use OC\User\Manager; use OC\User\Manager;
use OCP\Encryption\IEncryptionModule;
use OCP\Encryption\IFile;
use OCP\Encryption\Keys\IStorage;
use OCP\Files\Cache\ICache; use OCP\Files\Cache\ICache;
use OCP\Files\Mount\IMountPoint;
use OCP\ILogger;
use Test\Files\Storage\Storage; use Test\Files\Storage\Storage;
class EncryptionTest extends Storage { class EncryptionTest extends Storage {
@ -926,4 +934,90 @@ class EncryptionTest extends Storage {
]; ];
} }
/**
* @dataProvider dataTestShouldEncrypt
*
* @param bool $encryptMountPoint
* @param \PHPUnit_Framework_MockObject_MockObject | IEncryptionModule $encryptionModule
* @param bool $encryptionModuleShouldEncrypt
* @param bool $expected
*/
public function testShouldEncrypt(
$encryptMountPoint,
$encryptionModule,
$encryptionModuleShouldEncrypt,
$expected
) {
$encryptionManager = $this->createMock(\OC\Encryption\Manager::class);
$util = $this->createMock(Util::class);
$logger = $this->createMock(ILogger::class);
$fileHelper = $this->createMock(IFile::class);
$uid = null;
$keyStorage = $this->createMock(IStorage::class);
$update = $this->createMock(Update::class);
$mountManager = $this->createMock(\OC\Files\Mount\Manager::class);
$mount = $this->createMock(IMountPoint::class);
$arrayCache = $this->createMock(ArrayCache::class);
$path = '/welcome.txt';
$fullPath = 'admin/files/welcome.txt';
$defaultEncryptionModule = $this->createMock(IEncryptionModule::class);
$wrapper = $this->getMockBuilder(Encryption::class)
->setConstructorArgs(
[
['mountPoint' => '', 'mount' => $mount, 'storage' => ''],
$encryptionManager,
$util,
$logger,
$fileHelper,
$uid,
$keyStorage,
$update,
$mountManager,
$arrayCache
]
)
->setMethods(['getFullPath', 'getEncryptionModule'])
->getMock();
$wrapper->method('getFullPath')->with($path)->willReturn($fullPath);
$wrapper->method('getEncryptionModule')->with($fullPath)
->willReturnCallback(
function() use ($encryptionModule) {
if ($encryptionModule === false) {
throw new ModuleDoesNotExistsException();
}
return $encryptionModule;
}
);
$mount->expects($this->once())->method('getOption')->with('encrypt', true)
->willReturn($encryptMountPoint);
if ($encryptionModule !== null && $encryptionModule !== false) {
$encryptionModule->method('shouldEncrypt')->with($fullPath)
->willReturn($encryptionModuleShouldEncrypt);
}
if ($encryptionModule === null) {
$encryptionManager->expects($this->once())->method('getEncryptionModule')
->willReturn($defaultEncryptionModule);
}
$defaultEncryptionModule->method('shouldEncrypt')->willReturn(true);
$result = $this->invokePrivate($wrapper, 'shouldEncrypt', [$path]);
$this->assertSame($expected, $result);
}
public function dataTestShouldEncrypt() {
$encryptionModule = $this->createMock(IEncryptionModule::class);
return [
[false, false, false, false],
[true, false, false, false],
[true, $encryptionModule, false, false],
[true, $encryptionModule, true, true],
[true, null, false, true],
];
}
} }