[Libreoffice-commits] online.git: fuzzer/ClientSession.cpp loleaflet/src Makefile.am wsd/ClientSession.cpp wsd/ClientSession.hpp wsd/DocumentBroker.cpp wsd/DocumentBroker.hpp wsd/FileServer.cpp wsd/LOOLWSD.cpp wsd/ProxyProtocol.cpp wsd/ServerURL.hpp
Michael Meeks (via logerrit)
logerrit at kemper.freedesktop.org
Wed May 6 21:12:33 UTC 2020
Makefile.am | 1
fuzzer/ClientSession.cpp | 4 -
loleaflet/src/map/Clipboard.js | 14 +++---
wsd/ClientSession.cpp | 13 +++---
wsd/ClientSession.hpp | 7 +--
wsd/DocumentBroker.cpp | 7 +--
wsd/DocumentBroker.hpp | 5 +-
wsd/FileServer.cpp | 54 +-------------------------
wsd/LOOLWSD.cpp | 18 ++------
wsd/ProxyProtocol.cpp | 4 -
wsd/ServerURL.hpp | 84 +++++++++++++++++++++++++++++++++++++++++
11 files changed, 124 insertions(+), 87 deletions(-)
New commits:
commit 18c4301a1f26e5630b24db532a532baafb6cd57f
Author: Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Wed May 6 17:02:51 2020 +0100
Commit: Michael Meeks <michael.meeks at collabora.com>
CommitDate: Wed May 6 23:12:12 2020 +0200
Proxy: re-factor proxy handling into ServerURL and cleanup copy/paste.
Also adds ServiceRoot handling for clipboard.
Change-Id: I7bc6591130fcc7d693e59ab8561fb9e99f4e93d5
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/93578
Tested-by: Michael Meeks <michael.meeks at collabora.com>
Reviewed-by: Michael Meeks <michael.meeks at collabora.com>
diff --git a/Makefile.am b/Makefile.am
index 42e338913..1b5beb47c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -225,6 +225,7 @@ wsd_headers = wsd/Admin.hpp \
wsd/ProofKey.hpp \
wsd/QueueHandler.hpp \
wsd/SenderQueue.hpp \
+ wsd/ServerURL.hpp \
wsd/Storage.hpp \
wsd/TileCache.hpp \
wsd/TileDesc.hpp \
diff --git a/fuzzer/ClientSession.cpp b/fuzzer/ClientSession.cpp
index 844fa0c80..a9a6ad657 100644
--- a/fuzzer/ClientSession.cpp
+++ b/fuzzer/ClientSession.cpp
@@ -21,9 +21,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
std::shared_ptr<ProtocolHandlerInterface> ws;
std::string id;
bool isReadOnly = false;
- const std::string hostNoTrust;
+ const ServerURL serverURL("", "");
auto session
- = std::make_shared<ClientSession>(ws, id, docBroker, uriPublic, isReadOnly, hostNoTrust);
+ = std::make_shared<ClientSession>(ws, id, docBroker, uriPublic, isReadOnly, serverURL);
std::string input(reinterpret_cast<const char*>(data), size);
std::stringstream ss(input);
diff --git a/loleaflet/src/map/Clipboard.js b/loleaflet/src/map/Clipboard.js
index 700369d29..c7b604083 100644
--- a/loleaflet/src/map/Clipboard.js
+++ b/loleaflet/src/map/Clipboard.js
@@ -99,6 +99,10 @@ L.Clipboard = L.Class.extend({
'&Tag=' + this._accessKey[idx];
},
+ getMetaURL: function(idx) {
+ return this.getMetaBase() + this.getMetaPath(idx);
+ },
+
// Returns the marker used to identify stub messages.
_getHtmlStubMarker: function() {
return '<title>Stub HTML Message</title>';
@@ -111,7 +115,7 @@ L.Clipboard = L.Class.extend({
// wrap some content with our stub magic
_originWrapBody: function(body, isStub) {
- var encodedOrigin = encodeURIComponent(this.getMetaPath());
+ var encodedOrigin = encodeURIComponent(this.getMetaURL());
var text = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">\n' +
'<html>\n' +
' <head>\n';
@@ -340,8 +344,7 @@ L.Clipboard = L.Class.extend({
if (meta !== '')
{
console.log('Transfer between servers\n\t"' + meta + '" vs. \n\t"' + id + '"');
- var destination = this.getMetaBase() + this.getMetaPath();
- this._dataTransferDownloadAndPasteAsync(meta, destination, htmlText);
+ this._dataTransferDownloadAndPasteAsync(meta, this.getMetaURL(), htmlText);
return;
}
@@ -397,8 +400,7 @@ L.Clipboard = L.Class.extend({
formData.append('file', content);
var that = this;
- var destination = this.getMetaBase() + this.getMetaPath();
- this._doAsyncDownload('POST', destination, formData,
+ this._doAsyncDownload('POST', this.getMetaURL(), formData,
function() {
console.log('Posted ' + content.size + ' bytes successfully');
if (usePasteKeyEvent) {
@@ -439,7 +441,7 @@ L.Clipboard = L.Class.extend({
text = this._getStubHtml();
this._onDownloadOnLargeCopyPaste();
this._downloadProgress.setURI( // richer, bigger HTML ...
- this.getMetaBase() + this.getMetaPath() + '&MimeType=text/html');
+ this.getMetaURL() + '&MimeType=text/html');
}
} else if (this._selectionType === null) {
console.log('Copy/Cut with no selection!');
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index c4c6ec7cb..c28961fb6 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -44,7 +44,7 @@ ClientSession::ClientSession(
const std::shared_ptr<DocumentBroker>& docBroker,
const Poco::URI& uriPublic,
const bool readOnly,
- const std::string& hostNoTrust) :
+ const ServerURL &serverURL) :
Session(ws, "ToClient-" + id, id, readOnly),
_docBroker(docBroker),
_uriPublic(uriPublic),
@@ -58,7 +58,7 @@ ClientSession::ClientSession(
_tileWidthTwips(0),
_tileHeightTwips(0),
_kitViewId(-1),
- _hostNoTrust(hostNoTrust),
+ _serverURL(serverURL),
_isTextDocument(false)
{
const size_t curConnections = ++LOOLWSD::NumConnections;
@@ -207,12 +207,11 @@ std::string ClientSession::getClipboardURI(bool encode)
std::string encodeChars = ",/?:@&=+$#"; // match JS encodeURIComponent
Poco::URI::encode(wopiSrc.toString(), encodeChars, encodedFrom);
- std::string proto = (LOOLWSD::isSSLEnabled() || LOOLWSD::isSSLTermination()) ? "https://" : "http://";
- std::string meta = proto + _hostNoTrust +
+ std::string meta = _serverURL.getSubURLForEndpoint(
"/lool/clipboard?WOPISrc=" + encodedFrom +
"&ServerId=" + LOOLWSD::HostIdentifier +
"&ViewId=" + std::to_string(getKitViewId()) +
- "&Tag=" + _clipboardKeys[0];
+ "&Tag=" + _clipboardKeys[0]);
if (!encode)
return meta;
@@ -1030,6 +1029,7 @@ void ClientSession::writeQueuedMessages()
LOG_TRC(getName() << " ClientSession: performed write.");
}
+// NB. also see loleaflet/src/map/Clipboard.js that does this in JS for stubs.
void ClientSession::postProcessCopyPayload(std::shared_ptr<Message> payload)
{
// Insert our meta origin if we can
@@ -1043,6 +1043,7 @@ void ClientSession::postProcessCopyPayload(std::shared_ptr<Message> payload)
if (pos != std::string::npos) // assume text/html
{
const std::string meta = getClipboardURI();
+ LOG_TRC("Inject clipboard meta origin of '" << meta << "'");
const std::string origin = "<meta name=\"origin\" content=\"" + meta + "\"/>\n";
data.insert(data.begin() + pos, origin.begin(), origin.end());
return true;
@@ -1719,7 +1720,7 @@ void ClientSession::dumpState(std::ostream& os)
<< "\n\t\ttile size Pixel: " << _tileWidthPixel << "x" << _tileHeightPixel
<< "\n\t\ttile size Twips: " << _tileWidthTwips << "x" << _tileHeightTwips
<< "\n\t\tkit ViewId: " << _kitViewId
- << "\n\t\thost (un-trusted): " << _hostNoTrust
+ << "\n\t\tour URL (un-trusted): " << _serverURL.getSubURLForEndpoint("")
<< "\n\t\tisTextDocument: " << _isTextDocument
<< "\n\t\tclipboardKeys[0]: " << _clipboardKeys[0]
<< "\n\t\tclipboardKeys[1]: " << _clipboardKeys[1]
diff --git a/wsd/ClientSession.hpp b/wsd/ClientSession.hpp
index f2bd63adc..a99832560 100644
--- a/wsd/ClientSession.hpp
+++ b/wsd/ClientSession.hpp
@@ -13,6 +13,7 @@
#include "Storage.hpp"
#include "MessageQueue.hpp"
#include "SenderQueue.hpp"
+#include "ServerURL.hpp"
#include "DocumentBroker.hpp"
#include <Poco/URI.h>
#include <Rectangle.hpp>
@@ -33,7 +34,7 @@ public:
const std::shared_ptr<DocumentBroker>& docBroker,
const Poco::URI& uriPublic,
const bool isReadOnly,
- const std::string& hostNoTrust);
+ const ServerURL &serverURL);
void construct();
virtual ~ClientSession();
@@ -260,8 +261,8 @@ private:
/// The integer id of the view in the Kit process
int _kitViewId;
- /// Un-trusted hostname of our service from the client
- const std::string _hostNoTrust;
+ /// How to find our service from the client.
+ const ServerURL _serverURL;
/// Client is using a text document?
bool _isTextDocument;
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index a81864506..1cbfcac13 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -1526,7 +1526,7 @@ std::shared_ptr<ClientSession> DocumentBroker::createNewClientSession(
const std::string& id,
const Poco::URI& uriPublic,
const bool isReadOnly,
- const std::string& hostNoTrust)
+ const ServerURL &serverURL)
{
try
{
@@ -1541,7 +1541,7 @@ std::shared_ptr<ClientSession> DocumentBroker::createNewClientSession(
// In case of WOPI, if this session is not set as readonly, it might be set so
// later after making a call to WOPI host which tells us the permission on files
// (UserCanWrite param).
- auto session = std::make_shared<ClientSession>(ws, id, shared_from_this(), uriPublic, isReadOnly, hostNoTrust);
+ auto session = std::make_shared<ClientSession>(ws, id, shared_from_this(), uriPublic, isReadOnly, serverURL);
session->construct();
return session;
@@ -2269,7 +2269,8 @@ bool ConvertToBroker::startConversion(SocketDisposition &disposition, const std:
const bool isReadOnly = true;
// FIXME: associate this with moveSocket (?)
std::shared_ptr<ProtocolHandlerInterface> nullPtr;
- _clientSession = std::make_shared<ClientSession>(nullPtr, id, docBroker, getPublicUri(), isReadOnly, "nocliphost");
+ ServerURL serverURL;
+ _clientSession = std::make_shared<ClientSession>(nullPtr, id, docBroker, getPublicUri(), isReadOnly, serverURL);
_clientSession->construct();
if (!_clientSession)
diff --git a/wsd/DocumentBroker.hpp b/wsd/DocumentBroker.hpp
index f8c2ccea2..f086ddea6 100644
--- a/wsd/DocumentBroker.hpp
+++ b/wsd/DocumentBroker.hpp
@@ -97,6 +97,7 @@ private:
int _smapsFD;
};
+class ServerURL;
class ClientSession;
/// DocumentBroker is responsible for setting up a document in jail and brokering loading it from
@@ -153,7 +154,7 @@ public:
const std::string& id,
const Poco::URI& uriPublic,
const bool isReadOnly,
- const std::string& hostNoTrust);
+ const ServerURL &serverURL);
/// Find or create a new client session for the PHP proxy
void handleProxyRequest(
@@ -161,7 +162,7 @@ public:
const std::string& id,
const Poco::URI& uriPublic,
const bool isReadOnly,
- const std::string& hostNoTrust,
+ const ServerURL &serverURL,
const std::shared_ptr<StreamSocket> &socket,
bool isWaiting);
diff --git a/wsd/FileServer.cpp b/wsd/FileServer.cpp
index 888509591..8809a582a 100644
--- a/wsd/FileServer.cpp
+++ b/wsd/FileServer.cpp
@@ -43,6 +43,7 @@
#include <Crypto.hpp>
#include "FileServer.hpp"
#include "LOOLWSD.hpp"
+#include "ServerURL.hpp"
#include <Log.hpp>
#include <Protocol.hpp>
#include <Util.hpp>
@@ -641,61 +642,12 @@ constexpr char BRANDING_UNSUPPORTED[] = "branding-unsupported";
#endif
namespace {
- /// 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;
-
- 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
- {
- return _pathPlus;
- }
-
- std::string getWebSocketUrl() const
- {
- return _schemeAuthority;
- }
- };
}
void FileServerRequestHandler::preprocessFile(const HTTPRequest& request, Poco::MemoryInputStream& message,
const std::shared_ptr<StreamSocket>& socket)
{
- ProxyURL cnxDetails(request);
+ ServerURL cnxDetails(request);
const Poco::URI::QueryParameters params = Poco::URI(request.getURI()).getQueryParameters();
@@ -963,7 +915,7 @@ void FileServerRequestHandler::preprocessAdminFile(const HTTPRequest& request,co
if (!FileServerRequestHandler::isAdminLoggedIn(request, response))
throw Poco::Net::NotAuthenticatedException("Invalid admin login");
- ProxyURL cnxDetails(request);
+ ServerURL cnxDetails(request);
std::string responseRoot = cnxDetails.getResponseRoot();
static const std::string scriptJS("<script src=\"%s/loleaflet/" LOOLWSD_VERSION_HASH "/%s.js\"></script>");
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 3b770cf03..18d8469ef 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -2956,7 +2956,7 @@ private:
}
}
- const std::string hostNoTrust = (LOOLWSD::ServerName.empty() ? request.getHost() : LOOLWSD::ServerName);
+ ServerURL serverURL(request);
LOG_INF("URL [" << LOOLWSD::anonymizeUrl(url) << "] is " << (isReadOnly ? "readonly" : "writable") << ".");
(void)request; (void)message; (void)disposition;
@@ -2973,7 +2973,7 @@ private:
{
// need to move into the DocumentBroker context before doing session lookup / creation etc.
std::string id = _id;
- disposition.setMove([docBroker, id, uriPublic, isReadOnly, hostNoTrust, sessionId, isWaiting]
+ disposition.setMove([docBroker, id, uriPublic, isReadOnly, serverURL, sessionId, isWaiting]
(const std::shared_ptr<Socket> &moveSocket)
{
LOG_TRC("Setting up docbroker thread for " << docBroker->getDocKey());
@@ -2983,7 +2983,7 @@ private:
// We no longer own this socket.
moveSocket->setThreadOwner(std::thread::id());
- docBroker->addCallback([docBroker, id, uriPublic, isReadOnly, hostNoTrust,
+ docBroker->addCallback([docBroker, id, uriPublic, isReadOnly, serverURL,
sessionId, moveSocket, isWaiting]()
{
// Now inside the document broker thread ...
@@ -2994,7 +2994,7 @@ private:
{
docBroker->handleProxyRequest(
sessionId, id, uriPublic, isReadOnly,
- hostNoTrust, streamSocket, isWaiting);
+ serverURL, streamSocket, isWaiting);
return;
}
catch (const UnauthorizedRequestException& exc)
@@ -3084,15 +3084,9 @@ private:
DocumentBroker::ChildType::Interactive, url, docKey, _id, uriPublic);
if (docBroker)
{
-#if MOBILEAPP
- const std::string hostNoTrust;
-#else
- // We can send this back to whomever sent it to us though.
- const std::string hostNoTrust = (LOOLWSD::ServerName.empty() ? request.getHost() : LOOLWSD::ServerName);
-#endif
-
+ ServerURL serverURL(request);
std::shared_ptr<ClientSession> clientSession =
- docBroker->createNewClientSession(ws, _id, uriPublic, isReadOnly, hostNoTrust);
+ docBroker->createNewClientSession(ws, _id, uriPublic, isReadOnly, serverURL);
if (clientSession)
{
// Transfer the client socket to the DocumentBroker when we get back to the poll:
diff --git a/wsd/ProxyProtocol.cpp b/wsd/ProxyProtocol.cpp
index 973d9f3c5..f11d7d942 100644
--- a/wsd/ProxyProtocol.cpp
+++ b/wsd/ProxyProtocol.cpp
@@ -24,7 +24,7 @@ void DocumentBroker::handleProxyRequest(
const std::string& id,
const Poco::URI& uriPublic,
const bool isReadOnly,
- const std::string& hostNoTrust,
+ const ServerURL &serverURL,
const std::shared_ptr<StreamSocket> &socket,
bool isWaiting)
{
@@ -34,7 +34,7 @@ void DocumentBroker::handleProxyRequest(
LOG_TRC("proxy: Create session for " << _docKey);
clientSession = createNewClientSession(
std::make_shared<ProxyProtocolHandler>(),
- id, uriPublic, isReadOnly, hostNoTrust);
+ id, uriPublic, isReadOnly, serverURL);
addSession(clientSession);
LOOLWSD::checkDiskSpaceAndWarnClients(true);
LOOLWSD::checkSessionLimitsAndWarnClients();
diff --git a/wsd/ServerURL.hpp b/wsd/ServerURL.hpp
new file mode 100644
index 000000000..3e96fff98
--- /dev/null
+++ b/wsd/ServerURL.hpp
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <string>
+#include <Poco/Net/HTTPRequest.h>
+#include "LOOLWSD.hpp"
+
+/** This class helps us to build a URL that will reliably point back
+ * at our service. It does very simple splitting of proxy U
+ * and handles the proxy prefix feature.
+ */
+class ServerURL
+{
+ std::string _schemeProtocol;
+ std::string _schemeAuthority;
+ std::string _pathPlus;
+public:
+ ServerURL(const Poco::Net::HTTPRequest &request)
+ {
+ init(request.getHost(), request.get("ProxyPrefix", ""));
+ }
+
+ explicit ServerURL()
+ {
+ init("nohostname", "");
+ }
+
+ void init(const std::string &host, const std::string &proxyPrefix)
+ {
+ // The user can override the ServerRoot with a new prefix.
+ _pathPlus = LOOLWSD::ServiceRoot;
+
+ bool ssl = (LOOLWSD::isSSLEnabled() || LOOLWSD::isSSLTermination());
+ std::string serverName = LOOLWSD::ServerName.empty() ? host : LOOLWSD::ServerName;
+ _schemeProtocol = (ssl ? "wss://" : "ws://");
+ _schemeAuthority = serverName;
+
+ // A well formed ProxyPrefix will override it.
+ std::string url = proxyPrefix;
+ if (url.size() <= 0)
+ return;
+
+ size_t pos = url.find("://");
+ if (pos != std::string::npos) {
+ pos += 3;
+ auto hostEndPos = url.find("/", pos);
+ if (hostEndPos != std::string::npos)
+ {
+ _schemeProtocol = url.substr(0, pos);
+ _schemeAuthority = url.substr(pos, hostEndPos - pos);
+ _pathPlus = url.substr(hostEndPos);
+ return;
+ }
+ else
+ LOG_ERR("Unusual proxy prefix '" << url << "'");
+ } else
+ LOG_ERR("No http[s]:// in unusual proxy prefix '" << url << "'");
+ }
+
+ std::string getResponseRoot() const
+ {
+ return _pathPlus;
+ }
+
+ std::string getWebSocketUrl() const
+ {
+ return _schemeProtocol + _schemeAuthority;
+ }
+
+ std::string getSubURLForEndpoint(const std::string &path) const
+ {
+ return _schemeProtocol + _schemeAuthority + _pathPlus + path;
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
More information about the Libreoffice-commits
mailing list