Merge pull request #15774 from owncloud/jknockaert-patch-1

fix encryption header error
This commit is contained in:
Vincent Petry 2015-04-24 17:24:32 +02:00
commit f63a0c99a4
2 changed files with 71 additions and 20 deletions

View File

@ -1,7 +1,7 @@
<?php <?php
/** /**
* @author Björn Schießle <schiessle@owncloud.com> * @author Björn Schießle <schiessle@owncloud.com>
* @author jknockaert <jasper@knockaert.nl> * @author Jasper Knockaert <jasper@knockaert.nl>
* @author Thomas Müller <thomas.mueller@tmit.eu> * @author Thomas Müller <thomas.mueller@tmit.eu>
* *
* @copyright Copyright (c) 2015, ownCloud, Inc. * @copyright Copyright (c) 2015, ownCloud, Inc.
@ -221,10 +221,9 @@ class Encryption extends Wrapper {
|| $mode === 'w+' || $mode === 'w+'
|| $mode === 'wb' || $mode === 'wb'
|| $mode === 'wb+' || $mode === 'wb+'
|| $mode === 'r+'
|| $mode === 'rb+'
) { ) {
// We're writing a new file so start write counter with 0 bytes
$this->unencryptedSize = 0;
$this->size = 0;
$this->readOnly = false; $this->readOnly = false;
} else { } else {
$this->readOnly = true; $this->readOnly = true;
@ -238,6 +237,20 @@ class Encryption extends Wrapper {
$accessList = $this->file->getAccessList($sharePath); $accessList = $this->file->getAccessList($sharePath);
$this->newHeader = $this->encryptionModule->begin($this->fullPath, $this->uid, $this->header, $accessList); $this->newHeader = $this->encryptionModule->begin($this->fullPath, $this->uid, $this->header, $accessList);
if (
$mode === 'w'
|| $mode === 'w+'
|| $mode === 'wb'
|| $mode === 'wb+'
) {
// We're writing a new file so start write counter with 0 bytes
$this->unencryptedSize = 0;
$this->writeHeader();
$this->size = $this->util->getHeaderSize();
} else {
$this->skipHeader();
}
return true; return true;
} }
@ -250,11 +263,6 @@ class Encryption extends Wrapper {
$result = ''; $result = '';
// skip the header if we read the file from the beginning
if ($this->position === 0) {
parent::stream_read($this->util->getHeaderSize());
}
// $count = min($count, $this->unencryptedSize - $this->position); // $count = min($count, $this->unencryptedSize - $this->position);
while ($count > 0) { while ($count > 0) {
$remainingLength = $count; $remainingLength = $count;
@ -281,11 +289,6 @@ class Encryption extends Wrapper {
public function stream_write($data) { public function stream_write($data) {
if ($this->position === 0) {
$this->writeHeader();
$this->size = $this->util->getHeaderSize();
}
$length = 0; $length = 0;
// loop over $data to fit it in 6126 sized unencrypted blocks // loop over $data to fit it in 6126 sized unencrypted blocks
while (strlen($data) > 0) { while (strlen($data) > 0) {
@ -428,9 +431,16 @@ class Encryption extends Wrapper {
* @return integer * @return integer
* @throws EncryptionHeaderKeyExistsException if header key is already in use * @throws EncryptionHeaderKeyExistsException if header key is already in use
*/ */
private function writeHeader() { protected function writeHeader() {
$header = $this->util->createHeader($this->newHeader, $this->encryptionModule); $header = $this->util->createHeader($this->newHeader, $this->encryptionModule);
return parent::stream_write($header); return parent::stream_write($header);
} }
/**
* read first block to skip the header
*/
protected function skipHeader() {
parent::stream_read($this->util->getHeaderSize());
}
} }

View File

