[Libreoffice-commits] online.git: 2 commits - wsd/FileServer.cpp wsd/FileServer.hpp

Pranav Kant pranavk at collabora.co.uk
Mon Apr 10 09:56:35 UTC 2017


 wsd/FileServer.cpp |   71 +++++++++++++++++++++++++++++++----------------------
 wsd/FileServer.hpp |    8 ++---
 2 files changed, 45 insertions(+), 34 deletions(-)

New commits:
commit 74020e0f1ffa0a6a2448135440c7ba03482f0bea
Author: Pranav Kant <pranavk at collabora.co.uk>
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 <pranavk at collabora.co.uk>
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"


More information about the Libreoffice-commits mailing list