diff options
author | Björn Schießle <bjoern@schiessle.org> | 2015-07-17 21:42:32 +0200 |
---|---|---|
committer | Björn Schießle <bjoern@schiessle.org> | 2015-07-17 21:42:32 +0200 |
commit | f363fc2d4ad557159cbf6eac8ed1fedde316e380 (patch) | |
tree | 6b5d1757ccb7f23c35b8991fd24bc4df25a76b88 /lib/private/files/storage | |
parent | 37d085901b5eec59d1cf79356c7e8656599bc638 (diff) | |
parent | 16d8014cdd9caf17ec6887d9c6538c2ea7c8b6a6 (diff) | |
download | nextcloud-server-f363fc2d4ad557159cbf6eac8ed1fedde316e380.tar.gz nextcloud-server-f363fc2d4ad557159cbf6eac8ed1fedde316e380.zip |
Merge pull request #17540 from owncloud/enc_detect_legacy_files2
make sure that we always detect legacy files correctly
Diffstat (limited to 'lib/private/files/storage')
-rw-r--r-- | lib/private/files/storage/wrapper/encryption.php | 110 |
1 files changed, 95 insertions, 15 deletions
diff --git a/lib/private/files/storage/wrapper/encryption.php b/lib/private/files/storage/wrapper/encryption.php index 8818b822fa7..61290791faa 100644 --- a/lib/private/files/storage/wrapper/encryption.php +++ b/lib/private/files/storage/wrapper/encryption.php @@ -31,6 +31,7 @@ use OC\Encryption\Util; use OC\Files\Filesystem; use OC\Files\Mount\Manager; use OC\Files\Storage\LocalTempFileTrait; +use OCP\Encryption\Exceptions\GenericEncryptionException; use OCP\Encryption\IFile; use OCP\Encryption\IManager; use OCP\Encryption\Keys\IStorage; @@ -174,9 +175,8 @@ class Encryption extends Wrapper { public function file_get_contents($path) { $encryptionModule = $this->getEncryptionModule($path); - $info = $this->getCache()->get($path); - if ($encryptionModule || $info['encrypted'] === true) { + if ($encryptionModule) { $handle = $this->fopen($path, "r"); if (!$handle) { return false; @@ -338,14 +338,15 @@ class Encryption extends Wrapper { * @param string $path * @param string $mode * @return resource + * @throws GenericEncryptionException + * @throws ModuleDoesNotExistsException */ public function fopen($path, $mode) { $encryptionEnabled = $this->encryptionManager->isEnabled(); $shouldEncrypt = false; $encryptionModule = null; - $rawHeader = $this->getHeader($path); - $header = $this->util->readHeader($rawHeader); + $header = $this->getHeader($path); $fullPath = $this->getFullPath($path); $encryptionModuleId = $this->util->getEncryptionModuleId($header); @@ -380,6 +381,10 @@ class Encryption extends Wrapper { || $mode === 'wb' || $mode === 'wb+' ) { + // don't overwrite encrypted files if encyption is not enabled + if ($targetIsEncrypted && $encryptionEnabled === false) { + throw new GenericEncryptionException('Tried to access encrypted file but encryption is not enabled'); + } if ($encryptionEnabled) { // if $encryptionModuleId is empty, the default module will be used $encryptionModule = $this->encryptionManager->getEncryptionModule($encryptionModuleId); @@ -398,6 +403,7 @@ class Encryption extends Wrapper { // OC_DEFAULT_MODULE to read the file $encryptionModule = $this->encryptionManager->getEncryptionModule('OC_DEFAULT_MODULE'); $shouldEncrypt = true; + $targetIsEncrypted = true; } } } catch (ModuleDoesNotExistsException $e) { @@ -416,7 +422,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, strlen($rawHeader)); + $size, $unencryptedSize, $this->getHeaderSize($path)); return $handle; } @@ -606,27 +612,101 @@ class Encryption extends Wrapper { } /** + * read first block of encrypted file, typically this will contain the + * encryption header + * + * @param string $path + * @return string + */ + protected function readFirstBlock($path) { + $firstBlock = ''; + if ($this->storage->file_exists($path)) { + $handle = $this->storage->fopen($path, 'r'); + $firstBlock = fread($handle, $this->util->getHeaderSize()); + fclose($handle); + } + return $firstBlock; + } + + /** + * return header size of given file + * + * @param string $path + * @return int + */ + protected function getHeaderSize($path) { + $headerSize = 0; + $realFile = $this->util->stripPartialFileExtension($path); + if ($this->storage->file_exists($realFile)) { + $path = $realFile; + } + $firstBlock = $this->readFirstBlock($path); + + if (substr($firstBlock, 0, strlen(Util::HEADER_START)) === Util::HEADER_START) { + $headerSize = strlen($firstBlock); + } + + return $headerSize; + } + + /** + * parse raw header to array + * + * @param string $rawHeader + * @return array + */ + protected function parseRawHeader($rawHeader) { + $result = array(); + if (substr($rawHeader, 0, strlen(Util::HEADER_START)) === Util::HEADER_START) { + $header = $rawHeader; + $endAt = strpos($header, Util::HEADER_END); + if ($endAt !== false) { + $header = substr($header, 0, $endAt + strlen(Util::HEADER_END)); + + // +1 to not start with an ':' which would result in empty element at the beginning + $exploded = explode(':', substr($header, strlen(Util::HEADER_START)+1)); + + $element = array_shift($exploded); + while ($element !== Util::HEADER_END) { + $result[$element] = array_shift($exploded); + $element = array_shift($exploded); + } + } + } + + return $result; + } + + /** * read header from file * * @param string $path * @return array */ protected function getHeader($path) { - $header = ''; $realFile = $this->util->stripPartialFileExtension($path); if ($this->storage->file_exists($realFile)) { $path = $realFile; } - if ($this->storage->file_exists($path)) { - $handle = $this->storage->fopen($path, 'r'); - $firstBlock = fread($handle, $this->util->getHeaderSize()); - fclose($handle); - if (substr($firstBlock, 0, strlen(Util::HEADER_START)) === Util::HEADER_START) { - $header = $firstBlock; + $firstBlock = $this->readFirstBlock($path); + $result = $this->parseRawHeader($firstBlock); + + // if the header doesn't contain a encryption module we check if it is a + // legacy file. If true, we add the default encryption module + if (!isset($result[Util::HEADER_ENCRYPTION_MODULE_KEY])) { + if (!empty($result)) { + $result[Util::HEADER_ENCRYPTION_MODULE_KEY] = 'OC_DEFAULT_MODULE'; + } else { + // if the header was empty we have to check first if it is a encrypted file at all + $info = $this->getCache()->get($path); + if (isset($info['encrypted']) && $info['encrypted'] === true) { + $result[Util::HEADER_ENCRYPTION_MODULE_KEY] = 'OC_DEFAULT_MODULE'; + } } } - return $header; + + return $result; } /** @@ -639,8 +719,7 @@ class Encryption extends Wrapper { */ protected function getEncryptionModule($path) { $encryptionModule = null; - $rawHeader = $this->getHeader($path); - $header = $this->util->readHeader($rawHeader); + $header = $this->getHeader($path); $encryptionModuleId = $this->util->getEncryptionModuleId($header); if (!empty($encryptionModuleId)) { try { @@ -675,4 +754,5 @@ class Encryption extends Wrapper { return false; } + } |