]> source.dussan.org Git - nextcloud-server.git/commitdiff
ceanup encryption code, improved return codes
authorBjoern Schiessle <schiessle@owncloud.com>
Thu, 22 May 2014 13:43:42 +0000 (15:43 +0200)
committerBjoern Schiessle <schiessle@owncloud.com>
Mon, 2 Jun 2014 11:15:11 +0000 (13:15 +0200)
apps/files_encryption/hooks/hooks.php
apps/files_encryption/lib/util.php
apps/files_encryption/tests/helper.php
apps/files_encryption/tests/util.php

index 6e375f99a8e4f31348b55ee52328be6550eeb13a..f538d38fada9646a1d8633204a61cb543baa778e 100644 (file)
@@ -51,16 +51,16 @@ class Hooks {
                $view = new \OC\Files\View('/');\r
 \r
                // ensure filesystem is loaded\r
-               if(!\OC\Files\Filesystem::$loaded) {\r
+               if (!\OC\Files\Filesystem::$loaded) {\r
                        \OC_Util::setupFS($params['uid']);\r
                }\r
 \r
                $privateKey = \OCA\Encryption\Keymanager::getPrivateKey($view, $params['uid']);\r
 \r
                // if no private key exists, check server configuration\r
-               if(!$privateKey) {\r
+               if (!$privateKey) {\r
                        //check if all requirements are met\r
-                       if(!Helper::checkRequirements() || !Helper::checkConfiguration()) {\r
+                       if (!Helper::checkRequirements() || !Helper::checkConfiguration()) {\r
                                $error_msg = $l->t("Missing requirements.");\r
                                $hint = $l->t('Please make sure that PHP 5.3.3 or newer is installed and that OpenSSL together with the PHP extension is enabled and configured properly. For now, the encryption app has been disabled.');\r
                                \OC_App::disable('files_encryption');\r
@@ -90,6 +90,8 @@ class Hooks {
                        return false;\r
                }\r
 \r
+               $result = true;\r
+\r
                // If migration not yet done\r
                if ($ready) {\r
 \r
@@ -97,15 +99,12 @@ class Hooks {
 \r
                        // Set legacy encryption key if it exists, to support\r
                        // depreciated encryption system\r
-                       if (\r
-                               $userView->file_exists('encryption.key')\r
-                               && $encLegacyKey = $userView->file_get_contents('encryption.key')\r
-                       ) {\r
+                       $encLegacyKey = $userView->file_get_contents('encryption.key');\r
+                       if ($encLegacyKey) {\r
 \r
                                $plainLegacyKey = Crypt::legacyDecrypt($encLegacyKey, $params['password']);\r
 \r
                                $session->setLegacyKey($plainLegacyKey);\r
-\r
                        }\r
 \r
                        // Encrypt existing user files\r
@@ -113,26 +112,24 @@ class Hooks {
                                $result = $util->encryptAll('/' . $params['uid'] . '/' . 'files', $session->getLegacyKey(), $params['password']);\r
                        } catch (\Exception $ex) {\r
                                \OCP\Util::writeLog('Encryption library', 'Initial encryption failed! Error: ' . $ex->getMessage(), \OCP\Util::FATAL);\r
-                               $util->resetMigrationStatus();\r
-                               \OCP\User::logout();\r
                                $result = false;\r
                        }\r
 \r
                        if ($result) {\r
-\r
                                \OC_Log::write(\r
-                                       'Encryption library', 'Encryption of existing files belonging to "' . $params['uid'] . '" completed'\r
-                                       , \OC_Log::INFO\r
-                               );\r
-\r
+                                               'Encryption library', 'Encryption of existing files belonging to "' . $params['uid'] . '" completed'\r
+                                               , \OC_Log::INFO\r
+                                       );\r
                                // Register successful migration in DB\r
                                $util->finishMigration();\r
-\r
+                       } else  {\r
+                               \OCP\Util::writeLog('Encryption library', 'Initial encryption failed!', \OCP\Util::FATAL);\r
+                               $util->resetMigrationStatus();\r
+                               \OCP\User::logout();\r
                        }\r
                }\r
 \r
-               return true;\r
-\r
+               return $result;\r
        }\r
 \r
        /**\r
index d20efc3ac7be9894eb3ed55179324103bc812e1c..fecdef288191a9e57b92efc9030eeabe58c81c21 100644 (file)
@@ -303,7 +303,7 @@ class Util {
         * Find all files and their encryption status within a directory
         * @param string $directory The path of the parent directory to search
         * @param bool $found the founded files if called again
-        * @return mixed false if 0 found, array on success. Keys: name, path
+        * @return array keys: plain, encrypted, legacy, broken
         * @note $directory needs to be a path relative to OC data dir. e.g.
         *       /admin/files NOT /backup OR /home/www/oc/data/admin/files
         */
@@ -322,11 +322,8 @@ class Util {
                        );
                }
 
-               if (
-                       $this->view->is_dir($directory)
-                       && $handle = $this->view->opendir($directory)
-               ) {
-                       if(is_resource($handle)) {
+               if ($this->view->is_dir($directory) && $handle = $this->view->opendir($directory)){
+                       if (is_resource($handle)) {
                                while (false !== ($file = readdir($handle))) {
 
                                        if ($file !== "." && $file !== "..") {
@@ -390,34 +387,16 @@ class Util {
                                                                        'name' => $file,
                                                                        'path' => $relPath
                                                                );
-
                                                        }
-
                                                }
-
                                        }
-
                                }
                        }
-
-                       \OC_FileProxy::$enabled = true;
-
-                       if (empty($found)) {
-
-                               return false;
-
-                       } else {
-
-                               return $found;
-
-                       }
-
                }
 
                \OC_FileProxy::$enabled = true;
 
-               return false;
-
+               return $found;
        }
 
        /**
@@ -571,28 +550,6 @@ class Util {
                return $result;
        }
 
-
-       /**
-        * @param string $path
-        * @return bool
-        */
-       public function isSharedPath($path) {
-
-               $trimmed = ltrim($path, '/');
-               $split = explode('/', $trimmed);
-
-               if (isset($split[2]) && $split[2] === 'Shared') {
-
-                       return true;
-
-               } else {
-
-                       return false;
-
-               }
-
-       }
-
        /**
         * encrypt versions from given file
         * @param array $filelist list of encrypted files, relative to data/user/files
@@ -808,121 +765,119 @@ class Util {
         */
        public function encryptAll($dirPath, $legacyPassphrase = null, $newPassphrase = null) {
 
+               $result = true;
+
                $found = $this->findEncFiles($dirPath);
 
-               if ($found) {
+               // Disable proxy to prevent file being encrypted twice
+               \OC_FileProxy::$enabled = false;
 
-                       // Disable proxy to prevent file being encrypted twice
-                       \OC_FileProxy::$enabled = false;
+               $versionStatus = \OCP\App::isEnabled('files_versions');
+               \OC_App::disable('files_versions');
 
-                       $versionStatus = \OCP\App::isEnabled('files_versions');
-                       \OC_App::disable('files_versions');
+               $encryptedFiles = array();
 
-                       $encryptedFiles = array();
+               // Encrypt unencrypted files
+               foreach ($found['plain'] as $plainFile) {
 
-                       // Encrypt unencrypted files
-                       foreach ($found['plain'] as $plainFile) {
+                       //get file info
+                       $fileInfo = \OC\Files\Filesystem::getFileInfo($plainFile['path']);
 
-                               //get file info
-                               $fileInfo = \OC\Files\Filesystem::getFileInfo($plainFile['path']);
+                       //relative to data/<user>/file
+                       $relPath = $plainFile['path'];
 
-                               //relative to data/<user>/file
-                               $relPath = $plainFile['path'];
+                       //relative to /data
+                       $rawPath = '/' . $this->userId . '/files/' . $plainFile['path'];
 
-                               //relative to /data
-                               $rawPath = '/' . $this->userId . '/files/' . $plainFile['path'];
-
-                               // keep timestamp
-                               $timestamp = $fileInfo['mtime'];
+                       // keep timestamp
+                       $timestamp = $fileInfo['mtime'];
 
-                               // Open plain file handle for binary reading
-                               $plainHandle = $this->view->fopen($rawPath, 'rb');
+                       // Open plain file handle for binary reading
+                       $plainHandle = $this->view->fopen($rawPath, 'rb');
 
-                               // Open enc file handle for binary writing, with same filename as original plain file
-                               $encHandle = fopen('crypt://' . $rawPath . '.part', 'wb');
+                       // Open enc file handle for binary writing, with same filename as original plain file
+                       $encHandle = fopen('crypt://' . $rawPath . '.part', 'wb');
 
-                               if (is_resource($encHandle)) {
-                                       // Move plain file to a temporary location
-                                       $size = stream_copy_to_stream($plainHandle, $encHandle);
+                       if (is_resource($encHandle) && is_resource($plainHandle)) {
+                               // Move plain file to a temporary location
+                               $size = stream_copy_to_stream($plainHandle, $encHandle);
 
-                                       fclose($encHandle);
-                                       fclose($plainHandle);
+                               fclose($encHandle);
+                               fclose($plainHandle);
 
-                                       $fakeRoot = $this->view->getRoot();
-                                       $this->view->chroot('/' . $this->userId . '/files');
+                               $fakeRoot = $this->view->getRoot();
+                               $this->view->chroot('/' . $this->userId . '/files');
 
-                                       $this->view->rename($relPath . '.part', $relPath);
+                               $this->view->rename($relPath . '.part', $relPath);
 
-                                       // set timestamp
-                                       $this->view->touch($relPath, $timestamp);
+                               // set timestamp
+                               $this->view->touch($relPath, $timestamp);
 
-                                       $encSize = $this->view->filesize($relPath);
+                               $encSize = $this->view->filesize($relPath);
 
-                                       $this->view->chroot($fakeRoot);
+                               $this->view->chroot($fakeRoot);
 
-                                       // Add the file to the cache
-                                       \OC\Files\Filesystem::putFileInfo($relPath, array(
-                                               'encrypted' => true,
-                                               'size' => $encSize,
-                                               'unencrypted_size' => $size,
-                                               'etag' => $fileInfo['etag']
-                                       ));
+                               // Add the file to the cache
+                               \OC\Files\Filesystem::putFileInfo($relPath, array(
+                                       'encrypted' => true,
+                                       'size' => $encSize,
+                                       'unencrypted_size' => $size,
+                                       'etag' => $fileInfo['etag']
+                               ));
 
-                                       $encryptedFiles[] = $relPath;
-                               }
+                               $encryptedFiles[] = $relPath;
+                       } else {
+                               \OCP\Util::writeLog('files_encryption', 'initial encryption: could not encrypt ' . $rawPath, \OCP\Util::FATAL);
+                               $result = false;
                        }
+               }
 
-                       // Encrypt legacy encrypted files
-                       if (
-                               !empty($legacyPassphrase)
-                               && !empty($newPassphrase)
-                       ) {
-
-                               foreach ($found['legacy'] as $legacyFile) {
+               // Encrypt legacy encrypted files
+               if (!empty($legacyPassphrase) && !empty($newPassphrase)) {
 
-                                       // Fetch data from file
-                                       $legacyData = $this->view->file_get_contents($legacyFile['path']);
+                       foreach ($found['legacy'] as $legacyFile) {
 
-                                       // decrypt data, generate catfile
-                                       $decrypted = Crypt::legacyBlockDecrypt($legacyData, $legacyPassphrase);
+                               // Fetch data from file
+                               $legacyData = $this->view->file_get_contents($legacyFile['path']);
 
-                                       $rawPath = $legacyFile['path'];
+                               // decrypt data, generate catfile
+                               $decrypted = Crypt::legacyBlockDecrypt($legacyData, $legacyPassphrase);
 
-                                       // enable proxy the ensure encryption is handled
-                                       \OC_FileProxy::$enabled = true;
+                               $rawPath = $legacyFile['path'];
 
-                                       // Open enc file handle for binary writing, with same filename as original plain file
-                                       $encHandle = $this->view->fopen( $rawPath, 'wb' );
+                               // enable proxy the ensure encryption is handled
+                               \OC_FileProxy::$enabled = true;
 
-                                       if (is_resource($encHandle)) {
+                               // Open enc file handle for binary writing, with same filename as original plain file
+                               $encHandle = $this->view->fopen($rawPath, 'wb');
 
-                                               // write data to stream
-                                               fwrite($encHandle, $decrypted);
+                               if (is_resource($encHandle)) {
 
-                                               // close stream
-                                               fclose($encHandle);
-                                       }
+                                       // write data to stream
+                                       fwrite($encHandle, $decrypted);
 
-                                       // disable proxy to prevent file being encrypted twice
-                                       \OC_FileProxy::$enabled = false;
+                                       // close stream
+                                       fclose($encHandle);
+                               } else {
+                                       \OCP\Util::writeLog('files_encryption', 'initial encryption: could not encrypt legacy file ' . $rawPath, \OCP\Util::FATAL);
+                                       $result = false;
                                }
+
+                               // disable proxy to prevent file being encrypted twice
+                               \OC_FileProxy::$enabled = false;
                        }
+               }
 
-                       \OC_FileProxy::$enabled = true;
+               \OC_FileProxy::$enabled = true;
 
-                       if ($versionStatus) {
-                               \OC_App::enable('files_versions');
-                       }
+               if ($versionStatus) {
+                       \OC_App::enable('files_versions');
+               }
 
-                       $this->encryptVersions($encryptedFiles);
+               $result = $result && $this->encryptVersions($encryptedFiles);
 
-                       // If files were found, return true
-                       return true;
-               } else {
+               return $result;
 
-                       // If no files were found, return false
-                       return false;
-               }
        }
 
        /**
index 4b46e976b8164f498f57be6ddff4ff9d4fab9ed8..582d8149a8ac3206728bc794965891b14003a3d1 100644 (file)
@@ -18,15 +18,20 @@ use OCA\Encryption;
 class Test_Encryption_Helper extends \PHPUnit_Framework_TestCase {
 
        const TEST_ENCRYPTION_HELPER_USER1 = "test-helper-user1";
+       const TEST_ENCRYPTION_HELPER_USER2 = "test-helper-user2";
 
        public static function setUpBeforeClass() {
                // create test user
+               \Test_Encryption_Util::loginHelper(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER2, true);
                \Test_Encryption_Util::loginHelper(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER1, true);
        }
 
        public static function tearDownAfterClass() {
                // cleanup test user
                \OC_User::deleteUser(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER1);
+               \OC_User::deleteUser(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER2);
+               \OC_Hook::clear();
+               \OC_FileProxy::clearProxies();
        }
 
        /**
@@ -81,9 +86,11 @@ class Test_Encryption_Helper extends \PHPUnit_Framework_TestCase {
 
                $path1 = "/" . self::TEST_ENCRYPTION_HELPER_USER1 . "/files/foo/bar.txt";
                $path2 = "/" . self::TEST_ENCRYPTION_HELPER_USER1 . "/cache/foo/bar.txt";
-               $path3 = "/" . self::TEST_ENCRYPTION_HELPER_USER1 . "/thumbnails/foo";
+               $path3 = "/" . self::TEST_ENCRYPTION_HELPER_USER2 . "/thumbnails/foo";
                $path4 ="/" . "/" . self::TEST_ENCRYPTION_HELPER_USER1;
 
+               \Test_Encryption_Util::loginHelper(self::TEST_ENCRYPTION_HELPER_USER1);
+
                // if we are logged-in every path should return the currently logged-in user
                $this->assertEquals(self::TEST_ENCRYPTION_HELPER_USER1, Encryption\Helper::getUser($path3));
 
index a4dcc5cc8bdcffa26e86c55cbefec523e1df21e4..2b873bb308dfbbcce013e9e73b23b46a4c2e4309 100755 (executable)
@@ -306,18 +306,6 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
                $this->view->unlink($this->userId . '/files/' . $filename);
        }
 
-       /**
-        * @medium
-        */
-       function testIsSharedPath() {
-               $sharedPath = '/user1/files/Shared/test';
-               $path = '/user1/files/test';
-
-               $this->assertTrue($this->util->isSharedPath($sharedPath));
-
-               $this->assertFalse($this->util->isSharedPath($path));
-       }
-
        function testEncryptAll() {
 
                $filename = "/encryptAll" . uniqid() . ".txt";