From b27fc42e1f0fbd1edebb1eb1818de4b4e0c4ee4b Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Thu, 21 Nov 2013 00:23:38 +0100 Subject: [PATCH 1/2] public upload now also works with encryption enabled --- apps/files/index.php | 1 - apps/files_encryption/lib/keymanager.php | 14 +++++--------- apps/files_encryption/lib/proxy.php | 7 +++---- apps/files_encryption/lib/stream.php | 14 +++++++------- apps/files_encryption/lib/util.php | 4 ++-- apps/files_encryption/tests/keymanager.php | 4 +++- apps/files_sharing/public.php | 3 --- 7 files changed, 20 insertions(+), 27 deletions(-) diff --git a/apps/files/index.php b/apps/files/index.php index 9ae378d7a1d..8f6838aa0d9 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -108,7 +108,6 @@ if ($needUpgrade) { // if the encryption app is disabled, than everything is fine (INIT_SUCCESSFUL status code) $encryptionInitStatus = 2; if (OC_App::isEnabled('files_encryption')) { - $publicUploadEnabled = 'no'; $session = new \OCA\Encryption\Session(new \OC\Files\View('/')); $encryptionInitStatus = $session->getInitialized(); } diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index b207b1437ba..b4396864a49 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -112,6 +112,7 @@ class Keymanager { * @brief store file encryption key * * @param \OC_FilesystemView $view + * @param \OCA\Encryption\Util $util * @param string $path relative path of the file, including filename * @param $userId * @param $catfile @@ -120,13 +121,11 @@ class Keymanager { * @note The keyfile is not encrypted here. Client code must * asymmetrically encrypt the keyfile before passing it to this method */ - public static function setFileKey(\OC_FilesystemView $view, $path, $userId, $catfile) { + public static function setFileKey(\OC_FilesystemView $view, $util, $path, $userId, $catfile) { $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; - $userId = Helper::getUser($path); - $util = new Util($view, $userId); list($owner, $filename) = $util->getUidAndFilename($path); // in case of system wide mount points the keys are stored directly in the data directory @@ -315,19 +314,16 @@ class Keymanager { /** * @brief store multiple share keys for a single file * @param \OC_FilesystemView $view - * @param $path + * @param \OCA\Encryption\Util $util + * @param string $path * @param array $shareKeys * @return bool */ - public static function setShareKeys(\OC_FilesystemView $view, $path, array $shareKeys) { + public static function setShareKeys(\OC_FilesystemView $view, $util, $path, array $shareKeys) { // $shareKeys must be an array with the following format: // [userId] => [encrypted key] - $userId = Helper::getUser($path); - - $util = new Util($view, $userId); - list($owner, $filename) = $util->getUidAndFilename($path); // in case of system wide mount points the keys are stored directly in the data directory diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index f7253b4591b..43d451d67c8 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -47,8 +47,10 @@ class Proxy extends \OC_FileProxy { */ private static function shouldEncrypt($path) { + $userId = Helper::getUser($path); + if (\OCP\App::isEnabled('files_encryption') === false || Crypt::mode() !== 'server' || - strpos($path, '/' . \OCP\User::getUser() . '/files') !== 0) { + strpos($path, '/' . $userId . '/files') !== 0) { return false; } @@ -244,9 +246,6 @@ class Proxy extends \OC_FileProxy { // split the path parts $pathParts = explode('/', $path); - // get relative path - $relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path); - // FIXME: handling for /userId/cache used by webdav for chunking. The cache chunks are NOT encrypted if (isset($pathParts[2]) && $pathParts[2] === 'cache') { return $result; diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 2497e56e898..3fbcf7db3e4 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -90,11 +90,14 @@ class Stream { $this->rootView = new \OC_FilesystemView('/'); } + // rawPath is relative to the data directory + $this->rawPath = \OC\Files\Filesystem::normalizePath(str_replace('crypt://', '', $path)); + $this->session = new \OCA\Encryption\Session($this->rootView); $this->privateKey = $this->session->getPrivateKey(); - $userId = Helper::getUser($path); + $userId = Helper::getUser($this->rawPath); $util = new Util($this->rootView, $userId); @@ -102,9 +105,6 @@ class Stream { // public share key ID $this->userId = $util->getUserId(); - // rawPath is relative to the data directory - $this->rawPath = \OC\Files\Filesystem::normalizePath(str_replace('crypt://', '', $path)); - // Strip identifier text from path, this gives us the path relative to data//files $this->relPath = Helper::stripUserFilesPath($this->rawPath); // if raw path doesn't point to a real file, check if it is a version or a file in the trash bin @@ -518,7 +518,7 @@ class Stream { $util = new Util($this->rootView, $userId); // Get all users sharing the file includes current user - $uniqueUserIds = $util->getSharingUsersArray($sharingEnabled, $this->relPath, $this->userId); + $uniqueUserIds = $util->getSharingUsersArray($sharingEnabled, $this->relPath, $userId); $checkedUserIds = $util->filterShareReadyUsers($uniqueUserIds); // Fetch public keys for all sharing users @@ -528,10 +528,10 @@ class Stream { $this->encKeyfiles = Crypt::multiKeyEncrypt($this->plainKey, $publicKeys); // Save the new encrypted file key - Keymanager::setFileKey($this->rootView, $this->relPath, $this->userId, $this->encKeyfiles['data']); + Keymanager::setFileKey($this->rootView, $util, $this->relPath, $userId, $this->encKeyfiles['data']); // Save the sharekeys - Keymanager::setShareKeys($this->rootView, $this->relPath, $this->encKeyfiles['keys']); + Keymanager::setShareKeys($this->rootView, $util, $this->relPath, $this->encKeyfiles['keys']); // Re-enable proxy - our work is done \OC_FileProxy::$enabled = $proxyStatus; diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 1e8b852fb31..b15c61f599e 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -1097,8 +1097,8 @@ class Util { // Save the recrypted key to it's owner's keyfiles directory // Save new sharekeys to all necessary user directory if ( - !Keymanager::setFileKey($this->view, $filePath, $fileOwner, $multiEncKey['data']) - || !Keymanager::setShareKeys($this->view, $filePath, $multiEncKey['keys']) + !Keymanager::setFileKey($this->view, $this, $filePath, $fileOwner, $multiEncKey['data']) + || !Keymanager::setShareKeys($this->view, $this, $filePath, $multiEncKey['keys']) ) { \OCP\Util::writeLog('Encryption library', diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php index ad6bbd3a7e9..72ee270ee59 100644 --- a/apps/files_encryption/tests/keymanager.php +++ b/apps/files_encryption/tests/keymanager.php @@ -145,13 +145,15 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { $file = 'unittest-' . time() . '.txt'; + $util = new Encryption\Util($this->view, $this->userId); + // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $this->view->file_put_contents($this->userId . '/files/' . $file, $this->dataShort); - Encryption\Keymanager::setFileKey($this->view, $file, $this->userId, $key); + Encryption\Keymanager::setFileKey($this->view, $util, $file, $this->userId, $key); $this->assertTrue($this->view->file_exists('/' . $this->userId . '/files_encryption/keyfiles/' . $file . '.key')); diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index d59f9b7401a..f8091967012 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -152,9 +152,6 @@ if (isset($path)) { $tmpl->assign('sharingToken', $token); $tmpl->assign('disableSharing', true); $allowPublicUploadEnabled = (bool) ($linkItem['permissions'] & OCP\PERMISSION_CREATE); - if (\OCP\App::isEnabled('files_encryption')) { - $allowPublicUploadEnabled = false; - } if (OC_Appconfig::getValue('core', 'shareapi_allow_public_upload', 'yes') === 'no') { $allowPublicUploadEnabled = false; } From d2e6f7d9790d42faf9d79b7beb07b2d287fd2da3 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Thu, 21 Nov 2013 15:57:49 +0100 Subject: [PATCH 2/2] check HTTP Referer to check if we come from public.php or from a internal page. Necessary to detect public access also if a user is logged in. --- apps/files_encryption/lib/helper.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index e66a84d909f..897b5d46620 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -225,7 +225,7 @@ class Helper { * @return bool */ public static function isPublicAccess() { - if (\OCP\USER::getUser() === false) { + if (strpos($_SERVER['HTTP_REFERER'], 'public.php') !== false) { return true; } else { return false; @@ -252,16 +252,22 @@ class Helper { return $relPath; } + /** + * @brief get user from the path, because we can't assume that \OCP\User::getUser() + * will always return the right result + * @param type $path + * @return boolean + */ public static function getUser($path) { $user = \OCP\User::getUser(); - // if we are logged in, than we return the userid - if ($user) { + // if we are logged in and if we don't come from a public URL, then we return the userid + if ($user && strpos($_SERVER['HTTP_REFERER'], 'public.php') === false) { return $user; } - // if no user is logged in we try to access a publically shared files. + // ...otherwise we try to access a publically shared files. // In this case we need to try to get the user from the path $trimmed = ltrim($path, '/');