From acfa1d1f1069e4a4bbed8599d0e6b4e9b2ea37fe Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 1 Aug 2016 14:55:58 +0600 Subject: CLOUD: Handle paths in marked places Paths containing '../' are forbidden to use in Files Manager. There is also a special inner black list of paths which are not used and a check that specified path is under "savepath" or "rootpath" (from "cloud" domain). --- .../networking/sdl_net/handlers/createdirectoryhandler.cpp | 14 +++++++++++--- .../networking/sdl_net/handlers/downloadfilehandler.cpp | 14 +++++++++++--- backends/networking/sdl_net/handlers/filesbasehandler.cpp | 10 +++++++--- backends/networking/sdl_net/handlers/filespagehandler.cpp | 8 +++++--- backends/networking/sdl_net/handlers/listajaxhandler.cpp | 8 +++++--- backends/networking/sdl_net/handlers/uploadfilehandler.cpp | 14 +++++++++++--- 6 files changed, 50 insertions(+), 18 deletions(-) (limited to 'backends/networking/sdl_net/handlers') diff --git a/backends/networking/sdl_net/handlers/createdirectoryhandler.cpp b/backends/networking/sdl_net/handlers/createdirectoryhandler.cpp index c539525820..284bf16651 100644 --- a/backends/networking/sdl_net/handlers/createdirectoryhandler.cpp +++ b/backends/networking/sdl_net/handlers/createdirectoryhandler.cpp @@ -61,6 +61,12 @@ void CreateDirectoryHandler::handle(Client &client) { return; } + // check that contains no '../' + if (HandlerUtils::hasForbiddenCombinations(path)) { + handleError(client, _("Invalid path!")); + return; + } + // transform virtual path to actual file system one Common::String prefixToRemove = "", prefixToAdd = ""; if (!transformPath(path, prefixToRemove, prefixToAdd) || path.empty()) { @@ -68,10 +74,12 @@ void CreateDirectoryHandler::handle(Client &client) { return; } - // TODO: handle - - // check that exists and is directory + // check that exists, is directory and isn't forbidden AbstractFSNode *node = g_system->getFilesystemFactory()->makeFileNodePath(path); + if (!HandlerUtils::permittedPath(node->getPath())) { + handleError(client, _("Invalid path!")); + return; + } if (!node->exists()) { handleError(client, _("Parent directory doesn't exists!")); return; diff --git a/backends/networking/sdl_net/handlers/downloadfilehandler.cpp b/backends/networking/sdl_net/handlers/downloadfilehandler.cpp index 8f5633c6be..9e212b1a6c 100644 --- a/backends/networking/sdl_net/handlers/downloadfilehandler.cpp +++ b/backends/networking/sdl_net/handlers/downloadfilehandler.cpp @@ -44,6 +44,12 @@ void DownloadFileHandler::handle(Client &client) { return; } + // check that contains no '../' + if (HandlerUtils::hasForbiddenCombinations(path)) { + HandlerUtils::setFilesManagerErrorMessageHandler(client, _("Invalid path!")); + return; + } + // transform virtual path to actual file system one Common::String prefixToRemove = "", prefixToAdd = ""; if (!transformPath(path, prefixToRemove, prefixToAdd, false) || path.empty()) { @@ -51,10 +57,12 @@ void DownloadFileHandler::handle(Client &client) { return; } - // TODO: handle - - // check that exists and is directory + // check that exists, is directory and isn't forbidden AbstractFSNode *node = g_system->getFilesystemFactory()->makeFileNodePath(path); + if (!HandlerUtils::permittedPath(node->getPath())) { + HandlerUtils::setFilesManagerErrorMessageHandler(client, _("Invalid path!")); + return; + } if (!node->exists()) { HandlerUtils::setFilesManagerErrorMessageHandler(client, _("The file doesn't exist!")); return; diff --git a/backends/networking/sdl_net/handlers/filesbasehandler.cpp b/backends/networking/sdl_net/handlers/filesbasehandler.cpp index 68d7919d4a..5e5787b624 100644 --- a/backends/networking/sdl_net/handlers/filesbasehandler.cpp +++ b/backends/networking/sdl_net/handlers/filesbasehandler.cpp @@ -52,12 +52,16 @@ bool FilesBaseHandler::transformPath(Common::String &path, Common::String &prefi if (path.hasPrefix("/root")) { prefixToAdd = "/root/"; - prefixToRemove = ""; + prefixToRemove = (ConfMan.hasKey("rootpath", "cloud") ? ConfMan.get("rootpath", "cloud") : ""); + if (prefixToRemove.size() && prefixToRemove.lastChar() != '/' && prefixToRemove.lastChar() != '\\') + prefixToRemove += '/'; + if (prefixToRemove == "/") prefixToRemove = ""; path.erase(0, 5); + if (path.size() && (path[0] == '/' || path[0] == '\\')) + path.deleteChar(0); // if that was "/root/ab/c", it becomes "/ab/c", but we need "ab/c" + path = prefixToRemove + path; if (path == "") path = "/"; // absolute root is '/' - if (path != "/") - path.deleteChar(0); // if that was "/root/ab/c", it becomes "/ab/c", but we need "ab/c" return true; } diff --git a/backends/networking/sdl_net/handlers/filespagehandler.cpp b/backends/networking/sdl_net/handlers/filespagehandler.cpp index 56b0551ed7..0bc9237805 100644 --- a/backends/networking/sdl_net/handlers/filespagehandler.cpp +++ b/backends/networking/sdl_net/handlers/filespagehandler.cpp @@ -81,17 +81,19 @@ bool FilesPageHandler::listDirectory(Common::String path, Common::String &conten return true; } + if (HandlerUtils::hasForbiddenCombinations(path)) + return false; + Common::String prefixToRemove = "", prefixToAdd = ""; if (!transformPath(path, prefixToRemove, prefixToAdd)) return false; - // TODO: handle - Common::FSNode node = Common::FSNode(path); if (path == "/") node = node.getParent(); // absolute root - // TODO: handle + if (!HandlerUtils::permittedPath(node.getPath())) + return false; if (!node.isDirectory()) return false; diff --git a/backends/networking/sdl_net/handlers/listajaxhandler.cpp b/backends/networking/sdl_net/handlers/listajaxhandler.cpp index ad8907cf27..57fa04d10d 100644 --- a/backends/networking/sdl_net/handlers/listajaxhandler.cpp +++ b/backends/networking/sdl_net/handlers/listajaxhandler.cpp @@ -46,17 +46,19 @@ Common::JSONObject ListAjaxHandler::listDirectory(Common::String path) { return successResult; } + if (HandlerUtils::hasForbiddenCombinations(path)) + return errorResult; + Common::String prefixToRemove = "", prefixToAdd = ""; if (!transformPath(path, prefixToRemove, prefixToAdd)) return errorResult; - // TODO: handle - Common::FSNode node = Common::FSNode(path); if (path == "/") node = node.getParent(); // absolute root - // TODO: handle + if (!HandlerUtils::permittedPath(node.getPath())) + return errorResult; if (!node.isDirectory()) return errorResult; diff --git a/backends/networking/sdl_net/handlers/uploadfilehandler.cpp b/backends/networking/sdl_net/handlers/uploadfilehandler.cpp index 22896a25f0..a0e992c25e 100644 --- a/backends/networking/sdl_net/handlers/uploadfilehandler.cpp +++ b/backends/networking/sdl_net/handlers/uploadfilehandler.cpp @@ -44,6 +44,12 @@ void UploadFileHandler::handle(Client &client) { return; } + // check that contains no '../' + if (HandlerUtils::hasForbiddenCombinations(path)) { + HandlerUtils::setFilesManagerErrorMessageHandler(client, _("Invalid path!")); + return; + } + // transform virtual path to actual file system one Common::String prefixToRemove = "", prefixToAdd = ""; if (!transformPath(path, prefixToRemove, prefixToAdd, false) || path.empty()) { @@ -51,10 +57,12 @@ void UploadFileHandler::handle(Client &client) { return; } - // TODO: handle - - // check that exists and is directory + // check that exists, is directory and isn't forbidden AbstractFSNode *node = g_system->getFilesystemFactory()->makeFileNodePath(path); + if (!HandlerUtils::permittedPath(node->getPath())) { + HandlerUtils::setFilesManagerErrorMessageHandler(client, _("Invalid path!")); + return; + } if (!node->exists()) { HandlerUtils::setFilesManagerErrorMessageHandler(client, _("The parent directory doesn't exist!")); return; -- cgit v1.2.3