mirror of
https://github.com/nextcloud/server.git
synced 2026-06-08 08:16:43 -04:00
Fix encrypted version to 0 when finding unencrypted file
Whenever the command is run and a "legacy cipher" seems to be detected when the legacy option is disabled, it's highly likely that the file is actually unencrypted but the database contains a encrypted version higher than 0 for some reason. The command now detects this case and automatically sets the encrypted version to 0 so that the file can be read again. Signed-off-by: Vincent Petry <vincent@nextcloud.com>
This commit is contained in:
parent
c81fd490c4
commit
fd6c5a134f
2 changed files with 68 additions and 1 deletions
|
|
@ -24,6 +24,7 @@ namespace OCA\Encryption\Command;
|
|||
|
||||
use OC\Files\View;
|
||||
use OC\HintException;
|
||||
use OC\ServerNotAvailableException;
|
||||
use OCA\Encryption\Util;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\IConfig;
|
||||
|
|
@ -53,6 +54,9 @@ class FixEncryptedVersion extends Command {
|
|||
/** @var View */
|
||||
private $view;
|
||||
|
||||
/** @var bool */
|
||||
private $supportLegacy;
|
||||
|
||||
public function __construct(
|
||||
IConfig $config,
|
||||
ILogger $logger,
|
||||
|
|
@ -67,6 +71,8 @@ class FixEncryptedVersion extends Command {
|
|||
$this->userManager = $userManager;
|
||||
$this->util = $util;
|
||||
$this->view = $view;
|
||||
$this->supportLegacy = false;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
|
@ -95,6 +101,7 @@ class FixEncryptedVersion extends Command {
|
|||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int {
|
||||
$skipSignatureCheck = $this->config->getSystemValue('encryption_skip_signature_check', false);
|
||||
$this->supportLegacy = $this->config->getSystemValueBool('encryption.legacy_format_support', false);
|
||||
|
||||
if ($skipSignatureCheck) {
|
||||
$output->writeln("<error>Repairing is not possible when \"encryption_skip_signature_check\" is set. Please disable this flag in the configuration.</error>\n");
|
||||
|
|
@ -187,6 +194,14 @@ class FixEncryptedVersion extends Command {
|
|||
\fclose($handle);
|
||||
|
||||
return true;
|
||||
} catch (ServerNotAvailableException $e) {
|
||||
// not a "bad signature" error and likely "legacy cipher" exception
|
||||
// this could mean that the file is maybe not encrypted but the encrypted version is set
|
||||
if (!$this->supportLegacy && $ignoreCorrectEncVersionCall === true) {
|
||||
$output->writeln("<info>Attempting to fix the path: \"$path\"</info>");
|
||||
return $this->correctEncryptedVersion($path, $output, true);
|
||||
}
|
||||
return false;
|
||||
} catch (HintException $e) {
|
||||
$this->logger->warning("Issue: " . $e->getMessage());
|
||||
//If allowOnce is set to false, this becomes recursive.
|
||||
|
|
@ -202,9 +217,10 @@ class FixEncryptedVersion extends Command {
|
|||
/**
|
||||
* @param string $path
|
||||
* @param OutputInterface $output
|
||||
* @param bool $includeZero whether to try zero version for unencrypted file
|
||||
* @return bool
|
||||
*/
|
||||
private function correctEncryptedVersion($path, OutputInterface $output): bool {
|
||||
private function correctEncryptedVersion($path, OutputInterface $output, bool $includeZero = false): bool {
|
||||
$fileInfo = $this->view->getFileInfo($path);
|
||||
if (!$fileInfo) {
|
||||
$output->writeln("<warning>File info not found for file: \"$path\"</warning>");
|
||||
|
|
@ -231,6 +247,17 @@ class FixEncryptedVersion extends Command {
|
|||
// Save original encrypted version so we can restore it if decryption fails with all version
|
||||
$originalEncryptedVersion = $encryptedVersion;
|
||||
if ($encryptedVersion >= 0) {
|
||||
if ($includeZero) {
|
||||
// try with zero first
|
||||
$cacheInfo = ['encryptedVersion' => 0, 'encrypted' => 0];
|
||||
$cache->put($fileCache->getPath(), $cacheInfo);
|
||||
$output->writeln("<info>Set the encrypted version to 0 (unencrypted)</info>");
|
||||
if ($this->verifyFileContent($path, $output, false) === true) {
|
||||
$output->writeln("<info>Fixed the file: \"$path\" with version 0 (unencrypted)</info>");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//test by decrementing the value till 1 and if nothing works try incrementing
|
||||
$encryptedVersion--;
|
||||
while ($encryptedVersion > 0) {
|
||||
|
|
|
|||
|
|
@ -244,6 +244,46 @@ Fixed the file: \"/$this->userId/files/world.txt\" with version 4", $output);
|
|||
$this->assertEquals(15, $encryptedVersion);
|
||||
}
|
||||
|
||||
public function testRepairUnencryptedFileWhenVersionIsSet() {
|
||||
$this->util->expects($this->once())->method('isMasterKeyEnabled')
|
||||
->willReturn(true);
|
||||
|
||||
$view = new View("/" . $this->userId . "/files");
|
||||
|
||||
// create a file, it's encrypted and also the version is set in the database
|
||||
$view->touch('hello.txt');
|
||||
|
||||
$fileInfo1 = $view->getFileInfo('hello.txt');
|
||||
|
||||
$storage1 = $fileInfo1->getStorage();
|
||||
$cache1 = $storage1->getCache();
|
||||
$fileCache1 = $cache1->get($fileInfo1->getId());
|
||||
|
||||
// Now change the encrypted version
|
||||
$cacheInfo = ['encryptedVersion' => 1, 'encrypted' => 1];
|
||||
$cache1->put($fileCache1->getPath(), $cacheInfo);
|
||||
|
||||
$absPath = $view->getLocalFolder(''). '/hello.txt';
|
||||
|
||||
// create unencrypted file on disk, the version stays
|
||||
file_put_contents($absPath, 'hello contents');
|
||||
|
||||
$this->commandTester->execute([
|
||||
'user' => $this->userId
|
||||
]);
|
||||
|
||||
$output = $this->commandTester->getDisplay();
|
||||
|
||||
$this->assertStringContainsString("Verifying the content of file \"/$this->userId/files/hello.txt\"
|
||||
Attempting to fix the path: \"/$this->userId/files/hello.txt\"
|
||||
Set the encrypted version to 0 (unencrypted)
|
||||
The file \"/$this->userId/files/hello.txt\" is: OK
|
||||
Fixed the file: \"/$this->userId/files/hello.txt\" with version 0 (unencrypted)", $output);
|
||||
|
||||
// the file can be decrypted
|
||||
$this->assertEquals('hello contents', $view->file_get_contents('hello.txt'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test commands with a file path
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue