diff options
Diffstat (limited to 'apps/files_encryption/lib/proxy.php')
-rw-r--r-- | apps/files_encryption/lib/proxy.php | 401 |
1 files changed, 0 insertions, 401 deletions
diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php deleted file mode 100644 index b452c0d4e27..00000000000 --- a/apps/files_encryption/lib/proxy.php +++ /dev/null @@ -1,401 +0,0 @@ -<?php -/** - * @author Björn Schießle <schiessle@owncloud.com> - * @author Florin Peter <github@florin-peter.de> - * @author Joas Schilling <nickvergessen@owncloud.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <icewind@owncloud.com> - * @author Robin McCorkell <rmccorkell@karoshi.org.uk> - * @author Sam Tuke <mail@samtuke.com> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * @author Vincent Petry <pvince81@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -/** - * Encryption proxy which handles filesystem operations before and after - * execution and encrypts, and handles keyfiles accordingly. Used for - * webui. - */ - -namespace OCA\Files_Encryption; - -/** - * Class Proxy - * @package OCA\Files_Encryption - */ -class Proxy extends \OC_FileProxy { - - private static $unencryptedSizes = array(); // remember unencrypted size - private static $fopenMode = array(); // remember the fopen mode - private static $enableEncryption = false; // Enable encryption for the given path - - - /** - * check if path is excluded from encryption - * - * @param string $path relative to data/ - * @return boolean - */ - protected function isExcludedPath($path) { - - $view = new \OC\Files\View(); - - $normalizedPath = \OC\Files\Filesystem::normalizePath($path); - - $parts = explode('/', $normalizedPath); - - // we only encrypt/decrypt files in the files and files_versions folder - if (sizeof($parts) < 3) { - /** - * Less then 3 parts means, we can't match: - * - /{$uid}/files/* nor - * - /{$uid}/files_versions/* - * So this is not a path we are looking for. - */ - return true; - } - if( - !($parts[2] === 'files' && \OCP\User::userExists($parts[1])) && - !($parts[2] === 'files_versions' && \OCP\User::userExists($parts[1]))) { - - return true; - } - - if (!$view->file_exists($normalizedPath)) { - $normalizedPath = dirname($normalizedPath); - } - - // we don't encrypt server-to-server shares - list($storage, ) = \OC\Files\Filesystem::resolvePath($normalizedPath); - /** - * @var \OCP\Files\Storage $storage - */ - if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) { - return true; - } - - return false; - } - - /** - * Check if a file requires encryption - * @param string $path - * @param string $mode type of access - * @return bool - * - * Tests if server side encryption is enabled, and if we should call the - * crypt stream wrapper for the given file - */ - private function shouldEncrypt($path, $mode = 'w') { - - // don't call the crypt stream wrapper, if... - if ( - Crypt::mode() !== 'server' // we are not in server-side-encryption mode - || $this->isExcludedPath($path) // if path is excluded from encryption - || substr($path, 0, 8) === 'crypt://' // we are already in crypt mode - ) { - return false; - } - - $userId = Helper::getUser($path); - $view = new \OC\Files\View(''); - $util = new Util($view, $userId); - - // for write operation we always encrypt the files, for read operations - // we check if the existing file is encrypted or not decide if it needs to - // decrypt it. - if (($mode !== 'r' && $mode !== 'rb') || $util->isEncryptedPath($path)) { - return true; - } - - return false; - } - - /** - * @param string $path - * @param string $data - * @return bool - */ - public function preFile_put_contents($path, &$data) { - - if ($this->shouldEncrypt($path)) { - - if (!is_resource($data)) { - - // get root view - $view = new \OC\Files\View('/'); - - // get relative path - $relativePath = Helper::stripUserFilesPath($path); - - if (!isset($relativePath)) { - return true; - } - - // create random cache folder - $cacheFolder = rand(); - $path_slices = explode('/', \OC\Files\Filesystem::normalizePath($path)); - $path_slices[2] = "cache/".$cacheFolder; - $tmpPath = implode('/', $path_slices); - - $handle = fopen('crypt://' . $tmpPath, 'w'); - if (is_resource($handle)) { - - // write data to stream - fwrite($handle, $data); - - // close stream - fclose($handle); - - // disable encryption proxy to prevent recursive calls - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; - - // get encrypted content - $data = $view->file_get_contents($tmpPath); - - // store new unenecrypted size so that it can be updated - // in the post proxy - $tmpFileInfo = $view->getFileInfo($tmpPath); - if ( isset($tmpFileInfo['unencrypted_size']) ) { - self::$unencryptedSizes[\OC\Files\Filesystem::normalizePath($path)] = $tmpFileInfo['unencrypted_size']; - } - - // remove our temp file - $view->deleteAll('/' . \OCP\User::getUser() . '/cache/' . $cacheFolder); - - // re-enable proxy - our work is done - \OC_FileProxy::$enabled = $proxyStatus; - } else { - return false; - } - } - } - - return true; - - } - - /** - * update file cache with the new unencrypted size after file was written - * @param string $path - * @param mixed $result - * @return mixed - */ - public function postFile_put_contents($path, $result) { - $normalizedPath = \OC\Files\Filesystem::normalizePath($path); - if ( isset(self::$unencryptedSizes[$normalizedPath]) ) { - $view = new \OC\Files\View('/'); - $view->putFileInfo($normalizedPath, - array('encrypted' => true, 'unencrypted_size' => self::$unencryptedSizes[$normalizedPath])); - unset(self::$unencryptedSizes[$normalizedPath]); - } - - return $result; - } - - /** - * @param string $path Path of file from which has been read - * @param string $data Data that has been read from file - */ - public function postFile_get_contents($path, $data) { - - $plainData = null; - - // If data is a catfile - if ( - Crypt::mode() === 'server' - && $this->shouldEncrypt($path) - && Crypt::isCatfileContent($data) - ) { - - $handle = fopen('crypt://' . $path, 'r'); - - if (is_resource($handle)) { - while (($plainDataChunk = fgets($handle, 8192)) !== false) { - $plainData .= $plainDataChunk; - } - } - - } - - if (!isset($plainData)) { - - $plainData = $data; - - } - - return $plainData; - - } - - /** - * remember initial fopen mode because sometimes it gets changed during the request - * @param string $path path - * @param string $mode type of access - */ - public function preFopen($path, $mode) { - - self::$fopenMode[$path] = $mode; - self::$enableEncryption = $this->shouldEncrypt($path, $mode); - - } - - - /** - * @param string $path - * @param resource $result - * @return resource - */ - public function postFopen($path, $result) { - - $path = \OC\Files\Filesystem::normalizePath($path); - - if (!$result || self::$enableEncryption === false) { - - return $result; - - } - - // if we remember the mode from the pre proxy we re-use it - // otherwise we fall back to stream_get_meta_data() - if (isset(self::$fopenMode[$path])) { - $mode = self::$fopenMode[$path]; - unset(self::$fopenMode[$path]); - } else { - $meta = stream_get_meta_data($result); - $mode = $meta['mode']; - } - - // Close the original encrypted file - fclose($result); - - // Open the file using the crypto stream wrapper - // protocol and let it do the decryption work instead - $result = fopen('crypt://' . $path, $mode); - - return $result; - - } - - /** - * @param string $path - * @param array $data - * @return array - */ - public function postGetFileInfo($path, $data) { - - // if path is a folder do nothing - if (\OCP\App::isEnabled('files_encryption') && $data !== false && array_key_exists('size', $data)) { - - // Disable encryption proxy to prevent recursive calls - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; - - // get file size - $data['size'] = self::postFileSize($path, $data['size'], $data); - - // Re-enable the proxy - \OC_FileProxy::$enabled = $proxyStatus; - } - - return $data; - } - - /** - * @param string $path - * @param int $size - * @return int|bool - */ - public function postFileSize($path, $size, $fileInfo = null) { - - $view = new \OC\Files\View('/'); - - $userId = Helper::getUser($path); - $util = new Util($view, $userId); - - // if encryption is no longer enabled or if the files aren't migrated yet - // we return the default file size - if(!\OCP\App::isEnabled('files_encryption') || - $util->getMigrationStatus() !== Util::MIGRATION_COMPLETED) { - return $size; - } - - // if path is a folder do nothing - if ($view->is_dir($path)) { - $proxyState = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; - $fileInfo = $view->getFileInfo($path); - \OC_FileProxy::$enabled = $proxyState; - if (isset($fileInfo['unencrypted_size']) && $fileInfo['unencrypted_size'] > 0) { - return $fileInfo['unencrypted_size']; - } - return $size; - } - - // get relative path - $relativePath = Helper::stripUserFilesPath($path); - - // if path is empty we cannot resolve anything - if (empty($relativePath)) { - return $size; - } - - // get file info from database/cache - if (empty($fileInfo)) { - $proxyState = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; - $fileInfo = $view->getFileInfo($path); - \OC_FileProxy::$enabled = $proxyState; - } - - // if file is encrypted return real file size - if (isset($fileInfo['encrypted']) && $fileInfo['encrypted'] === true) { - // try to fix unencrypted file size if it doesn't look plausible - if ((int)$fileInfo['size'] > 0 && (int)$fileInfo['unencrypted_size'] === 0 ) { - $fixSize = $util->getFileSize($path); - $fileInfo['unencrypted_size'] = $fixSize; - // put file info if not .part file - if (!Helper::isPartialFilePath($relativePath)) { - $view->putFileInfo($path, array('unencrypted_size' => $fixSize)); - } - } - $size = $fileInfo['unencrypted_size']; - } else { - - $fileInfoUpdates = array(); - - $fixSize = $util->getFileSize($path); - if ($fixSize > 0) { - $size = $fixSize; - - $fileInfoUpdates['encrypted'] = true; - $fileInfoUpdates['unencrypted_size'] = $size; - - // put file info if not .part file - if (!Helper::isPartialFilePath($relativePath)) { - $view->putFileInfo($path, $fileInfoUpdates); - } - } - - } - return $size; - } - -} |