Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,9 @@ protected function setupUser($name, $password): View {
$this->loginWithEncryption($name);
return new View('/' . $name . '/files');
}

protected function tearDown(): void {
$this->tearDownEncryptionTrait();
parent::tearDown();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,9 @@ protected function setupUser($name, $password): View {
$this->loginWithEncryption($name);
return new View('/' . $name . '/files');
}

protected function tearDown(): void {
$this->tearDownEncryptionTrait();
parent::tearDown();
}
}
5 changes: 5 additions & 0 deletions apps/encryption/tests/Command/FixEncryptedVersionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -390,4 +390,9 @@ public function testExecuteWithNoMasterKey(): void {

$this->assertStringContainsString('only works with master key', $output);
}

protected function tearDown(): void {
$this->tearDownEncryptionTrait();
parent::tearDown();
}
}
5 changes: 5 additions & 0 deletions apps/encryption/tests/EncryptedStorageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,9 @@ public function testMoveFromEncrypted(): void {
$this->assertEquals('bar', $unencryptedStorage->file_get_contents('foo.txt'));
$this->assertFalse($unencryptedCache->get('foo.txt')->isEncrypted());
}

protected function tearDown(): void {
$this->tearDownEncryptionTrait();
parent::tearDown();
}
}
5 changes: 5 additions & 0 deletions apps/files_sharing/tests/EncryptedSizePropagationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,9 @@ protected function loginHelper($user, $create = false, $password = false) {
$this->setupForUser($user, $password);
parent::loginHelper($user, $create, $password);
}

protected function tearDown(): void {
$this->tearDownEncryptionTrait();
parent::tearDown();
}
}
16 changes: 0 additions & 16 deletions build/psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2975,19 +2975,6 @@
<code><![CDATA[\OC_Util::tearDownFS()]]></code>
</DeprecatedMethod>
</file>
<file src="core/Command/Encryption/Disable.php">
<DeprecatedMethod>
<code><![CDATA[getAppValue]]></code>
<code><![CDATA[setAppValue]]></code>
</DeprecatedMethod>
</file>
<file src="core/Command/Encryption/Enable.php">
<DeprecatedMethod>
<code><![CDATA[getAppValue]]></code>
<code><![CDATA[getAppValue]]></code>
<code><![CDATA[setAppValue]]></code>
</DeprecatedMethod>
</file>
<file src="core/Command/Encryption/MigrateKeyStorage.php">
<DeprecatedClass>
<code><![CDATA[\OC_Util::setupFS($uid)]]></code>
Expand Down Expand Up @@ -4257,9 +4244,6 @@
</DeprecatedMethod>
</file>
<file src="tests/lib/TestCase.php">
<DeprecatedMethod>
<code><![CDATA[$container]]></code>
</DeprecatedMethod>
<InternalMethod>
<code><![CDATA[lockFile]]></code>
<code><![CDATA[unlockFile]]></code>
Expand Down
6 changes: 4 additions & 2 deletions core/Command/Encryption/Disable.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
namespace OC\Core\Command\Encryption;