@ -55,6 +55,7 @@ class Encryption extends \Test\TestCase {
$fileExists, $fileExists,
$expectedSharePath, $expectedSharePath,
$expectedSize, $expectedSize,
$expectedUnencryptedSize,
$expectedReadOnly) { $expectedReadOnly) {
// build mocks // build mocks
@ -77,9 +78,15 @@ class Encryption extends \Test\TestCase {
return array(); return array();
})); }));
$utilMock = $this->getMockBuilder('\OC\Encryption\Util')
->disableOriginalConstructor()->getMock();
$utilMock->expects($this->any())
->method('getHeaderSize')
->willReturn(8192);
// get a instance of the stream wrapper // get a instance of the stream wrapper
$streamWrapper = $this->getMockBuilder('\OC\Files\Stream\Encryption') $streamWrapper = $this->getMockBuilder('\OC\Files\Stream\Encryption')
->setMethods(['loadContext'])->disableOriginalConstructor()->getMock(); ->setMethods(['loadContext', 'writeHeader', 'skipHeader'])->disableOriginalConstructor()->getMock();
// set internal properties of the stream wrapper // set internal properties of the stream wrapper
$stream = new \ReflectionClass('\OC\Files\Stream\Encryption'); $stream = new \ReflectionClass('\OC\Files\Stream\Encryption');
@ -95,6 +102,10 @@ class Encryption extends \Test\TestCase {
$file->setAccessible(true); $file->setAccessible(true);
$file->setValue($streamWrapper, $fileMock); $file->setValue($streamWrapper, $fileMock);
$file->setAccessible(false); $file->setAccessible(false);
$util = $stream->getProperty('util');
$util->setAccessible(true);
$util->setValue($streamWrapper, $utilMock);
$util->setAccessible(false);
$fullPathP = $stream->getProperty('fullPath'); $fullPathP = $stream->getProperty('fullPath');
$fullPathP->setAccessible(true); $fullPathP->setAccessible(true);
$fullPathP->setValue($streamWrapper, $fullPath); $fullPathP->setValue($streamWrapper, $fullPath);
@ -118,7 +129,7 @@ class Encryption extends \Test\TestCase {
$unencryptedSize = $stream->getProperty('unencryptedSize'); $unencryptedSize = $stream->getProperty('unencryptedSize');
$unencryptedSize->setAccessible(true); $unencryptedSize->setAccessible(true);
$this->assertSame($expectedSize, $this->assertSame($expectedUnencryptedSize,
$unencryptedSize->getValue($streamWrapper) $unencryptedSize->getValue($streamWrapper)
); );
$unencryptedSize->setAccessible(false); $unencryptedSize->setAccessible(false);
@ -133,9 +144,9 @@ class Encryption extends \Test\TestCase {
public function dataProviderStreamOpen() { public function dataProviderStreamOpen() {
return array( return array(
array('r', '/foo/bar/test.txt', true, '/foo/bar/test.txt', null, true), array('r', '/foo/bar/test.txt', true, '/foo/bar/test.txt', null, null, true),
array('r', '/foo/bar/test.txt', false, '/foo/bar', null, true), array('r', '/foo/bar/test.txt', false, '/foo/bar', null, null, true),
array('w', '/foo/bar/test.txt', true, '/foo/bar/test.txt', 0, false), array('w', '/foo/bar/test.txt', true, '/foo/bar/test.txt', 8192, 0, false),
); );
} }
@ -152,6 +163,36 @@ class Encryption extends \Test\TestCase {
unlink($fileName); unlink($fileName);
} }
public function testWriteWriteRead() {
$fileName = tempnam("/tmp", "FOO");
$stream = $this->getStream($fileName, 'w+', 0);
$this->assertEquals(6, fwrite($stream, 'foobar'));
fclose($stream);
$stream = $this->getStream($fileName, 'r+', 6);
$this->assertEquals(3, fwrite($stream, 'bar'));
fclose($stream);
$stream = $this->getStream($fileName, 'r', 6);
$this->assertEquals('barbar', fread($stream, 100));
fclose($stream);
}
public function testRewind() {
$fileName = tempnam("/tmp", "FOO");
$stream = $this->getStream($fileName, 'w+', 0);
$this->assertEquals(6, fwrite($stream, 'foobar'));
$this->assertEquals(TRUE, rewind($stream));
$this->assertEquals('foobar', fread($stream, 100));
$this->assertEquals(TRUE, rewind($stream));
$this->assertEquals(3, fwrite($stream, 'bar'));
fclose($stream);
$stream = $this->getStream($fileName, 'r', 6);
$this->assertEquals('barbar', fread($stream, 100));
fclose($stream);
}
public function testSeek() { public function testSeek() {
$fileName = tempnam("/tmp", "FOO"); $fileName = tempnam("/tmp", "FOO");
$stream = $this->getStream($fileName, 'w+', 0); $stream = $this->getStream($fileName, 'w+', 0);