]> source.dussan.org Git - nextcloud-server.git/commitdiff
move check if a file should be encrypted to the pre hook
authorBjoern Schiessle <schiessle@owncloud.com>
Thu, 27 Mar 2014 12:49:48 +0000 (13:49 +0100)
committerBjoern Schiessle <schiessle@owncloud.com>
Mon, 31 Mar 2014 13:29:16 +0000 (15:29 +0200)
apps/files_encryption/lib/proxy.php
apps/files_encryption/lib/util.php

index bae1fded53d3376b7b076ab92535548d27a7aaa1..f7f5ff6f363d191f57751a860529e8a9361aaa4f 100644 (file)
@@ -3,9 +3,10 @@
 /**
  * ownCloud
  *
- * @author Sam Tuke, Robin Appelman
- * @copyright 2012 Sam Tuke samtuke@owncloud.com, Robin Appelman
- * icewind1991@gmail.com
+ * @author Bjoern Schiessle, Sam Tuke, Robin Appelman
+ * @copyright 2012 Sam Tuke <samtuke@owncloud.com>
+ *            2012 Robin Appelman <icewind1991@gmail.com>
+ *            2014 Bjoern Schiessle <schiessle@owncloud.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@@ -36,37 +37,40 @@ namespace OCA\Encryption;
  */
 class Proxy extends \OC_FileProxy {
 
-       private static $blackList = null; //mimetypes blacklisted from encryption
        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 a file requires encryption
         * @param string $path
+        * @param string $mode type of access
         * @return bool
         *
-        * Tests if server side encryption is enabled, and file is allowed by blacklists
+        * Tests if server side encryption is enabled, and if we should call the
+        * crypt stream wrapper for the given file
         */
-       private static function shouldEncrypt($path) {
+       private static function shouldEncrypt($path, $mode = 'w') {
 
                $userId = Helper::getUser($path);
 
-               if (\OCP\App::isEnabled('files_encryption') === false || Crypt::mode() !== 'server' ||
-                               strpos($path, '/' . $userId . '/files') !== 0) {
+               // don't call the crypt stream wrapper, if...
+               if (
+                               \OCP\App::isEnabled('files_encryption') === false // encryption is disabled
+                               || Crypt::mode() !== 'server'   // we are not in server-side-encryption mode
+                               || strpos($path, '/' . $userId . '/files') !== 0 // path is not in files/
+                               || substr($path, 0, 8) === 'crypt://' // we are already in crypt mode
+               ) {
                        return false;
                }
 
-               if (is_null(self::$blackList)) {
-                       self::$blackList = explode(',', \OCP\Config::getAppValue('files_encryption', 'type_blacklist', ''));
-               }
-
-               if (Crypt::isCatfileContent($path)) {
-                       return true;
-               }
-
-               $extension = substr($path, strrpos($path, '.') + 1);
+               $view = new \OC_FilesystemView('');
+               $util = new Util($view, $userId);
 
-               if (array_search($extension, self::$blackList) === false) {
+               // 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;
                }
 
@@ -220,7 +224,10 @@ class Proxy extends \OC_FileProxy {
         * @param string $mode type of access
         */
        public function preFopen($path, $mode) {
+
                self::$fopenMode[$path] = $mode;
+               self::$enableEncryption = self::shouldEncrypt($path, $mode);
+
        }
 
 
@@ -233,26 +240,14 @@ class Proxy extends \OC_FileProxy {
 
                $path = \OC\Files\Filesystem::normalizePath($path);
 
-               if (!$result) {
+               if (!$result || self::$enableEncryption === false) {
 
                        return $result;
 
                }
 
-               // split the path parts
-               $pathParts = explode('/', $path);
-
-               // don't try to encrypt/decrypt cache chunks or files in the trash bin
-               if (isset($pathParts[2]) && ($pathParts[2] === 'cache' || $pathParts[2] === 'files_trashbin')) {
-                       return $result;
-               }
-
-               // Disable encryption proxy to prevent recursive calls
-               $proxyStatus = \OC_FileProxy::$enabled;
-               \OC_FileProxy::$enabled = false;
-
                // if we remember the mode from the pre proxy we re-use it
-               // oterwise we fall back to stream_get_meta_data()
+               // otherwise we fall back to stream_get_meta_data()
                if (isset(self::$fopenMode[$path])) {
                        $mode = self::$fopenMode[$path];
                        unset(self::$fopenMode[$path]);
@@ -261,35 +256,12 @@ class Proxy extends \OC_FileProxy {
                        $mode = $meta['mode'];
                }
 
-               $view = new \OC_FilesystemView('');
-
-               $userId = Helper::getUser($path);
-               $util = new Util($view, $userId);
+               // Close the original encrypted file
+               fclose($result);
 
-               // If file is already encrypted, decrypt using crypto protocol
-               if (
-                       Crypt::mode() === 'server'
-                       && $util->isEncryptedPath($path)
-               ) {
-
-                       // 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);
-
-               } elseif (
-                               self::shouldEncrypt($path)
-                               and $mode !== 'r'
-                               and $mode !== 'rb'
-
-               ) {
-                       $result = fopen('crypt://' . $path, $mode);
-               }
-
-               // Re-enable the proxy
-               \OC_FileProxy::$enabled = $proxyStatus;
+               // Open the file using the crypto stream wrapper
+               // protocol and let it do the decryption work instead
+               $result = fopen('crypt://' . $path, $mode);
 
                return $result;
 
index 3db5a423478052c84af1f386c8db99e5ed1176a4..c3058aefa6fe60c1ff28a1b0745d27cd96f0d5fd 100644 (file)
@@ -432,25 +432,28 @@ class Util {
                $proxyStatus = \OC_FileProxy::$enabled;
                \OC_FileProxy::$enabled = false;
 
-               // we only need 24 byte from the last chunk
                $data = '';
-               $handle = $this->view->fopen($path, 'r');
-               if (is_resource($handle)) {
-                       // suppress fseek warining, we handle the case that fseek doesn't
-                       // work in the else branch
-                       if (@fseek($handle, -24, SEEK_END) === 0) {
-                               $data = fgets($handle);
-                       } else {
-                               // if fseek failed on the storage we create a local copy from the file
-                               // and read this one
-                               fclose($handle);
-                               $localFile = $this->view->getLocalFile($path);
-                               $handle = fopen($localFile, 'r');
-                               if (is_resource($handle) && fseek($handle, -24, SEEK_END) === 0) {
+
+               // we only need 24 byte from the last chunk
+               if ($this->view->file_exists($path)) {
+                       $handle = $this->view->fopen($path, 'r');
+                       if (is_resource($handle)) {
+                               // suppress fseek warining, we handle the case that fseek doesn't
+                               // work in the else branch
+                               if (@fseek($handle, -24, SEEK_END) === 0) {
                                        $data = fgets($handle);
+                               } else {
+                                       // if fseek failed on the storage we create a local copy from the file
+                                       // and read this one
+                                       fclose($handle);
+                                       $localFile = $this->view->getLocalFile($path);
+                                       $handle = fopen($localFile, 'r');
+                                       if (is_resource($handle) && fseek($handle, -24, SEEK_END) === 0) {
+                                               $data = fgets($handle);
+                                       }
                                }
+                               fclose($handle);
                        }
-                       fclose($handle);
                }
 
                // re-enable proxy