summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/encryption/lib/crypto/crypt.php9
-rw-r--r--apps/encryption/lib/crypto/encryption.php14
-rw-r--r--apps/encryption/tests/lib/crypto/encryptionTest.php27
-rw-r--r--apps/encryption_dummy/lib/dummymodule.php3
-rw-r--r--lib/private/files/storage/wrapper/encryption.php26
-rw-r--r--lib/private/files/stream/encryption.php24
-rw-r--r--lib/public/encryption/iencryptionmodule.php3
-rw-r--r--tests/lib/files/stream/encryption.php2
8 files changed, 88 insertions, 20 deletions
diff --git a/apps/encryption/lib/crypto/crypt.php b/apps/encryption/lib/crypto/crypt.php
index 9ada9200551..782dbbe5a35 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 8498b4223e1..3f298481680 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 9e14a70ebb0..500433c77d4 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 e974ee468e2..141edfb58f9 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 af48d3475c3..e3458cb6bba 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);
@@ -317,10 +319,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) {
@@ -339,7 +349,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);
@@ -417,10 +427,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;
}
/**
@@ -433,7 +446,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 5f39207db87..0262405f367 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 dc55f8939ef..0dda042d759 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 0b34de8ae12..892491cbc32 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);
}
/**