[Libreoffice-commits] online.git: loleaflet/html loleaflet/src wsd/FileServer.cpp

Michael Meeks (via logerrit) logerrit at kemper.freedesktop.org
Wed Jan 15 09:56:48 UTC 2020


 loleaflet/html/loleaflet.html.m4      |    2 +
 loleaflet/src/map/handler/Map.WOPI.js |   54 ++++++++++++++++++++++++++++++++--
 wsd/FileServer.cpp                    |   28 +++++++++--------
 3 files changed, 68 insertions(+), 16 deletions(-)

New commits:
commit b5f58fbe8c4f283d10def377c8a687245312fa1f
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Tue Jan 14 16:56:01 2020 +0000
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Wed Jan 15 10:56:27 2020 +0100

    postMessage CSS checking improvements.
    
    Ironically our attempts to double-check message origin against our
    parent was blowing a security exception.
    
    Instead send the list of origins we will accept from WSD, and
    check them ourselves (as well as the browser check).
    
    Why make it so hard to check that a postMessage comes from an
    ancestor frame ?
    
    Change-Id: I1311be3e1d68a31cfdc96b45a5eb5dd7f26e7ea9
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/86788
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Alexandru Vlăduţu <alexandru.vladutu at 1and1.ro>
    Reviewed-by: Jan Holesovsky <kendy at collabora.com>

diff --git a/loleaflet/html/loleaflet.html.m4 b/loleaflet/html/loleaflet.html.m4
index ad6d90f4b..4addf8955 100644
--- a/loleaflet/html/loleaflet.html.m4
+++ b/loleaflet/html/loleaflet.html.m4
@@ -231,6 +231,7 @@ ifelse(MOBILEAPP,[true],
       window.idleTimeoutSecs = 1000000;
       window.reuseCookies = '';
       window.protocolDebug = false;
+      window.frameAncestors = '';
       window.tileSize = 256;],
      [window.host = '%HOST%';
       window.serviceRoot = '%SERVICE_ROOT%';
@@ -242,6 +243,7 @@ ifelse(MOBILEAPP,[true],
       window.idleTimeoutSecs = %IDLE_TIMEOUT_SECS%;
       window.reuseCookies = '%REUSE_COOKIES%';
       window.protocolDebug = %PROTOCOL_DEBUG%;
+      window.frameAncestors = '%FRAME_ANCESTORS%';
       window.tileSize = 256;])
 syscmd([cat ]GLOBAL_JS)dnl
     </script>
diff --git a/loleaflet/src/map/handler/Map.WOPI.js b/loleaflet/src/map/handler/Map.WOPI.js
index dcd401407..89f01ec53 100644
--- a/loleaflet/src/map/handler/Map.WOPI.js
+++ b/loleaflet/src/map/handler/Map.WOPI.js
@@ -141,13 +141,61 @@ L.Map.WOPI = L.Handler.extend({
 		this._map.fire('postMessage', {msgId: 'App_LoadingStatus', args: {Status: 'Document_Loaded', DocumentLoadedTime: this.DocumentLoadedTime}});
 	},
 
-	_postMessageListener: function(e) {
+	// Naturally we set a CSP to catch badness, but check here as well.
+	// Checking whether a message came from our iframe's parents is
+	// un-necessarily difficult.
+	_allowMessageOrigin: function(e) {
+		// cache - to avoid regexps.
+		if (this._cachedGoodOrigin && this._cachedGoodOrigin === e.origin)
+			return true;
 
 		// e.origin === 'null' when sandboxed (i.e. when the parent is a file on local filesystem).
-		if (e.origin !== 'null' && e.origin !== window.parent.origin) {
-			return;
+		if (e.origin === 'null')
+			return true;
+		try {
+			if (e.origin === window.parent.origin)
+				return true;
+		} catch (secErr) { // security error de-referencing window.parent.origin.
+		}
+
+		// sent from the server
+		var i;
+		if (!this._allowedOrigins && window.frameAncestors)
+		{
+			var ancestors = window.frameAncestors.trim().split(' ');
+			this._allowedOrigins = ancestors;
+			// convert to JS regexps from localhost:* to https*://localhost:.*
+			for (i = 0; i < ancestors.length; i++) {
+				this._allowedOrigins[i] = 'https*://' + ancestors[i].replace(/:\*/, ':.*');
+			}
+		}
+
+		if (this._allowedOrigins)
+		{
+			for (i = 0; i < this._allowedOrigins.length; i++) {
+				if (e.origin.match(this._allowedOrigins[i]))
+				{
+					this._cachedGoodOrigin = e.origin;
+					return true;
+				}
+			}
 		}
 
+		// chrome only
+		if (window.location.ancestorOrigins &&
+		    window.location.ancestorOrigins.contains(e.origin))
+		{
+			this._cachedGoodOrigin = e.origin;
+			return true;
+		}
+
+		return false;
+	},
+
+	_postMessageListener: function(e) {
+		if (!this._allowMessageOrigin(e))
+			return;
+
 		var msg;
 		try {
 			msg = JSON.parse(e.data);
diff --git a/wsd/FileServer.cpp b/wsd/FileServer.cpp
index 3cf3fbc51..07ac439b3 100644
--- a/wsd/FileServer.cpp
+++ b/wsd/FileServer.cpp
@@ -699,19 +699,6 @@ void FileServerRequestHandler::preprocessFile(const HTTPRequest& request, Poco::
 
     const std::string mimeType = "text/html";
 
-    std::ostringstream oss;
-    oss << "HTTP/1.1 200 OK\r\n"
-        "Date: " << Util::getHttpTimeNow() << "\r\n"
-        "Last-Modified: " << Util::getHttpTimeNow() << "\r\n"
-        "User-Agent: " << WOPI_AGENT_STRING << "\r\n"
-        "Cache-Control:max-age=11059200\r\n"
-        "ETag: \"" LOOLWSD_VERSION_HASH "\"\r\n"
-        "Content-Length: " << preprocess.size() << "\r\n"
-        "Content-Type: " << mimeType << "\r\n"
-        "X-Content-Type-Options: nosniff\r\n"
-        "X-XSS-Protection: 1; mode=block\r\n"
-        "Referrer-Policy: no-referrer\r\n";
-
     // Document signing: if endpoint URL is configured, whitelist that for
     // iframe purposes.
     std::ostringstream cspOss;
@@ -755,6 +742,7 @@ void FileServerRequestHandler::preprocessFile(const HTTPRequest& request, Poco::
         //(it's deprecated anyway and CSP works in all major browsers)
         cspOss << "img-src 'self' data: " << frameAncestors << "; "
                 << "frame-ancestors " << frameAncestors;
+        Poco::replaceInPlace(preprocess, std::string("%FRAME_ANCESTORS%"), frameAncestors);
     }
     else
     {
@@ -763,6 +751,20 @@ void FileServerRequestHandler::preprocessFile(const HTTPRequest& request, Poco::
     }
 
     cspOss << "\r\n";
+
+    std::ostringstream oss;
+    oss << "HTTP/1.1 200 OK\r\n"
+        "Date: " << Util::getHttpTimeNow() << "\r\n"
+        "Last-Modified: " << Util::getHttpTimeNow() << "\r\n"
+        "User-Agent: " << WOPI_AGENT_STRING << "\r\n"
+        "Cache-Control:max-age=11059200\r\n"
+        "ETag: \"" LOOLWSD_VERSION_HASH "\"\r\n"
+        "Content-Length: " << preprocess.size() << "\r\n"
+        "Content-Type: " << mimeType << "\r\n"
+        "X-Content-Type-Options: nosniff\r\n"
+        "X-XSS-Protection: 1; mode=block\r\n"
+        "Referrer-Policy: no-referrer\r\n";
+
     // Append CSP to response headers too
     oss << cspOss.str();
 


More information about the Libreoffice-commits mailing list