loleaflet/js/global.js |    2 -
 wsd/FileServer.cpp     |   89 +++++++++++++++++++++++++++++--------------------
 2 files changed, 55 insertions(+), 36 deletions(-)

New commits:
commit d439f8098d2fbec7ace4fa6a66f7c9c00d77edfe
Author:     Michael Meeks <michael.me...@collabora.com>
AuthorDate: Tue Apr 28 18:05:25 2020 +0100
Commit:     Michael Meeks <michael.me...@collabora.com>
CommitDate: Tue Apr 28 19:34:15 2020 +0200

    Proxy: improving parsing & URL passing for websocket to fix connect-src.
    
    Change-Id: Id017c46e755eb14bc25d18be450b6100ff6bed92
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/93094
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Michael Meeks <michael.me...@collabora.com>

diff --git a/loleaflet/js/global.js b/loleaflet/js/global.js
index c3c8343ad..c2935ab96 100644
--- a/loleaflet/js/global.js
+++ b/loleaflet/js/global.js
@@ -344,7 +344,7 @@
                };
                this.getEndPoint = function(type) {
                        var base = this.uri;
-                       return base.replace(/^ws/, 'http') + '/' + type + '/' + 
this.outSerial;
+                       return base + '/' + type + '/' + this.outSerial;
                };
                console.debug('proxy: new socket ' + this.id + ' ' + this.uri);
 
