Skip to content

Commit

Permalink
make file cache updates more robust
Browse files Browse the repository at this point in the history
only update the encrypted version after the write operation is finished and the stream is closed

Signed-off-by: Bjoern Schiessle <bjoern@schiessle.org>
  • Loading branch information
schiessle committed Jul 26, 2018
1 parent a2df728 commit 0512d91
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 3 deletions.
1 change: 0 additions & 1 deletion apps/encryption/lib/Crypto/Encryption.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,6 @@ public function begin($path, $user, $mode, array $header, array $accessList) {
public function end($path, $position = 0) {
$result = '';
if ($this->isWriteOperation) {
$this->keyManager->setVersion($path, $this->version + 1, new View());
// in case of a part file we remember the new signature versions
// the version will be set later on update.
// This way we make sure that other apps listening to the pre-hooks
Expand Down
19 changes: 17 additions & 2 deletions lib/private/Files/Stream/Encryption.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ class Encryption extends Wrapper {
/** @var array */
protected $expectedContextProperties;

/** @var bool */
protected $fileUpdated;

public function __construct() {
$this->expectedContextProperties = array(
'source',
Expand Down Expand Up @@ -235,6 +238,7 @@ public function stream_open($path, $mode, $options, &$opened_path) {
$this->position = 0;
$this->cache = '';
$this->writeFlag = false;
$this->fileUpdated = false;
$this->unencryptedBlockSize = $this->encryptionModule->getUnencryptedBlockSize($this->signed);

if (
Expand Down Expand Up @@ -313,7 +317,6 @@ public function stream_read($count) {
}

public function stream_write($data) {

$length = 0;
// loop over $data to fit it in 6126 sized unencrypted blocks
while (isset($data[0])) {
Expand All @@ -333,6 +336,7 @@ public function stream_write($data) {

// switch the writeFlag so flush() will write the block
$this->writeFlag = true;
$this->fileUpdated = true;

// determine the relative position in the current block
$blockPosition = ($this->position % $this->unencryptedBlockSize);
Expand Down Expand Up @@ -414,7 +418,18 @@ public function stream_close() {
}
$this->encryptionStorage->updateUnencryptedSize($this->fullPath, $this->unencryptedSize);
}
return parent::stream_close();
$result = parent::stream_close();

if ($this->fileUpdated) {
$cache = $this->storage->getCache();
$cacheEntry = $cache->get($this->internalPath);
if ($cacheEntry) {
$version = $cacheEntry['encryptedVersion'] + 1;
$cache->update($cacheEntry->getId(), ['encrypted' => $version, 'encryptedVersion' => $version]);
}
}

return $result;
}

/**
Expand Down
11 changes: 11 additions & 0 deletions tests/lib/Files/Stream/EncryptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

namespace Test\Files\Stream;

use OC\Files\Cache\CacheEntry;
use OC\Files\View;
use OC\Memcache\ArrayCache;
use OCP\Files\Cache\ICache;
use OCP\IConfig;

class EncryptionTest extends \Test\TestCase {
Expand All @@ -26,6 +28,7 @@ protected function getStream($fileName, $mode, $unencryptedSize, $wrapper = '\OC
$header = [];
$uid = '';
$this->encryptionModule = $this->buildMockModule();
$cache = $this->createMock(ICache::class);
$storage = $this->getMockBuilder('\OC\Files\Storage\Storage')
->disableOriginalConstructor()->getMock();
$encStorage = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption')
Expand All @@ -49,6 +52,13 @@ protected function getStream($fileName, $mode, $unencryptedSize, $wrapper = '\OC
$util->expects($this->any())
->method('getUidAndFilename')
->willReturn(['user1', $internalPath]);
$storage->expects($this->any())->method('getCache')->willReturn($cache);
$entry = new CacheEntry([
'fileid' => 5,
'encryptedVersion' => 2,
]);
$cache->expects($this->any())->method('get')->willReturn($entry );
$cache->expects($this->any())->method('update')->with(5, ['encrypted' => 3, 'encryptedVersion' => 3]);


return $wrapper::wrap($source, $internalPath,
Expand Down Expand Up @@ -208,6 +218,7 @@ public function testRewind() {

public function testSeek() {
$fileName = tempnam("/tmp", "FOO");

$stream = $this->getStream($fileName, 'w+', 0);
$this->assertEquals(6, fwrite($stream, 'foobar'));
$this->assertEquals(0, fseek($stream, 3));
Expand Down

0 comments on commit 0512d91

Please sign in to comment.