diff options
author | Simon L <szaimen@e.mail.de> | 2023-04-01 18:14:16 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-01 18:14:16 +0200 |
commit | 57bd5e71b9d3865e148ea2ab3f203681fbf5c590 (patch) | |
tree | becf94f5410cf53dcbaf8712986a3fde5fd759c9 | |
parent | 06ab4f25eb423a5a3ff146f5fcda81f60993010a (diff) | |
parent | 808a80eb9c491823bddb461f62036d83e67fdb13 (diff) | |
download | nextcloud-server-57bd5e71b9d3865e148ea2ab3f203681fbf5c590.tar.gz nextcloud-server-57bd5e71b9d3865e148ea2ab3f203681fbf5c590.zip |
Merge pull request #35961 from nextcloud/move-from-encryption-remove-flag
clear encrypted flag when moving away from encrypted storage
-rw-r--r-- | apps/encryption/tests/EncryptedStorageTest.php | 85 | ||||
-rw-r--r-- | lib/private/Files/Cache/Cache.php | 22 | ||||
-rw-r--r-- | lib/private/Files/Cache/Wrapper/CacheWrapper.php | 9 |
3 files changed, 116 insertions, 0 deletions
diff --git a/apps/encryption/tests/EncryptedStorageTest.php b/apps/encryption/tests/EncryptedStorageTest.php new file mode 100644 index 00000000000..3219707d48b --- /dev/null +++ b/apps/encryption/tests/EncryptedStorageTest.php @@ -0,0 +1,85 @@ +<?php + +declare(strict_types=1); +/** + * @copyright Copyright (c) 2023 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\encryption\tests; + +use OC\Files\Storage\Temporary; +use OC\Files\Storage\Wrapper\Encryption; +use OC\Files\View; +use OCP\Files\Mount\IMountManager; +use OCP\Files\Storage\IDisableEncryptionStorage; +use Test\TestCase; +use Test\Traits\EncryptionTrait; +use Test\Traits\MountProviderTrait; +use Test\Traits\UserTrait; + +class TemporaryNoEncrypted extends Temporary implements IDisableEncryptionStorage { + +} + +/** + * @group DB + */ +class EncryptedStorageTest extends TestCase { + use MountProviderTrait; + use EncryptionTrait; + use UserTrait; + + public function testMoveFromEncrypted() { + $this->createUser("test1", "test2"); + $this->setupForUser("test1", 'test2'); + + $unwrapped = new Temporary(); + + $this->registerMount("test1", new TemporaryNoEncrypted(), "/test1/files/unenc"); + $this->registerMount("test1", $unwrapped, "/test1/files/enc"); + + $this->loginWithEncryption("test1"); + + $view = new View("/test1/files"); + + /** @var IMountManager $mountManager */ + $mountManager = \OC::$server->get(IMountManager::class); + + $encryptedMount = $mountManager->find("/test1/files/enc"); + $unencryptedMount = $mountManager->find("/test1/files/unenc"); + $encryptedStorage = $encryptedMount->getStorage(); + $unencryptedStorage = $unencryptedMount->getStorage(); + $encryptedCache = $encryptedStorage->getCache(); + $unencryptedCache = $unencryptedStorage->getCache(); + + $this->assertTrue($encryptedStorage->instanceOfStorage(Encryption::class)); + $this->assertFalse($unencryptedStorage->instanceOfStorage(Encryption::class)); + + $encryptedStorage->file_put_contents("foo.txt", "bar"); + $this->assertEquals("bar", $encryptedStorage->file_get_contents("foo.txt")); + $this->assertStringStartsWith("HBEGIN:oc_encryption_module:", $unwrapped->file_get_contents("foo.txt")); + + $this->assertTrue($encryptedCache->get("foo.txt")->isEncrypted()); + + $view->rename("enc/foo.txt", "unenc/foo.txt"); + + $this->assertEquals("bar", $unencryptedStorage->file_get_contents("foo.txt")); + $this->assertFalse($unencryptedCache->get("foo.txt")->isEncrypted()); + } +} diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index 9afeea7b573..afa464a8138 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -43,6 +43,7 @@ namespace OC\Files\Cache; use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use OC\Files\Search\SearchComparison; use OC\Files\Search\SearchQuery; +use OC\Files\Storage\Wrapper\Encryption; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Cache\CacheEntryInsertedEvent; @@ -659,6 +660,10 @@ class Cache implements ICache { return [$this->getNumericStorageId(), $path]; } + protected function hasEncryptionWrapper(): bool { + return $this->storage->instanceOfStorage(Encryption::class); + } + /** * Move a file or folder in the cache * @@ -710,6 +715,11 @@ class Cache implements ICache { ->where($query->expr()->eq('storage', $query->createNamedParameter($sourceStorageId, IQueryBuilder::PARAM_INT))) ->andWhere($query->expr()->like('path', $query->createNamedParameter($this->connection->escapeLikeParameter($sourcePath) . '/%'))); + // when moving from an encrypted storage to a non-encrypted storage remove the `encrypted` mark + if ($sourceCache->hasEncryptionWrapper() && !$this->hasEncryptionWrapper()) { + $query->set('encrypted', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT)); + } + try { $query->execute(); } catch (\OC\DatabaseException $e) { @@ -726,6 +736,12 @@ class Cache implements ICache { ->set('name', $query->createNamedParameter(basename($targetPath))) ->set('parent', $query->createNamedParameter($newParentId, IQueryBuilder::PARAM_INT)) ->whereFileId($sourceId); + + // when moving from an encrypted storage to a non-encrypted storage remove the `encrypted` mark + if ($sourceCache->hasEncryptionWrapper() && !$this->hasEncryptionWrapper()) { + $query->set('encrypted', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT)); + } + $query->execute(); $this->connection->commit(); @@ -1085,6 +1101,12 @@ class Cache implements ICache { throw new \RuntimeException("Invalid source cache entry on copyFromCache"); } $data = $this->cacheEntryToArray($sourceEntry); + + // when moving from an encrypted storage to a non-encrypted storage remove the `encrypted` mark + if ($sourceCache instanceof Cache && $sourceCache->hasEncryptionWrapper() && !$this->hasEncryptionWrapper()) { + $data['encrypted'] = 0; + } + $fileId = $this->put($targetPath, $data); if ($fileId <= 0) { throw new \RuntimeException("Failed to copy to " . $targetPath . " from cache with source data " . json_encode($data) . " "); diff --git a/lib/private/Files/Cache/Wrapper/CacheWrapper.php b/lib/private/Files/Cache/Wrapper/CacheWrapper.php index 66ae83fd144..2cd378ad23c 100644 --- a/lib/private/Files/Cache/Wrapper/CacheWrapper.php +++ b/lib/private/Files/Cache/Wrapper/CacheWrapper.php @@ -56,6 +56,15 @@ class CacheWrapper extends Cache { return $this->cache; } + protected function hasEncryptionWrapper(): bool { + $cache = $this->getCache(); + if ($cache instanceof Cache) { + return $cache->hasEncryptionWrapper(); + } else { + return false; + } + } + /** * Make it easy for wrappers to modify every returned cache entry * |