use OCP\IAppConfig;
use OCP\IConfig;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
Expand All @@ -15,6 +16,7 @@
class Disable extends Command {
public function __construct(
protected IConfig $config,
protected IAppConfig $appConfig,
) {
parent::__construct();
}
Expand All @@ -27,10 +29,10 @@ protected function configure() {
}

protected function execute(InputInterface $input, OutputInterface $output): int {
if ($this->config->getAppValue('core', 'encryption_enabled', 'no') !== 'yes') {
if ($this->appConfig->getValueString('core', 'encryption_enabled', 'no') !== 'yes') {
$output->writeln('Encryption is already disabled');
} else {
$this->config->setAppValue('core', 'encryption_enabled', 'no');
$this->appConfig->setValueString('core', 'encryption_enabled', 'no');
$output->writeln('<info>Encryption disabled</info>');
}
return 0;
Expand Down
8 changes: 5 additions & 3 deletions core/Command/Encryption/Enable.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace OC\Core\Command\Encryption;

use OCP\Encryption\IManager;
use OCP\IAppConfig;
use OCP\IConfig;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
Expand All @@ -16,6 +17,7 @@
class Enable extends Command {
public function __construct(
protected IConfig $config,
protected IAppConfig $appConfig,
protected IManager $encryptionManager,
) {
parent::__construct();
Expand All @@ -29,10 +31,10 @@ protected function configure() {
}

protected function execute(InputInterface $input, OutputInterface $output): int {
if ($this->config->getAppValue('core', 'encryption_enabled', 'no') === 'yes') {
if ($this->appConfig->getValueString('core', 'encryption_enabled', 'no') === 'yes') {
$output->writeln('Encryption is already enabled');
} else {
$this->config->setAppValue('core', 'encryption_enabled', 'yes');
$this->appConfig->setValueString('core', 'encryption_enabled', 'yes');
$output->writeln('<info>Encryption enabled</info>');
}
$output->writeln('');
Expand All @@ -42,7 +44,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$output->writeln('<error>No encryption module is loaded</error>');
return 1;
}
$defaultModule = $this->config->getAppValue('core', 'default_encryption_module');
$defaultModule = $this->appConfig->getValueString('core', 'default_encryption_module', '');
if ($defaultModule === '') {
$output->writeln('<error>No default module is set</error>');
return 1;
Expand Down
67 changes: 42 additions & 25 deletions lib/private/Encryption/EncryptionWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace OC\Encryption;

use OC\Files\Filesystem;
use OC\Files\Mount\HomeMountPoint;
use OC\Files\Storage\Wrapper\Encryption;
use OC\Files\View;
use OC\Memcache\ArrayCache;
Expand Down Expand Up @@ -62,32 +63,48 @@ public function wrapStorage(string $mountPoint, IStorage $storage, IMountPoint $
'mount' => $mount
];

if ($force || (!$storage->instanceOfStorage(IDisableEncryptionStorage::class) && $mountPoint !== '/')) {
$user = \OC::$server->getUserSession()->getUser();
$mountManager = Filesystem::getMountManager();
$uid = $user ? $user->getUID() : null;
$fileHelper = \OC::$server->get(IFile::class);
$keyStorage = \OC::$server->get(EncryptionKeysStorage::class);
// Only evaluate other conditions if not forced
if (!$force) {
// If a disabled storage medium, return basic storage
if ($storage->instanceOfStorage(IDisableEncryptionStorage::class)) {
return $storage;
}

$util = new Util(
new View(),
\OC::$server->getUserManager(),
\OC::$server->getGroupManager(),
\OC::$server->getConfig()
);
return new Encryption(
$parameters,
$this->manager,
$util,
$this->logger,
$fileHelper,
$uid,
$keyStorage,
$mountManager,
$this->arrayCache
);
} else {
return $storage;
// Root mount point handling: skip encryption wrapper
if ($mountPoint === '/') {
return $storage;
}

// Skip encryption for home mounts if encryptHomeStorage is disabled
if ($mount instanceof HomeMountPoint
&& \OC::$server->getConfig()->getAppValue('encryption', 'encryptHomeStorage', '1') !== '1') {
return $storage;
}
}

// Apply encryption wrapper
$user = \OC::$server->getUserSession()->getUser();
$mountManager = Filesystem::getMountManager();
$uid = $user ? $user->getUID() : null;
$fileHelper = \OC::$server->get(IFile::class);
$keyStorage = \OC::$server->get(EncryptionKeysStorage::class);

$util = new Util(
new View(),
\OC::$server->getUserManager(),
\OC::$server->getGroupManager(),
\OC::$server->getConfig()
);
return new Encryption(
$parameters,
$this->manager,
$util,
$this->logger,
$fileHelper,
$uid,
$keyStorage,
$mountManager,
$this->arrayCache
);
}
}
2 changes: 1 addition & 1 deletion lib/private/Files/Cache/CacheEntry.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public function __clone() {
}

public function getUnencryptedSize(): int {
if ($this->data['encrypted'] && isset($this->data['unencrypted_size']) && $this->data['unencrypted_size'] > 0) {
if ($this->data['encrypted'] && isset($this->data['unencrypted_size'])) {
return $this->data['unencrypted_size'];
} else {
return $this->data['size'] ?? 0;
Expand Down
15 changes: 12 additions & 3 deletions lib/private/Files/Cache/Scanner.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,12 @@ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData =
}
}

// we only updated unencrypted_size if it's already set
if (isset($cacheData['unencrypted_size']) && $cacheData['unencrypted_size'] === 0) {
// Only skip updating unencrypted_size if both cached and new values are 0
// This allows updating from incorrect cached 0 to correct non-zero value
// while avoiding unnecessary updates when both are legitimately 0
if (isset($cacheData['unencrypted_size'])
&& $cacheData['unencrypted_size'] === 0
&& (!isset($data['unencrypted_size']) || $data['unencrypted_size'] === 0)) {
unset($data['unencrypted_size']);
}

Expand All @@ -216,7 +220,12 @@ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData =
$data['etag_changed'] = true;
}
} else {
unset($data['unencrypted_size']);
// For new files, only unset unencrypted_size if the file is not encrypted
// or if unencrypted_size is 0/not set (not a valid encrypted file)
if (!isset($data['encrypted']) || !$data['encrypted']
|| !isset($data['unencrypted_size']) || $data['unencrypted_size'] === 0) {
unset($data['unencrypted_size']);
}
$newData = $data;
$fileId = -1;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/private/Files/FileInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public function getSize($includeMounts = true) {
if ($includeMounts) {
$this->updateEntryFromSubMounts();

if ($this->isEncrypted() && isset($this->data['unencrypted_size']) && $this->data['unencrypted_size'] > 0) {
if ($this->isEncrypted() && isset($this->data['unencrypted_size'])) {
return $this->data['unencrypted_size'];
} else {
return isset($this->data['size']) ? 0 + $this->data['size'] : 0;
Expand Down
1 change: 1 addition & 0 deletions lib/private/Files/Storage/Wrapper/Encryption.php
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ protected function verifyUnencryptedSize(string $path, int $unencryptedSize): in
if ($unencryptedSize < 0
|| ($size > 0 && $unencryptedSize === $size)
|| $unencryptedSize > $size
|| ($unencryptedSize === 0 && $size > 0)
) {
// check if we already calculate the unencrypted size for the
// given path to avoid recursions
Expand Down
2 changes: 1 addition & 1 deletion lib/private/Files/Stream/Encryption.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Encryption extends Wrapper {
protected string $cache;
protected ?int $size = null;
protected int $position;
protected ?int $unencryptedSize = null;
protected int|float|null $unencryptedSize = null;
protected int $headerSize;
protected int $unencryptedBlockSize;
protected array $header;
Expand Down
19 changes: 13 additions & 6 deletions tests/Core/Command/Encryption/DisableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace Tests\Core\Command\Encryption;

use OC\Core\Command\Encryption\Disable;
use OCP\IAppConfig;
use OCP\IConfig;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
Expand All @@ -18,6 +19,8 @@ class DisableTest extends TestCase {
/** @var \PHPUnit\Framework\MockObject\MockObject */
protected $config;
/** @var \PHPUnit\Framework\MockObject\MockObject */
protected $appConfig;
/** @var \PHPUnit\Framework\MockObject\MockObject */
protected $consoleInput;
/** @var \PHPUnit\Framework\MockObject\MockObject */
protected $consoleOutput;
Expand All @@ -31,11 +34,15 @@ protected function setUp(): void {
$config = $this->config = $this->getMockBuilder(IConfig::class)
->disableOriginalConstructor()
->getMock();
$appConfig = $this->appConfig = $this->getMockBuilder(IAppConfig::class)
->disableOriginalConstructor()
->getMock();
$this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock();
$this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock();

/** @var IConfig $config */
$this->command = new Disable($config);
/** @var IAppConfig $appConfig */
$this->command = new Disable($config, $appConfig);
}


Expand All @@ -54,18 +61,18 @@ public static function dataDisable(): array {
*/
#[\PHPUnit\Framework\Attributes\DataProvider('dataDisable')]
public function testDisable($oldStatus, $isUpdating, $expectedString): void {
$this->config->expects($this->once())
->method('getAppValue')
->with('core', 'encryption_enabled', $this->anything())
$this->appConfig->expects($this->once())
->method('getValueString')
->with('core', 'encryption_enabled', 'no')
->willReturn($oldStatus);

$this->consoleOutput->expects($this->once())
->method('writeln')
->with($this->stringContains($expectedString));

if ($isUpdating) {
$this->config->expects($this->once())
->method('setAppValue')
$this->appConfig->expects($this->once())
->method('setValueString')
->with('core', 'encryption_enabled', 'no');
}

Expand Down
Loading
Loading