wsd/FileServer.cpp | 71 +++++++++++++++++++++++++++++++---------------------- wsd/FileServer.hpp | 8 ++--- 2 files changed, 45 insertions(+), 34 deletions(-)
New commits: commit 74020e0f1ffa0a6a2448135440c7ba03482f0bea Author: Pranav Kant <[email protected]> Date: Mon Apr 10 15:04:51 2017 +0530 Revert "wsd: Fileserver cleanup" This reverts commit de2bc17c04af088d9c7e18a97216b174494e1a9c. Lets not introduce any cleanup commits while we are near a release, will apply it again after the release. The cleanup is supposed to not handle the custom file server root correctly, so don't forget to test it with a custom file server root before re-reverting. It changes the path where loleaflet.html is searched for from /usr/share/loolwsd/loleaflet/... to /usr/share/loleaflet/... and doesn't find it there. Change-Id: I23940e9a3e06721f0a8b7493a526f42d2072cfa4 diff --git a/wsd/FileServer.cpp b/wsd/FileServer.cpp index 6c892f3d..9f056903 100644 --- a/wsd/FileServer.cpp +++ b/wsd/FileServer.cpp @@ -44,8 +44,8 @@ using Poco::Net::HTTPBasicCredentials; using Poco::StreamCopier; using Poco::Util::Application; -bool FileServerRequestHandler::tryAdminLogin(const HTTPRequest& request, - HTTPResponse &response) +bool FileServerRequestHandler::isAdminLoggedIn(const HTTPRequest& request, + HTTPResponse &response) { const auto& config = Application::instance().config(); const auto sslKeyPath = config.getString("ssl.key_file_path", ""); @@ -109,43 +109,56 @@ void FileServerRequestHandler::handleRequest(const HTTPRequest& request, Poco::M { bool noCache = false; Poco::Net::HTTPResponse response; - const auto requestPathname = Poco::Path(getRequestPathname(request)); - const auto filePath = Poco::Path(LOOLWSD::FileServerRoot, requestPathname); - const auto file = Poco::File(filePath); - LOG_TRC("Fileserver request: " << requestPathname.toString() << ", " << - "Resolved file path: " << filePath.toString()); - - if (!file.exists() || - requestPathname[0] != "loleaflet" || - requestPathname[1] != "dist") + Poco::URI requestUri(request.getURI()); + LOG_TRC("Fileserver request: " << requestUri.toString()); + requestUri.normalize(); // avoid .'s and ..'s + + std::vector<std::string> requestSegments; + requestUri.getPathSegments(requestSegments); + if (requestSegments.size() < 1) { - throw Poco::FileNotFoundException("Invalid URI request: [" + filePath.toString() + "]."); + throw Poco::FileNotFoundException("Invalid URI request: [" + requestUri.toString() + "]."); } const auto& config = Application::instance().config(); const std::string loleafletHtml = config.getString("loleaflet_html", "loleaflet.html"); - if (filePath.getFileName() == loleafletHtml) + const std::string endPoint = requestSegments[requestSegments.size() - 1]; + if (endPoint == loleafletHtml) { - preprocessAndSendLoleafletHtml(request, message, socket); + preprocessFile(request, message, socket); return; } if (request.getMethod() == HTTPRequest::HTTP_GET) { - if (filePath.getFileName() == "admin.html" || - filePath.getFileName() == "adminSettings.html" || - filePath.getFileName() == "adminAnalytics.html") + if (endPoint == "admin.html" || + endPoint == "adminSettings.html" || + endPoint == "adminAnalytics.html") { noCache = true; - if (!FileServerRequestHandler::tryAdminLogin(request, response)) + if (!FileServerRequestHandler::isAdminLoggedIn(request, response)) throw Poco::Net::NotAuthenticatedException("Invalid admin login"); // Ask UAs to block if they detect any XSS attempt response.add("X-XSS-Protection", "1; mode=block"); } - const std::string fileType = filePath.getExtension(); + const auto path = Poco::Path(LOOLWSD::FileServerRoot, getRequestPathname(request)); + const auto filepath = path.absolute().toString(); + if (filepath.find(LOOLWSD::FileServerRoot) != 0) + { + // Accessing unauthorized path. + throw Poco::FileAccessDeniedException("Invalid or forbidden file path: [" + filepath + "]."); + } + + const std::size_t extPoint = endPoint.find_last_of('.'); + if (extPoint == std::string::npos) + { + throw Poco::FileNotFoundException("Invalid file."); + } + + const std::string fileType = endPoint.substr(extPoint + 1); std::string mimeType; if (fileType == "js") mimeType = "application/javascript"; @@ -184,7 +197,7 @@ void FileServerRequestHandler::handleRequest(const HTTPRequest& request, Poco::M } bool deflate = request.hasToken("Accept-Encoding", "deflate"); - HttpHelper::sendFile(socket, filePath.toString(), mimeType, response, noCache, deflate); + HttpHelper::sendFile(socket, filepath, mimeType, response, noCache, deflate); } } catch (const Poco::Net::NotAuthenticatedException& exc) @@ -237,17 +250,13 @@ std::string FileServerRequestHandler::getRequestPathname(const HTTPRequest& requ std::string path(requestUri.getPath()); - // Remove first foreslash as the root ends in one. - if (path[0] == '/') - path = path.substr(1); - - // Convert version back to a real file name. - Poco::replaceInPlace(path, std::string("loleaflet/" LOOLWSD_VERSION_HASH "/"), std::string("loleaflet/dist/")); + // Convert version back to a real file name. Remove first foreslash as the root ends in one. + Poco::replaceInPlace(path, std::string("/loleaflet/" LOOLWSD_VERSION_HASH "/"), std::string("loleaflet/dist/")); return path; } -void FileServerRequestHandler::preprocessAndSendLoleafletHtml(const HTTPRequest& request, Poco::MemoryInputStream& message, const std::shared_ptr<StreamSocket>& socket) +void FileServerRequestHandler::preprocessFile(const HTTPRequest& request, Poco::MemoryInputStream& message, const std::shared_ptr<StreamSocket>& socket) { const auto host = ((LOOLWSD::isSSLEnabled() || LOOLWSD::isSSLTermination()) ? "wss://" : "ws://") + (LOOLWSD::ServerName.empty() ? request.getHost() : LOOLWSD::ServerName); const auto params = Poco::URI(request.getURI()).getQueryParameters(); diff --git a/wsd/FileServer.hpp b/wsd/FileServer.hpp index 3ba6803f..b27526f3 100644 --- a/wsd/FileServer.hpp +++ b/wsd/FileServer.hpp @@ -20,13 +20,11 @@ class FileServerRequestHandler { static std::string getRequestPathname(const Poco::Net::HTTPRequest& request); - static void preprocessAndSendLoleafletHtml(const Poco::Net::HTTPRequest& request, Poco::MemoryInputStream& message, const std::shared_ptr<StreamSocket>& socket); + static void preprocessFile(const Poco::Net::HTTPRequest& request, Poco::MemoryInputStream& message, const std::shared_ptr<StreamSocket>& socket); public: - /// If valid cookies exists in request, log the admin in (returns true) - /// If no cookie exist check the credentials, set the cookie and log the admin in - /// In case no valid cookie exists or invalid or no credentials exist, return false - static bool tryAdminLogin(const Poco::Net::HTTPRequest& request, Poco::Net::HTTPResponse& response); + /// Evaluate if the cookie exists, and if not, ask for the credentials. + static bool isAdminLoggedIn(const Poco::Net::HTTPRequest& request, Poco::Net::HTTPResponse& response); static void handleRequest(const Poco::Net::HTTPRequest& request, Poco::MemoryInputStream& message, const std::shared_ptr<StreamSocket>& socket); }; commit a0d7c33877c266db0ef88c32645c69a6ad892216 Author: Pranav Kant <[email protected]> Date: Sun Apr 9 23:53:45 2017 +0530 security: X-Frame-Options: Deny framing if no wopi host Change-Id: I6936f8a11e3e076e111e0883305f47064e032983 diff --git a/wsd/FileServer.cpp b/wsd/FileServer.cpp index 07c9857b..6c892f3d 100644 --- a/wsd/FileServer.cpp +++ b/wsd/FileServer.cpp @@ -340,8 +340,12 @@ void FileServerRequestHandler::preprocessAndSendLoleafletHtml(const HTTPRequest& if (!wopiDomain.empty()) { - oss << "X-Frame-Options: allow-from " << wopiDomain << "\r\n" - << "Content-Security-Policy: frame-ancestors " << wopiDomain << "\r\n"; + oss << "X-Frame-Options: allow-from " << wopiDomain << "\r\n"; + oss << "Content-Security-Policy: frame-ancestors " << wopiDomain << "\r\n"; + } + else + { + oss << "X-Frame-Options: deny\r\n"; } oss << "\r\n" _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
