loolwsd.xml.in | 1 + net/Socket.cpp | 12 ++++++++++++ net/Socket.hpp | 3 +++ wsd/LOOLWSD.cpp | 13 +++++++++++++ wsd/LOOLWSD.hpp | 1 + wsd/ProxyProtocol.cpp | 5 +++++ 6 files changed, 35 insertions(+)
New commits: commit 2cbf6d12a0d4e4b6c76d3e9419ce67cda67f6c6e Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Thu May 7 21:11:38 2020 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Fri May 8 18:05:14 2020 +0200 Proxy: only accept request from localhost. Also - add net.proxy_prefix setting to enable this. Change-Id: I87f5aab2316c053ea1bc8cc177e4a54ba0455697 Reviewed-on: https://gerrit.libreoffice.org/c/online/+/93682 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Michael Meeks <michael.me...@collabora.com> diff --git a/loolwsd.xml.in b/loolwsd.xml.in index bbd37ec35..e66f3526d 100644 --- a/loolwsd.xml.in +++ b/loolwsd.xml.in @@ -77,6 +77,7 @@ <proto type="string" default="all" desc="Protocol to use IPv4, IPv6 or all for both">all</proto> <listen type="string" default="any" desc="Listen address that loolwsd binds to. Can be 'any' or 'loopback'.">any</listen> <service_root type="path" default="" desc="Prefix all the pages, websockets, etc. with this path."></service_root> + <proxy_prefix type="bool" default="false" desc="Enable a ProxyPrefix to be passed int through which to redirect requests"></proxy_prefix> <post_allow desc="Allow/deny client IP address for POST(REST)." allow="true"> <host desc="The IPv4 private 192.168 block as plain IPv4 dotted decimal addresses.">192\.168\.[0-9]{1,3}\.[0-9]{1,3}</host> <host desc="Ditto, but as IPv4-mapped IPv6 addresses">::ffff:192\.168\.[0-9]{1,3}\.[0-9]{1,3}</host> diff --git a/net/Socket.cpp b/net/Socket.cpp index 5e96ab2ac..568fcca5e 100644 --- a/net/Socket.cpp +++ b/net/Socket.cpp @@ -694,6 +694,18 @@ int Socket::getPid() const return creds.pid; } +// Does this socket come from the localhost ? +bool Socket::isLocal() const +{ + if (_clientAddress.size() < 1) + return false; + if (_clientAddress[0] == '/') // Unix socket + return true; + if (_clientAddress == "::1") + return true; + return _clientAddress.rfind("127.0.0.", 0); +} + std::shared_ptr<Socket> LocalServerSocket::accept() { const int rc = ::accept4(getFD(), nullptr, nullptr, SOCK_NONBLOCK); diff --git a/net/Socket.hpp b/net/Socket.hpp index 37e289a63..c004a1748 100644 --- a/net/Socket.hpp +++ b/net/Socket.hpp @@ -274,6 +274,9 @@ public: } #endif + // Does this socket come from the localhost ? + bool isLocal() const; + virtual void dumpState(std::ostream&) {} /// Set the thread-id we're bound to diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp index 18d8469ef..d024ee436 100644 --- a/wsd/LOOLWSD.cpp +++ b/wsd/LOOLWSD.cpp @@ -725,6 +725,7 @@ std::string LOOLWSD::ConfigDir = LOOLWSD_CONFIGDIR "/conf.d"; std::string LOOLWSD::LogLevel = "trace"; bool LOOLWSD::AnonymizeUserData = false; bool LOOLWSD::CheckLoolUser = true; +bool LOOLWSD::IsProxyPrefixEnabled = false; #if ENABLE_SSL Util::RuntimeConstant<bool> LOOLWSD::SSLEnabled; Util::RuntimeConstant<bool> LOOLWSD::SSLTermination; @@ -901,6 +902,7 @@ void LOOLWSD::initialize(Application& self) { "net.listen", "any" }, { "net.proto", "all" }, { "net.service_root", "" }, + { "net.proxy_prefix", "false" }, { "num_prespawn_children", "1" }, { "per_document.always_save_on_exit", "false" }, { "per_document.autosave_duration_secs", "300" }, @@ -1120,6 +1122,8 @@ void LOOLWSD::initialize(Application& self) while (ServiceRoot.length() > 0 && ServiceRoot[ServiceRoot.length() - 1] == '/') ServiceRoot.pop_back(); + IsProxyPrefixEnabled = getConfigValue<bool>(conf, "net.proxy_prefix", false); + #if ENABLE_SSL LOOLWSD::SSLEnabled.set(getConfigValue<bool>(conf, "ssl.enable", true)); #endif @@ -2256,6 +2260,15 @@ private: if (!Util::startsWith(request.getURI(), LOOLWSD::ServiceRoot)) throw BadRequestException("The request does not start with prefix: " + LOOLWSD::ServiceRoot); + // Config & security ... + if (request.has("ProxyPrefix")) + { + if (!LOOLWSD::IsProxyPrefixEnabled) + throw BadRequestException("ProxyPrefix present but net.proxy_prefix is not enabled"); + else if (!socket->isLocal()) + throw BadRequestException("ProxyPrefix request from non-local socket"); + } + std::string requestURIString(request.getURI().substr(LOOLWSD::ServiceRoot.length())); request.setURI(requestURIString); diff --git a/wsd/LOOLWSD.hpp b/wsd/LOOLWSD.hpp index 3172f8bb7..f5cb6c69d 100644 --- a/wsd/LOOLWSD.hpp +++ b/wsd/LOOLWSD.hpp @@ -242,6 +242,7 @@ public: static std::string LogLevel; static bool AnonymizeUserData; static bool CheckLoolUser; + static bool IsProxyPrefixEnabled; static std::atomic<unsigned> NumConnections; static std::unique_ptr<TraceFileWriter> TraceDumper; #if !MOBILEAPP diff --git a/wsd/ProxyProtocol.cpp b/wsd/ProxyProtocol.cpp index 26ea53e39..7c03d65e8 100644 --- a/wsd/ProxyProtocol.cpp +++ b/wsd/ProxyProtocol.cpp @@ -31,6 +31,11 @@ void DocumentBroker::handleProxyRequest( std::shared_ptr<ClientSession> clientSession; if (sessionId == "fetchsession") { + bool isLocal = socket->isLocal(); + LOG_TRC("proxy: validate that socket is from localhost: " << isLocal); + if (!isLocal) + throw BadRequestException("invalid host - only connect from localhost"); + LOG_TRC("proxy: Create session for " << _docKey); clientSession = createNewClientSession( std::make_shared<ProxyProtocolHandler>(), _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits