[Pkg-owncloud-commits] [owncloud] 83/215: fall back to the ownCloud default encryption module and aes128 if we read a encrypted file without a header

David Prévot taffit at moszumanska.debian.org
Tue May 5 01:01:26 UTC 2015


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch stable8
in repository owncloud.

commit 27683f944289e7b37f20ec7d877ed295d5ca66a3
Author: Bjoern Schiessle <schiessle at owncloud.com>
Date:   Fri Apr 24 13:02:06 2015 +0200

    fall back to the ownCloud default encryption module and aes128 if we read a encrypted file without a header
---
 apps/encryption/lib/crypto/crypt.php               |  9 ++++++++
 apps/encryption/lib/crypto/encryption.php          | 14 ++++++++---
 .../encryption/tests/lib/crypto/encryptionTest.php | 27 ++++++++++++++++++++++
 apps/encryption_dummy/lib/dummymodule.php          |  3 ++-
 lib/private/files/storage/wrapper/encryption.php   | 26 ++++++++++++++++-----
 lib/private/files/stream/encryption.php            | 24 ++++++++++++-------
 lib/public/encryption/iencryptionmodule.php        |  3 ++-
 tests/lib/files/stream/encryption.php              |  2 +-
 8 files changed, 88 insertions(+), 20 deletions(-)

diff --git a/apps/encryption/lib/crypto/crypt.php b/apps/encryption/lib/crypto/crypt.php
index 9ada920..782dbbe 100644
--- a/apps/encryption/lib/crypto/crypt.php
+++ b/apps/encryption/lib/crypto/crypt.php
@@ -210,6 +210,15 @@ class Crypt {
 	}
 
 	/**
+	 * get legacy cipher
+	 *
+	 * @return string
+	 */
+	public function getLegacyCipher() {
+		return self::LEGACY_CIPHER;
+	}
+
+	/**
 	 * @param string $encryptedContent
 	 * @param string $iv
 	 * @return string
diff --git a/apps/encryption/lib/crypto/encryption.php b/apps/encryption/lib/crypto/encryption.php
index 8498b42..3f29848 100644
--- a/apps/encryption/lib/crypto/encryption.php
+++ b/apps/encryption/lib/crypto/encryption.php
@@ -101,6 +101,7 @@ class Encryption implements IEncryptionModule {
 	 *
 	 * @param string $path to the file
 	 * @param string $user who read/write the file
+	 * @param string $mode php stream open mode
 	 * @param array $header contains the header data read from the file
 	 * @param array $accessList who has access to the file contains the key 'users' and 'public'
 	 *
@@ -108,12 +109,19 @@ class Encryption implements IEncryptionModule {
 	 *                       written to the header, in case of a write operation
 	 *                       or if no additional data is needed return a empty array
 	 */
-	public function begin($path, $user, array $header, array $accessList) {
+	public function begin($path, $user, $mode, array $header, array $accessList) {
 
 		if (isset($header['cipher'])) {
 			$this->cipher = $header['cipher'];
-		} else {
+		} else if (
+			$mode === 'w'
+			|| $mode === 'w+'
+			|| $mode === 'wb'
+			|| $mode === 'wb+'
+		) {
 			$this->cipher = $this->crypt->getCipher();
+		} else {
+			$this->cipher = $this->crypt->getLegacyCipher();
 		}
 
 		$this->path = $this->getPathToRealFile($path);
@@ -234,7 +242,7 @@ class Encryption implements IEncryptionModule {
 	public function decrypt($data) {
 		$result = '';
 		if (!empty($data)) {
-			$result = $this->crypt->symmetricDecryptFileContent($data, $this->fileKey);
+			$result = $this->crypt->symmetricDecryptFileContent($data, $this->fileKey, $this->cipher);
 		}
 		return $result;
 	}
diff --git a/apps/encryption/tests/lib/crypto/encryptionTest.php b/apps/encryption/tests/lib/crypto/encryptionTest.php
index 9e14a70..500433c 100644
--- a/apps/encryption/tests/lib/crypto/encryptionTest.php
+++ b/apps/encryption/tests/lib/crypto/encryptionTest.php
@@ -72,5 +72,32 @@ class EncryptionTest extends TestCase {
 		);
 	}
 
+	/**
+	 * @dataProvider dataTestBegin
+	 */
+	public function testBegin($mode, $header, $legacyCipher, $defaultCipher, $expected) {
+
+		$this->cryptMock->expects($this->any())
+			->method('getCipher')
+			->willReturn($defaultCipher);
+		$this->cryptMock->expects($this->any())
+			->method('getLegacyCipher')
+			->willReturn($legacyCipher);
+
+		$result = $this->instance->begin('/user/files/foo.txt', 'user', $mode, $header, []);
+
+		$this->assertArrayHasKey('cipher', $result);
+		$this->assertSame($expected, $result['cipher']);
+	}
+
+	public function dataTestBegin() {
+		return array(
+			array('w', ['cipher' => 'myCipher'], 'legacyCipher', 'defaultCipher', 'myCipher'),
+			array('r', ['cipher' => 'myCipher'], 'legacyCipher', 'defaultCipher', 'myCipher'),
+			array('w', [], 'legacyCipher', 'defaultCipher', 'defaultCipher'),
+			array('r', [], 'legacyCipher', 'defaultCipher', 'legacyCipher'),
+		);
+	}
+
 
 }
\ No newline at end of file
diff --git a/apps/encryption_dummy/lib/dummymodule.php b/apps/encryption_dummy/lib/dummymodule.php
index e974ee4..141edfb 100644
--- a/apps/encryption_dummy/lib/dummymodule.php
+++ b/apps/encryption_dummy/lib/dummymodule.php
@@ -53,6 +53,7 @@ class DummyModule implements IEncryptionModule {
 	 *
 	 * @param string $path to the file
 	 * @param string $user who read/write the file (null for public access)
+	 * @param string $mode php stream open mode
 	 * @param array $header contains the header data read from the file
 	 * @param array $accessList who has access to the file contains the key 'users' and 'public'
 	 *
@@ -60,7 +61,7 @@ class DummyModule implements IEncryptionModule {
 	 *                       written to the header, in case of a write operation
 	 *                       or if no additional data is needed return a empty array
 	 */
-	public function begin($path, $user, array $header, array $accessList) {
+	public function begin($path, $user, $mode, array $header, array $accessList) {
 		return array();
 	}
 
diff --git a/lib/private/files/storage/wrapper/encryption.php b/lib/private/files/storage/wrapper/encryption.php
index 0dc59cb..5e96f50 100644
--- a/lib/private/files/storage/wrapper/encryption.php
+++ b/lib/private/files/storage/wrapper/encryption.php
@@ -162,8 +162,9 @@ class Encryption extends Wrapper {
 	public function file_get_contents($path) {
 
 		$encryptionModule = $this->getEncryptionModule($path);
+		$info = $this->getCache()->get($path);
 
-		if ($encryptionModule) {
+		if ($encryptionModule || $info['encrypted'] === true) {
 			$handle = $this->fopen($path, "r");
 			if (!$handle) {
 				return false;
@@ -283,7 +284,8 @@ class Encryption extends Wrapper {
 		$encryptionEnabled = $this->encryptionManager->isEnabled();
 		$shouldEncrypt = false;
 		$encryptionModule = null;
-		$header = $this->getHeader($path);
+		$rawHeader = $this->getHeader($path);
+		$header = $this->util->readHeader($rawHeader);
 		$fullPath = $this->getFullPath($path);
 		$encryptionModuleId = $this->util->getEncryptionModuleId($header);
 
@@ -319,10 +321,18 @@ class Encryption extends Wrapper {
 					$shouldEncrypt = $encryptionModule->shouldEncrypt($fullPath);
 				}
 			} else {
+				$info = $this->getCache()->get($path);
 				// only get encryption module if we found one in the header
+				// or if file should be encrypted according to the file cache
 				if (!empty($encryptionModuleId)) {
 					$encryptionModule = $this->encryptionManager->getEncryptionModule($encryptionModuleId);
 					$shouldEncrypt = true;
+				} else if(empty($encryptionModuleId) && $info['encrypted'] === true) {
+					// we come from a old installation. No header and/or no module defined
+					// but the file is encrypted. In this case we need to use the
+					// OC_DEFAULT_MODULE to read the file
+					$encryptionModule = $this->encryptionManager->getEncryptionModule('OC_DEFAULT_MODULE');
+					$shouldEncrypt = true;
 				}
 			}
 		} catch (ModuleDoesNotExistsException $e) {
@@ -341,7 +351,7 @@ class Encryption extends Wrapper {
 			$source = $this->storage->fopen($path, $mode);
 			$handle = \OC\Files\Stream\Encryption::wrap($source, $path, $fullPath, $header,
 				$this->uid, $encryptionModule, $this->storage, $this, $this->util, $this->fileHelper, $mode,
-				$size, $unencryptedSize);
+				$size, $unencryptedSize, strlen($rawHeader));
 			return $handle;
 		} else {
 			return $this->storage->fopen($path, $mode);
@@ -419,10 +429,13 @@ class Encryption extends Wrapper {
 		$header = '';
 		if ($this->storage->file_exists($path)) {
 			$handle = $this->storage->fopen($path, 'r');
-			$header = fread($handle, $this->util->getHeaderSize());
+			$firstBlock = fread($handle, $this->util->getHeaderSize());
 			fclose($handle);
+			if (substr($firstBlock, 0, strlen(Util::HEADER_START)) === Util::HEADER_START) {
+				$header = $firstBlock;
+			}
 		}
-		return $this->util->readHeader($header);
+		return $header;
 	}
 
 	/**
@@ -435,7 +448,8 @@ class Encryption extends Wrapper {
 	 */
 	protected function getEncryptionModule($path) {
 		$encryptionModule = null;
-		$header = $this->getHeader($path);
+		$rawHeader = $this->getHeader($path);
+		$header = $this->util->readHeader($rawHeader);
 		$encryptionModuleId = $this->util->getEncryptionModuleId($header);
 		if (!empty($encryptionModuleId)) {
 			try {
diff --git a/lib/private/files/stream/encryption.php b/lib/private/files/stream/encryption.php
index 5f39207..0262405 100644
--- a/lib/private/files/stream/encryption.php
+++ b/lib/private/files/stream/encryption.php
@@ -59,6 +59,9 @@ class Encryption extends Wrapper {
 	protected $unencryptedSize;
 
 	/** @var integer */
+	protected $headerSize;
+
+	/** @var integer */
 	protected $unencryptedBlockSize;
 
 	/** @var array */
@@ -104,7 +107,8 @@ class Encryption extends Wrapper {
 			'util',
 			'size',
 			'unencryptedSize',
-			'encryptionStorage'
+			'encryptionStorage',
+			'headerSize'
 		);
 	}
 
@@ -125,6 +129,7 @@ class Encryption extends Wrapper {
 	 * @param string $mode
 	 * @param int $size
 	 * @param int $unencryptedSize
+	 * @param int $headerSize
 	 * @return resource
 	 *
 	 * @throws \BadMethodCallException
@@ -138,7 +143,8 @@ class Encryption extends Wrapper {
 								 \OC\Encryption\File $file,
 								$mode,
 								$size,
-								$unencryptedSize) {
+								$unencryptedSize,
+								$headerSize) {
 
 		$context = stream_context_create(array(
 			'ocencryption' => array(
@@ -153,7 +159,8 @@ class Encryption extends Wrapper {
 				'file' => $file,
 				'size' => $size,
 				'unencryptedSize' => $unencryptedSize,
-				'encryptionStorage' => $encStorage
+				'encryptionStorage' => $encStorage,
+				'headerSize' => $headerSize
 			)
 		));
 
@@ -235,7 +242,7 @@ class Encryption extends Wrapper {
 		}
 
 		$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, $mode, $this->header, $accessList);
 
 		if (
 			$mode === 'w'
@@ -246,7 +253,8 @@ class Encryption extends Wrapper {
 			// We're writing a new file so start write counter with 0 bytes
 			$this->unencryptedSize = 0;
 			$this->writeHeader();
-			$this->size = $this->util->getHeaderSize();
+			$this->headerSize = $this->util->getHeaderSize();
+			$this->size = $this->headerSize;
 		} else {
 			$this->skipHeader();
 		}
@@ -300,7 +308,7 @@ class Encryption extends Wrapper {
 			// for seekable streams the pointer is moved back to the beginning of the encrypted block
 			// flush will start writing there when the position moves to another block
 			$positionInFile = (int)floor($this->position / $this->unencryptedBlockSize) *
-				$this->util->getBlockSize() + $this->util->getHeaderSize();
+				$this->util->getBlockSize() + $this->headerSize;
 			$resultFseek = parent::stream_seek($positionInFile);
 
 			// only allow writes on seekable streams, or at the end of the encrypted stream
@@ -367,7 +375,7 @@ class Encryption extends Wrapper {
 		}
 
 		$newFilePosition = floor($newPosition / $this->unencryptedBlockSize)
-			* $this->util->getBlockSize() + $this->util->getHeaderSize();
+			* $this->util->getBlockSize() + $this->headerSize;
 
 		$oldFilePosition = parent::stream_tell();
 		if (parent::stream_seek($newFilePosition)) {
@@ -440,7 +448,7 @@ class Encryption extends Wrapper {
 	 * read first block to skip the header
 	 */
 	protected function skipHeader() {
-		parent::stream_read($this->util->getHeaderSize());
+		parent::stream_read($this->headerSize);
 	}
 
 }
diff --git a/lib/public/encryption/iencryptionmodule.php b/lib/public/encryption/iencryptionmodule.php
index dc55f89..0dda042 100644
--- a/lib/public/encryption/iencryptionmodule.php
+++ b/lib/public/encryption/iencryptionmodule.php
@@ -50,6 +50,7 @@ interface IEncryptionModule {
 	 *
 	 * @param string $path to the file
 	 * @param string $user who read/write the file (null for public access)
+	 * @param string $mode php stream open mode
 	 * @param array $header contains the header data read from the file
 	 * @param array $accessList who has access to the file contains the key 'users' and 'public'
 	 *
@@ -58,7 +59,7 @@ interface IEncryptionModule {
 	 *                       or if no additional data is needed return a empty array
 	 * @since 8.1.0
 	 */
-	public function begin($path, $user, array $header, array $accessList);
+	public function begin($path, $user, $mode, array $header, array $accessList);
 
 	/**
 	 * last chunk received. This is the place where you can perform some final
diff --git a/tests/lib/files/stream/encryption.php b/tests/lib/files/stream/encryption.php
index 0b34de8..892491c 100644
--- a/tests/lib/files/stream/encryption.php
+++ b/tests/lib/files/stream/encryption.php
@@ -44,7 +44,7 @@ class Encryption extends \Test\TestCase {
 
 		return \OC\Files\Stream\Encryption::wrap($source, $internalPath,
 			$fullPath, $header, $uid, $encryptionModule, $storage, $encStorage,
-			$util, $file, $mode, $size, $unencryptedSize);
+			$util, $file, $mode, $size, $unencryptedSize, 8192);
 	}
 
 	/**

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud.git



More information about the Pkg-owncloud-commits mailing list