diff options
-rw-r--r-- | apps/files_encryption/hooks/hooks.php | 28 | ||||
-rwxr-xr-x | apps/files_encryption/lib/helper.php | 11 | ||||
-rwxr-xr-x | apps/files_encryption/lib/keymanager.php | 125 | ||||
-rw-r--r-- | apps/files_encryption/lib/util.php | 50 | ||||
-rwxr-xr-x | apps/files_encryption/tests/util.php | 2 | ||||
-rw-r--r-- | apps/files_sharing/public.php | 3 | ||||
-rw-r--r-- | apps/files_trashbin/lib/trash.php | 28 | ||||
-rw-r--r-- | core/js/share.js | 4 | ||||
-rw-r--r-- | lib/config.php | 3 |
9 files changed, 174 insertions, 80 deletions
diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 197982010f9..b2a17f6bca5 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -476,10 +476,19 @@ class Hooks { $util = new Util($view, $userId);
// Format paths to be relative to user files dir
- $oldKeyfilePath = \OC\Files\Filesystem::normalizePath(
- $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $params['oldpath']);
- $newKeyfilePath = \OC\Files\Filesystem::normalizePath(
- $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $params['newpath']);
+ if ($util->isSystemWideMountPoint($params['oldpath'])) {
+ $baseDir = 'files_encryption/';
+ $oldKeyfilePath = $baseDir . 'keyfiles/' . $params['oldpath'];
+ } else {
+ $baseDir = $userId . '/' . 'files_encryption/';
+ $oldKeyfilePath = $baseDir . 'keyfiles/' . $params['oldpath'];
+ }
+
+ if ($util->isSystemWideMountPoint($params['newpath'])) {
+ $newKeyfilePath = $baseDir . 'keyfiles/' . $params['newpath'];
+ } else {
+ $newKeyfilePath = $baseDir . 'keyfiles/' . $params['newpath'];
+ }
// add key ext if this is not an folder
if (!$view->is_dir($oldKeyfilePath)) {
@@ -487,8 +496,9 @@ class Hooks { $newKeyfilePath .= '.key';
// handle share-keys
- $localKeyPath = $view->getLocalFile($userId . '/files_encryption/share-keys/' . $params['oldpath']);
- $matches = glob(preg_quote($localKeyPath) . '*.shareKey');
+ $localKeyPath = $view->getLocalFile($baseDir . 'share-keys/' . $params['oldpath']);
+ $escapedPath = Helper::escapeGlobPattern($localKeyPath);
+ $matches = glob($escapedPath . '*.shareKey');
foreach ($matches as $src) {
$dst = \OC\Files\Filesystem::normalizePath(str_replace($params['oldpath'], $params['newpath'], $src));
@@ -502,10 +512,8 @@ class Hooks { } else {
// handle share-keys folders
- $oldShareKeyfilePath = \OC\Files\Filesystem::normalizePath(
- $userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $params['oldpath']);
- $newShareKeyfilePath = \OC\Files\Filesystem::normalizePath(
- $userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $params['newpath']);
+ $oldShareKeyfilePath = $baseDir . 'share-keys/' . $params['oldpath'];
+ $newShareKeyfilePath = $baseDir . 'share-keys/' . $params['newpath'];
// create destination folder if not exists
if (!$view->file_exists(dirname($newShareKeyfilePath))) {
diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index 31cf48a0393..6eee8fed6a6 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -218,7 +218,6 @@ class Helper { exit(); } - /** * check requirements for encryption app. * @return bool true if requirements are met @@ -233,4 +232,14 @@ class Helper { return (bool) $result; } + + /** + * @brief glob uses different pattern than regular expressions, escape glob pattern only + * @param unescaped path + * @return escaped path + */ + public static function escapeGlobPattern($path) { + return preg_replace('/(\*|\?|\[)/', '[$1]', $path); + } } + diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index e911c1785df..b2fd650f18d 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -126,7 +126,12 @@ class Keymanager { $util = new Util($view, \OCP\User::getUser()); list($owner, $filename) = $util->getUidAndFilename($path); - $basePath = '/' . $owner . '/files_encryption/keyfiles'; + // in case of system wide mount points the keys are stored directly in the data directory + if ($util->isSystemWideMountPoint($filename)) { + $basePath = '/files_encryption/keyfiles'; + } else { + $basePath = '/' . $owner . '/files_encryption/keyfiles'; + } $targetPath = self::keySetPreparation($view, $filename, $basePath, $owner); @@ -233,7 +238,12 @@ class Keymanager { list($owner, $filename) = $util->getUidAndFilename($filePath); $filePath_f = ltrim($filename, '/'); - $keyfilePath = '/' . $owner . '/files_encryption/keyfiles/' . $filePath_f . '.key'; + // in case of system wide mount points the keys are stored directly in the data directory + if ($util->isSystemWideMountPoint($filename)) { + $keyfilePath = '/files_encryption/keyfiles/' . $filePath_f . '.key'; + } else { + $keyfilePath = '/' . $owner . '/files_encryption/keyfiles/' . $filePath_f . '.key'; + } $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; @@ -267,7 +277,14 @@ class Keymanager { public static function deleteFileKey(\OC_FilesystemView $view, $userId, $path) { $trimmed = ltrim($path, '/'); - $keyPath = '/' . $userId . '/files_encryption/keyfiles/' . $trimmed; + + $util = new Util($view, \OCP\User::getUser()); + + if($util->isSystemWideMountPoint($path)) { + $keyPath = '/files_encryption/keyfiles/' . $trimmed; + } else { + $keyPath = '/' . $userId . '/files_encryption/keyfiles/' . $trimmed; + } $result = false; @@ -325,57 +342,26 @@ class Keymanager { * @brief store share key * * @param \OC_FilesystemView $view - * @param string $path relative path of the file, including filename - * @param $userId + * @param string $path where the share key is stored * @param $shareKey - * @internal param string $key - * @internal param string $dbClassName * @return bool true/false * @note The keyfile is not encrypted here. Client code must * asymmetrically encrypt the keyfile before passing it to this method */ - public static function setShareKey(\OC_FilesystemView $view, $path, $userId, $shareKey) { - - // Here we need the currently logged in user, while userId can be a different user - $util = new Util($view, \OCP\User::getUser()); - - list($owner, $filename) = $util->getUidAndFilename($path); - - $basePath = '/' . $owner . '/files_encryption/share-keys'; - - $shareKeyPath = self::keySetPreparation($view, $filename, $basePath, $owner); - - // try reusing key file if part file - if (self::isPartialFilePath($shareKeyPath)) { - - $writePath = $basePath . '/' . self::fixPartialFilePath($shareKeyPath) . '.' . $userId . '.shareKey'; - - } else { - - $writePath = $basePath . '/' . $shareKeyPath . '.' . $userId . '.shareKey'; - - } + private static function setShareKey(\OC_FilesystemView $view, $path, $shareKey) { $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; - $result = $view->file_put_contents($writePath, $shareKey); + $result = $view->file_put_contents($path, $shareKey); \OC_FileProxy::$enabled = $proxyStatus; - if ( - is_int($result) - && $result > 0 - ) { - + if (is_int($result) && $result > 0) { return true; - } else { - return false; - } - } /** @@ -389,23 +375,40 @@ class Keymanager { // $shareKeys must be an array with the following format: // [userId] => [encrypted key] + // Here we need the currently logged in user, while userId can be a different user + $util = new Util($view, \OCP\User::getUser()); + + list($owner, $filename) = $util->getUidAndFilename($path); + + // in case of system wide mount points the keys are stored directly in the data directory + if ($util->isSystemWideMountPoint($filename)) { + $basePath = '/files_encryption/share-keys'; + } else { + $basePath = '/' . $owner . '/files_encryption/share-keys'; + } + + $shareKeyPath = self::keySetPreparation($view, $filename, $basePath, $owner); $result = true; foreach ($shareKeys as $userId => $shareKey) { - if (!self::setShareKey($view, $path, $userId, $shareKey)) { + // try reusing key file if part file + if (self::isPartialFilePath($shareKeyPath)) { + $writePath = $basePath . '/' . self::fixPartialFilePath($shareKeyPath) . '.' . $userId . '.shareKey'; + } else { + $writePath = $basePath . '/' . $shareKeyPath . '.' . $userId . '.shareKey'; + } + + if (!self::setShareKey($view, $writePath, $shareKey)) { // If any of the keys are not set, flag false $result = false; - } - } // Returns false if any of the keys weren't set return $result; - } /** @@ -440,8 +443,13 @@ class Keymanager { $util = new Util($view, \OCP\User::getUser()); list($owner, $filename) = $util->getUidAndFilename($filePath); - $shareKeyPath = \OC\Files\Filesystem::normalizePath( - '/' . $owner . '/files_encryption/share-keys/' . $filename . '.' . $userId . '.shareKey'); + + // in case of system wide mount points the keys are stored directly in the data directory + if ($util->isSystemWideMountPoint($filename)) { + $shareKeyPath = '/files_encryption/share-keys/' . $filename . '.' . $userId . '.shareKey'; + } else { + $shareKeyPath = '/' . $owner . '/files_encryption/share-keys/' . $filename . '.' . $userId . '.shareKey'; + } if ($view->file_exists($shareKeyPath)) { @@ -467,11 +475,21 @@ class Keymanager { */ public static function delAllShareKeys(\OC_FilesystemView $view, $userId, $filePath) { + $util = new util($view, $userId); + + if ($util->isSystemWideMountPoint($filePath)) { + $baseDir = '/files_encryption/share-keys/'; + } else { + $baseDir = $userId . '/files_encryption/share-keys/'; + } + + if ($view->is_dir($userId . '/files/' . $filePath)) { - $view->unlink($userId . '/files_encryption/share-keys/' . $filePath); + $view->unlink($baseDir . $filePath); } else { - $localKeyPath = $view->getLocalFile($userId . '/files_encryption/share-keys/' . $filePath); - $matches = glob(preg_quote($localKeyPath) . '*.shareKey'); + $localKeyPath = $view->getLocalFile($baseDir . $filePath); + $escapedPath = Helper::escapeGlobPattern($localKeyPath); + $matches = glob($escapedPath . '*.shareKey'); foreach ($matches as $ma) { $result = unlink($ma); if (!$result) { @@ -495,7 +513,11 @@ class Keymanager { list($owner, $filename) = $util->getUidAndFilename($filePath); - $shareKeyPath = \OC\Files\Filesystem::normalizePath('/' . $owner . '/files_encryption/share-keys/' . $filename); + if ($util->isSystemWideMountPoint($filename)) { + $shareKeyPath = \OC\Files\Filesystem::normalizePath('/files_encryption/share-keys/' . $filename); + } else { + $shareKeyPath = \OC\Files\Filesystem::normalizePath('/' . $owner . '/files_encryption/share-keys/' . $filename); + } if ($view->is_dir($shareKeyPath)) { @@ -526,7 +548,10 @@ class Keymanager { */ private static function recursiveDelShareKeys($dir, $userIds) { foreach ($userIds as $userId) { - $matches = glob(preg_quote($dir) . '/*' . preg_quote('.' . $userId . '.shareKey')); + $extension = '.' . $userId . '.shareKey'; + $escapedDir = Helper::escapeGlobPattern($dir); + $escapedExtension = Helper::escapeGlobPattern($extension); + $matches = glob($escapedDir . '/*' . $escapedExtension); } /** @var $matches array */ foreach ($matches as $ma) { @@ -535,7 +560,7 @@ class Keymanager { 'Could not delete shareKey; does not exist: "' . $ma . '"', \OCP\Util::ERROR); } } - $subdirs = $directories = glob(preg_quote($dir) . '/*', GLOB_ONLYDIR); + $subdirs = $directories = glob($escapedDir . '/*', GLOB_ONLYDIR); foreach ($subdirs as $subdir) { self::recursiveDelShareKeys($subdir, $userIds); } diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index b3de85254e2..50e823585d7 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -992,13 +992,9 @@ class Util { \OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled') && $this->recoveryEnabledForUser() ) { - $recoveryEnabled = true; - } else { - $recoveryEnabled = false; - } // Make sure that a share key is generated for the owner too @@ -1019,20 +1015,25 @@ class Util { // If recovery is enabled, add the // Admin UID to list of users to share to if ($recoveryEnabled) { - // Find recoveryAdmin user ID $recoveryKeyId = \OC_Appconfig::getValue('files_encryption', 'recoveryKeyId'); - // Add recoveryAdmin to list of users sharing $userIds[] = $recoveryKeyId; - } // add current user if given if ($currentUserId !== false) { - $userIds[] = $currentUserId; + } + // check if it is a group mount + if (\OCP\App::isEnabled("files_external")) { + $mount = \OC_Mount_Config::getSystemMountPoints(); + foreach ($mount as $mountPoint => $data) { + if ($mountPoint == substr($ownerPath, 1, strlen($mountPoint))) { + $userIds = array_merge($userIds, $this->getUserWithAccessToMountPoint($data['applicable']['users'], $data['applicable']['groups'])); + } + } } // Remove duplicate UIDs @@ -1042,6 +1043,20 @@ class Util { } + private function getUserWithAccessToMountPoint($users, $groups) { + $result = array(); + if (in_array('all', $users)) { + $result = \OCP\User::getUsers(); + } else { + $result = array_merge($result, $users); + foreach ($groups as $group) { + $result = array_merge($result, \OC_Group::usersInGroup($group)); + } + } + + return $result; + } + /** * @brief start migration mode to initially encrypt users data * @return boolean @@ -1179,7 +1194,7 @@ class Util { return array( $fileOwnerUid, - $filename + \OC_Filesystem::normalizePath($filename) ); } @@ -1547,4 +1562,21 @@ class Util { return $relativePath; } + /** + * @brief check if the file is stored on a system wide mount point + * @param $path relative to /data/user with leading '/' + * @return boolean + */ + public function isSystemWideMountPoint($path) { + if (\OCP\App::isEnabled("files_external")) { + $mount = \OC_Mount_Config::getSystemMountPoints(); + foreach ($mount as $mountPoint => $data) { + if ($mountPoint == substr($path, 1, strlen($mountPoint))) { + return true; + } + } + } + return false; + } + } diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php index cb10befc8e4..368b7b3dc3f 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -219,7 +219,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { \OC_User::setUserId(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1); - $filename = 'tmp-' . time() . '.test'; + $filename = '/tmp-' . time() . '.test'; // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index fb18bc26248..96fe12fc86a 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -151,6 +151,9 @@ if (isset($path)) { if (\OCP\App::isEnabled('files_encryption')) { $allowPublicUploadEnabled = false; } + if (isset($file)) { + $allowPublicUploadEnabled = false; + } $tmpl->assign('allowPublicUploadEnabled', $allowPublicUploadEnabled); $tmpl->assign('uploadMaxFilesize', $maxUploadFilesize); $tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); diff --git a/apps/files_trashbin/lib/trash.php b/apps/files_trashbin/lib/trash.php index 1235d9d2ee0..b9d900dfab4 100644 --- a/apps/files_trashbin/lib/trash.php +++ b/apps/files_trashbin/lib/trash.php @@ -171,13 +171,19 @@ class Trashbin { list($owner, $ownerPath) = self::getUidAndFilename($file_path); + $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), $user); // disable proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; - // retain key files - $keyfile = \OC\Files\Filesystem::normalizePath($owner . '/files_encryption/keyfiles/' . $ownerPath); + if ($util->isSystemWideMountPoint($ownerPath)) { + $baseDir = '/files_encryption/'; + } else { + $baseDir = $owner . '/files_encryption/'; + } + + $keyfile = \OC\Files\Filesystem::normalizePath($baseDir . '/keyfiles/' . $ownerPath); if ($rootView->is_dir($keyfile) || $rootView->file_exists($keyfile . '.key')) { // move keyfiles @@ -191,7 +197,7 @@ class Trashbin { } // retain share keys - $sharekeys = \OC\Files\Filesystem::normalizePath($owner . '/files_encryption/share-keys/' . $ownerPath); + $sharekeys = \OC\Files\Filesystem::normalizePath($baseDir . '/share-keys/' . $ownerPath); if ($rootView->is_dir($sharekeys)) { $size += self::calculateSize(new \OC\Files\View($sharekeys)); @@ -403,6 +409,14 @@ class Trashbin { list($owner, $ownerPath) = self::getUidAndFilename($target); + $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), $user); + + if ($util->isSystemWideMountPoint($ownerPath)) { + $baseDir = '/files_encryption/'; + } else { + $baseDir = $owner . '/files_encryption/'; + } + $path_parts = pathinfo($file); $source_location = $path_parts['dirname']; @@ -432,18 +446,18 @@ class Trashbin { // handle keyfiles $size += self::calculateSize(new \OC\Files\View($keyfile)); - $rootView->rename($keyfile, $owner . '/files_encryption/keyfiles/' . $ownerPath); + $rootView->rename($keyfile, $baseDir . '/keyfiles/' . $ownerPath); // handle share-keys if ($timestamp) { $sharekey .= '.d' . $timestamp; } $size += self::calculateSize(new \OC\Files\View($sharekey)); - $rootView->rename($sharekey, $owner . '/files_encryption/share-keys/' . $ownerPath); + $rootView->rename($sharekey, $baseDir . '/share-keys/' . $ownerPath); } else { // handle keyfiles $size += $rootView->filesize($keyfile); - $rootView->rename($keyfile, $owner . '/files_encryption/keyfiles/' . $ownerPath . '.key'); + $rootView->rename($keyfile, $baseDir . '/keyfiles/' . $ownerPath . '.key'); // handle share-keys $ownerShareKey = \OC\Files\Filesystem::normalizePath($user . '/files_trashbin/share-keys/' . $source_location . '/' . $filename . '.' . $user . '.shareKey'); @@ -454,7 +468,7 @@ class Trashbin { $size += $rootView->filesize($ownerShareKey); // move only owners key - $rootView->rename($ownerShareKey, $owner . '/files_encryption/share-keys/' . $ownerPath . '.' . $user . '.shareKey'); + $rootView->rename($ownerShareKey, $baseDir . '/share-keys/' . $ownerPath . '.' . $user . '.shareKey'); // try to re-share if file is shared $filesystemView = new \OC_FilesystemView('/'); diff --git a/core/js/share.js b/core/js/share.js index 9494637c3dc..21e352ee1c6 100644 --- a/core/js/share.js +++ b/core/js/share.js @@ -181,13 +181,13 @@ OC.Share={ html += '<div id="linkPass">'; html += '<input id="linkPassText" type="password" placeholder="'+t('core', 'Password')+'" />'; html += '</div>'; - if (possiblePermissions & OC.PERMISSION_CREATE) { + if (itemType === 'folder' && (possiblePermissions & OC.PERMISSION_CREATE)) { html += '<div id="allowPublicUploadWrapper" style="display:none;">'; html += '<input type="checkbox" value="1" name="allowPublicUpload" id="sharingDialogAllowPublicUpload"' + ((allowPublicUploadStatus) ? 'checked="checked"' : '') + ' />'; html += '<label for="sharingDialogAllowPublicUpload">' + t('core', 'Allow Public Upload') + '</label>'; html += '</div>'; } - html += '</div><form id="emailPrivateLink" >'; + html += '</div><form id="emailPrivateLink" >'; html += '<input id="email" style="display:none; width:62%;" value="" placeholder="'+t('core', 'Email link to person')+'" type="text" />'; html += '<input id="emailButton" style="display:none;" type="submit" value="'+t('core', 'Send')+'" />'; html += '</form>'; diff --git a/lib/config.php b/lib/config.php index fcd0a9d7c3c..f1c139f22b1 100644 --- a/lib/config.php +++ b/lib/config.php @@ -132,6 +132,9 @@ class OC_Config{ // read all file in config dir ending by config.php $config_files = glob( OC::$SERVERROOT."/config/*.config.php"); + if (!is_array($config_files)) { + $config_files = array(); + } //Filter only regular files $config_files = array_filter($config_files, 'is_file'); |