diff --git a/wsd/FileServer.cpp b/wsd/FileServer.cpp
index 99ac332b3..888509591 100644
--- a/wsd/FileServer.cpp
+++ b/wsd/FileServer.cpp
@@ -641,44 +641,62 @@ constexpr char BRANDING_UNSUPPORTED[] = 
"branding-unsupported";
 #endif
 
 namespace {
-    // The user can override the ServerRoot with a new prefix.
-    std::string getResponseRoot(const HTTPRequest &request)
-    {
-        if (!request.has("ProxyPrefix"))
-            return LOOLWSD::ServiceRoot;
-        std::string proxyPrefix = request.get("ProxyPrefix", "");
-
-        // skip url to the root path.
-        size_t pos = proxyPrefix.find("://");
-        if (pos != std::string::npos) {
-            pos = proxyPrefix.find("/", pos + 3);
-            if (pos != std::string::npos)
-                proxyPrefix = proxyPrefix.substr(pos);
-            else
-                LOG_DBG("Unusual proxy prefix '" << proxyPrefix << "'");
-        } else
-            LOG_DBG("No http[s]:// in unusual proxy prefix '" << proxyPrefix);
-        return proxyPrefix;
-    }
+    /// Very simple splitting of proxy URLs without fear of escaping or 
validation.
+    class ProxyURL {
+        std::string _schemeAuthority;
+        std::string _pathPlus;
+    public:
+        ProxyURL(const HTTPRequest &request)
+        {
+            // The user can override the ServerRoot with a new prefix.
+            if (_pathPlus.size() <= 0)
+                _pathPlus = LOOLWSD::ServiceRoot;
 
-    std::string getWebSocketUrl(const HTTPRequest &request)
-    {
-        bool ssl = (LOOLWSD::isSSLEnabled() || LOOLWSD::isSSLTermination());
-        std::string proxyPrefix = request.get("ProxyPrefix", "");
-        std::string serverName = LOOLWSD::ServerName.empty() ? 
request.getHost() : LOOLWSD::ServerName;
-        if (proxyPrefix.size() > 0)
+            if (_schemeAuthority.size() <= 0)
+            {
+                bool ssl = (LOOLWSD::isSSLEnabled() || 
LOOLWSD::isSSLTermination());
+                std::string serverName = LOOLWSD::ServerName.empty() ? 
request.getHost() : LOOLWSD::ServerName;
+                _schemeAuthority = (ssl ? "wss://" : "ws://") + serverName;
+            }
+
+            // A well formed ProxyPrefix will override it.
+            std::string url = request.get("ProxyPrefix", "");
+            if (url.size() <= 0)
+                return;
+
+            size_t pos = url.find("://");
+            if (pos != std::string::npos) {
+                pos = url.find("/", pos + 3);
+                if (pos != std::string::npos)
+                {
+                    _schemeAuthority = url.substr(0, pos);
+                    _pathPlus = url.substr(pos);
+                    return;
+                }
+                else
+                    LOG_ERR("Unusual proxy prefix '" << url << "'");
+            } else
+                LOG_ERR("No http[s]:// in unusual proxy prefix '" << url << 
"'");
+
+        }
+
+        std::string getResponseRoot() const
         {
-            ssl = !strcmp(proxyPrefix.c_str(), "https://";);
-            serverName = request.getHost();
+            return _pathPlus;
         }
-        return (ssl ? "wss://" : "ws://") + serverName;
-    }
+
+        std::string getWebSocketUrl() const
+        {
+            return _schemeAuthority;
+        }
+    };
 }
 
 void FileServerRequestHandler::preprocessFile(const HTTPRequest& request, 
Poco::MemoryInputStream& message,
                                               const 
std::shared_ptr<StreamSocket>& socket)
 {
-    const auto host = getWebSocketUrl(request);
+    ProxyURL cnxDetails(request);
+
     const Poco::URI::QueryParameters params = 
Poco::URI(request.getURI()).getQueryParameters();
 
     // Is this a file we read at startup - if not; its not for serving.
@@ -725,12 +743,12 @@ void FileServerRequestHandler::preprocessFile(const 
HTTPRequest& request, Poco::
         socketProxy = "true";
     Poco::replaceInPlace(preprocess, std::string("%SOCKET_PROXY%"), 
socketProxy);
 
-    std::string responseRoot = getResponseRoot(request);
+    std::string responseRoot = cnxDetails.getResponseRoot();
 
     Poco::replaceInPlace(preprocess, std::string("%ACCESS_TOKEN%"), 
escapedAccessToken);
     Poco::replaceInPlace(preprocess, std::string("%ACCESS_TOKEN_TTL%"), 
std::to_string(tokenTtl));
     Poco::replaceInPlace(preprocess, std::string("%ACCESS_HEADER%"), 
escapedAccessHeader);
-    Poco::replaceInPlace(preprocess, std::string("%HOST%"), host);
+    Poco::replaceInPlace(preprocess, std::string("%HOST%"), 
cnxDetails.getWebSocketUrl());
     Poco::replaceInPlace(preprocess, std::string("%VERSION%"), 
std::string(LOOLWSD_VERSION_HASH));
     Poco::replaceInPlace(preprocess, std::string("%SERVICE_ROOT%"), 
responseRoot);
 
@@ -807,7 +825,7 @@ void FileServerRequestHandler::preprocessFile(const 
HTTPRequest& request, Poco::
     std::ostringstream cspOss;
     cspOss << "Content-Security-Policy: default-src 'none'; "
            "frame-src 'self' blob: " << documentSigningURL << "; "
-           "connect-src 'self' " << host << "; "
+           "connect-src 'self' " << cnxDetails.getWebSocketUrl() << "; "
            "script-src 'unsafe-inline' 'self'; "
            "style-src 'self' 'unsafe-inline'; "
            "font-src 'self' data:; "
@@ -816,7 +834,7 @@ void FileServerRequestHandler::preprocessFile(const 
HTTPRequest& request, Poco::
     // Frame ancestors: Allow loolwsd host, wopi host and anything configured.
     std::string configFrameAncestor = config.getString("net.frame_ancestors", 
"");
     std::string frameAncestors = configFrameAncestor;
-    Poco::URI uriHost(host);
+    Poco::URI uriHost(cnxDetails.getWebSocketUrl());
     if (uriHost.getHost() != configFrameAncestor)
         frameAncestors += " " + uriHost.getHost() + ":*";
 
@@ -945,7 +963,8 @@ void FileServerRequestHandler::preprocessAdminFile(const 
HTTPRequest& request,co
     if (!FileServerRequestHandler::isAdminLoggedIn(request, response))
         throw Poco::Net::NotAuthenticatedException("Invalid admin login");
 
-    std::string responseRoot = getResponseRoot(request);
+    ProxyURL cnxDetails(request);
+    std::string responseRoot = cnxDetails.getResponseRoot();
 
     static const std::string scriptJS("<script src=\"%s/loleaflet/" 
LOOLWSD_VERSION_HASH "/%s.js\"></script>");
     static const std::string footerPage("<div class=\"footer 
navbar-fixed-bottom text-info text-center\"><strong>Key:</strong> %s 
&nbsp;&nbsp;<strong>Expiry Date:</strong> %s</div>");
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to