From 1e631754d78e98d74ba0d3fb477d5eb815e9dfb3 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Wed, 17 Sep 2014 18:50:29 +0200 Subject: Fix share key finding algorithm in various cases Instead of inaccurate pattern matching, use the list of users who we know have access to the file to build the list of share keys. This covers the following cases: - Move/copy files into a subfolder within a share - Unsharing from a user - Deleting files directlry / moving share keys to trashbin --- apps/files_encryption/lib/helper.php | 46 ++++++++++++++++++--------- apps/files_encryption/lib/keymanager.php | 54 +++++++++++++++++++------------- 2 files changed, 63 insertions(+), 37 deletions(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index d427c51732f..ab19938d633 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -431,24 +431,40 @@ class Helper { /** * find all share keys for a given file - * @param string $path to the file - * @param \OC\Files\View $view view, relative to data/ - * @return array list of files, path relative to data/ + * + * @param string $filePath path to the file name relative to the user's files dir + * for example "subdir/filename.txt" + * @param string $shareKeyPath share key prefix path relative to the user's data dir + * for example "user1/files_encryption/share-keys/subdir/filename.txt" + * @param \OC\Files\View $rootView root view, relative to data/ + * @return array list of share key files, path relative to data/$user */ - public static function findShareKeys($path, $view) { + public static function findShareKeys($filePath, $shareKeyPath, $rootView) { $result = array(); - $pathinfo = pathinfo($path); - $dirContent = $view->opendir($pathinfo['dirname']); - - if (is_resource($dirContent)) { - while (($file = readdir($dirContent)) !== false) { - if (!\OC\Files\Filesystem::isIgnoredDir($file)) { - if (preg_match("/" . $pathinfo['filename'] . ".(.*).shareKey/", $file)) { - $result[] = $pathinfo['dirname'] . '/' . $file; - } - } + + $user = \OCP\User::getUser(); + $util = new Util($rootView, $user); + // get current sharing state + $sharingEnabled = \OCP\Share::isEnabled(); + + // get users sharing this file + $usersSharing = $util->getSharingUsersArray($sharingEnabled, $filePath); + + $pathinfo = pathinfo($shareKeyPath); + + $baseDir = $pathinfo['dirname'] . '/'; + $fileName = $pathinfo['basename']; + foreach ($usersSharing as $user) { + $keyName = $fileName . '.' . $user . '.shareKey'; + if ($rootView->file_exists($baseDir . $keyName)) { + $result[] = $baseDir . $keyName; + } else { + \OC_Log::write( + 'Encryption library', + 'No share key found for user "' . $user . '" for file "' . $pathOld . '"', + \OC_Log::WARN + ); } - closedir($dirContent); } return $result; diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 931469f4b74..9560126ef33 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -459,13 +459,17 @@ class Keymanager { \OCP\Util::writeLog('files_encryption', 'delAllShareKeys: delete share keys: ' . $baseDir . $filePath, \OCP\Util::DEBUG); $result = $view->unlink($baseDir . $filePath); } else { - $parentDir = dirname($baseDir . $filePath); - $filename = pathinfo($filePath, PATHINFO_BASENAME); - foreach($view->getDirectoryContent($parentDir) as $content) { - $path = $content['path']; - if (self::getFilenameFromShareKey($content['name']) === $filename) { - \OCP\Util::writeLog('files_encryption', 'dellAllShareKeys: delete share keys: ' . '/' . $userId . '/' . $path, \OCP\Util::DEBUG); - $result &= $view->unlink('/' . $userId . '/' . $path); + $sharingEnabled = \OCP\Share::isEnabled(); + $users = $util->getSharingUsersArray($sharingEnabled, $filePath); + foreach($users as $user) { + $keyName = $baseDir . $filePath . '.' . $user . '.shareKey'; + if ($view->file_exists($keyName)) { + \OCP\Util::writeLog( + 'files_encryption', + 'dellAllShareKeys: delete share keys: "' . $keyName . '"', + \OCP\Util::DEBUG + ); + $result &= $view->unlink($keyName); } } } @@ -539,17 +543,20 @@ class Keymanager { if ($view->is_dir($dir . '/' . $file)) { self::recursiveDelShareKeys($dir . '/' . $file, $userIds, $owner, $view); } else { - $realFile = $realFileDir . self::getFilenameFromShareKey($file); foreach ($userIds as $userId) { - if (preg_match("/(.*)." . $userId . ".shareKey/", $file)) { - if ($userId === $owner && - $view->file_exists($realFile)) { - \OCP\Util::writeLog('files_encryption', 'original file still exists, keep owners share key!', \OCP\Util::ERROR); - continue; - } - \OCP\Util::writeLog('files_encryption', 'recursiveDelShareKey: delete share key: ' . $file, \OCP\Util::DEBUG); - $view->unlink($dir . '/' . $file); + $fileNameFromShareKey = self::getFilenameFromShareKey($file, $userId); + if (!$fileNameFromShareKey) { + continue; } + $realFile = $realFileDir . $fileNameFromShareKey; + + if ($userId === $owner && + $view->file_exists($realFile)) { + \OCP\Util::writeLog('files_encryption', 'original file still exists, keep owners share key!', \OCP\Util::ERROR); + continue; + } + \OCP\Util::writeLog('files_encryption', 'recursiveDelShareKey: delete share key: ' . $file, \OCP\Util::DEBUG); + $view->unlink($dir . '/' . $file); } } } @@ -591,16 +598,19 @@ class Keymanager { /** * extract filename from share key name * @param string $shareKey (filename.userid.sharekey) + * @param string $userId * @return string|false filename or false */ - protected static function getFilenameFromShareKey($shareKey) { - $parts = explode('.', $shareKey); + protected static function getFilenameFromShareKey($shareKey, $userId) { + $expectedSuffix = '.' . $userId . '.' . 'shareKey'; + $suffixLen = strlen($expectedSuffix); - $filename = false; - if(count($parts) > 2) { - $filename = implode('.', array_slice($parts, 0, count($parts)-2)); + $suffix = substr($shareKey, -$suffixLen); + + if ($suffix !== $expectedSuffix) { + return false; } - return $filename; + return substr($shareKey, 0, -$suffixLen); } } -- cgit v1.2.3