[Libreoffice-commits] online.git: loolwsd/FileServer.hpp loolwsd/LOOLWSD.cpp loolwsd/LOOLWSD.hpp loolwsd/loolwsd.xml.in loolwsd/Makefile.am loolwsd/Storage.cpp loolwsd/Util.hpp

Marco Cecchetti marco.cecchetti at collabora.com
Tue Jul 19 09:00:08 UTC 2016


 loolwsd/FileServer.hpp |    2 
 loolwsd/LOOLWSD.cpp    |  107 ++++++++++++++++++++++++++++++++++++++-----------
 loolwsd/LOOLWSD.hpp    |   42 ++++++++++++++++---
 loolwsd/Makefile.am    |    4 -
 loolwsd/Storage.cpp    |   45 ++++++++++----------
 loolwsd/Util.hpp       |   39 +++++++++++++++++
 loolwsd/loolwsd.xml.in |    1 
 7 files changed, 184 insertions(+), 56 deletions(-)

New commits:
commit 6e616b745f663898810de39141bdc65535c92601
Author: Marco Cecchetti <marco.cecchetti at collabora.com>
Date:   Mon Jul 18 13:45:36 2016 +0200

    loolwsd: SSL support can be enabled/disabled on server start
    
    SSL support is enabled by default, it can be disabled by passing the
    `--disable-ssl` switch on the command line or by setting `ssl.enable`
    property in loolwsd.xml config file.
    
    It is still possible to build loolwsd with no SSL support at all.
    
    Change-Id: I00f952edc64f87f61505af44fdc2a715780dc44c
    Reviewed-on: https://gerrit.libreoffice.org/27288
    Reviewed-by: Jan Holesovsky <kendy at collabora.com>
    Tested-by: Jan Holesovsky <kendy at collabora.com>

diff --git a/loolwsd/FileServer.hpp b/loolwsd/FileServer.hpp
index 7c19e10..874db99 100644
--- a/loolwsd/FileServer.hpp
+++ b/loolwsd/FileServer.hpp
@@ -217,7 +217,7 @@ private:
     {
         HTMLForm form(request, request.stream());
 
-        const auto host = (LOOLWSD::SSLEnabled ? "wss://" : "ws://") + (LOOLWSD::ServerName.empty() ? request.getHost() : LOOLWSD::ServerName);
+        const auto host = (LOOLWSD::isSSLEnabled() ? "wss://" : "ws://") + (LOOLWSD::ServerName.empty() ? request.getHost() : LOOLWSD::ServerName);
         const auto path = Poco::Path(LOOLWSD::FileServerRoot, getRequestPathname(request));
 
         Log::debug("Preprocessing file: " + path.toString());
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 97851ab..ff36b76 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -10,6 +10,16 @@
 #include "LOOLWSD.hpp"
 #include "config.h"
 
+/* Default host used in the start test URI */
+#define LOOLWSD_TEST_HOST "localhost"
+
+/* Default loleaflet UI used in the start test URI */
+#define LOOLWSD_TEST_LOLEAFLET_UI "/loleaflet/" LOOLWSD_VERSION_HASH "/loleaflet.html"
+
+/* Default document used in the start test URI */
+#define LOOLWSD_TEST_DOCUMENT_RELATIVE_PATH "test/data/hello-world.odt"
+
+
 // This is the main source for the loolwsd program. LOOL uses several loolwsd processes: one main
 // parent process that listens on the TCP port and accepts connections from LOOL clients, and a
 // number of child processes, each which handles a viewing (editing) session for one document.
@@ -787,7 +797,7 @@ private:
         const std::string urlsrc = "urlsrc";
         const auto& config = Application::instance().config();
         const std::string loleafletHtml = config.getString("loleaflet_html", "loleaflet.html");
-        const std::string uriValue = (LOOLWSD::SSLEnabled ? "https://" : "http://") +
+        const std::string uriValue = (LOOLWSD::isSSLEnabled() ? "https://" : "http://") +
             (LOOLWSD::ServerName.empty() ? request.getHost() : LOOLWSD::ServerName) +
             "/loleaflet/" LOOLWSD_VERSION_HASH "/" + loleafletHtml + "?";
 
@@ -1207,6 +1217,35 @@ public:
     }
 };
 
+namespace {
+
+static inline
+ServerSocket* lcl_getServerSocket(int nClientPortNumber)
+{
+    return (LOOLWSD::isSSLEnabled()) ? new SecureServerSocket(nClientPortNumber)
+                       : new ServerSocket(nClientPortNumber);
+}
+
+static inline
+std::string lcl_getLaunchURI()
+{
+    std::string aAbsTopSrcDir = Poco::Path(Application::instance().commandPath()).parent().toString();
+    aAbsTopSrcDir = Poco::Path(aAbsTopSrcDir).absolute().toString();
+
+    std::string aLaunchURI("    ");
+    aLaunchURI += ((LOOLWSD::isSSLEnabled()) ? "https://" : "http://");
+    aLaunchURI += LOOLWSD_TEST_HOST ":";
+    aLaunchURI += std::to_string(ClientPortNumber);
+    aLaunchURI += LOOLWSD_TEST_LOLEAFLET_UI;
+    aLaunchURI += "?file_path=file://";
+    aLaunchURI += aAbsTopSrcDir;
+    aLaunchURI += LOOLWSD_TEST_DOCUMENT_RELATIVE_PATH;
+
+    return aLaunchURI;
+}
+
+} // anonymous namespace
+
 std::atomic<unsigned> LOOLWSD::NextSessionId;
 int LOOLWSD::ForKitWritePipe = -1;
 std::string LOOLWSD::Cache = LOOLWSD_CACHEDIR;
@@ -1216,12 +1255,8 @@ std::string LOOLWSD::ChildRoot;
 std::string LOOLWSD::ServerName;
 std::string LOOLWSD::FileServerRoot;
 std::string LOOLWSD::LOKitVersion;
-bool LOOLWSD::SSLEnabled =
-#if ENABLE_SSL
-    true;
-#else
-    false;
-#endif
+Util::RuntimeCostant<bool> LOOLWSD::SSLEnabled;
+
 static std::string UnitTestLibrary;
 
 unsigned int LOOLWSD::NumPreSpawnedChildren = 0;
@@ -1279,6 +1314,7 @@ void LOOLWSD::initialize(Application& self)
         { "loleaflet_html", "loleaflet.html" },
         { "logging.color", "true" },
         { "logging.level", "trace" },
+        { "ssl.enable", "true" },
         { "ssl.cert_file_path", LOOLWSD_CONFIGDIR "/cert.pem" },
         { "ssl.key_file_path", LOOLWSD_CONFIGDIR "/key.pem" },
         { "ssl.ca_file_path", LOOLWSD_CONFIGDIR "/ca-chain.cert.pem" },
@@ -1309,20 +1345,38 @@ void LOOLWSD::initialize(Application& self)
     // Allow UT to manipulate before using configuration values.
     UnitWSD::get().configure(config());
 
+#if ENABLE_SSL
+    LOOLWSD::SSLEnabled.set(getConfigValue<bool>(conf, "ssl.enable", true));
+#else
+    LOOLWSD::SSLEnabled.set(false);
+#endif
+
+    if (LOOLWSD::isSSLEnabled())
+    {
+        Log::info("SSL support: SSL is enabled.");
+    }
+    else
+    {
+        Log::warn("SSL support: SSL is disabled.");
+    }
+
     Cache = getPathFromConfig("tile_cache_path");
     SysTemplate = getPathFromConfig("sys_template_path");
     LoTemplate = getPathFromConfig("lo_template_path");
     ChildRoot = getPathFromConfig("child_root_path");
     ServerName = config().getString("server_name");
     FileServerRoot = getPathFromConfig("file_server_root_path");
-    NumPreSpawnedChildren = getUIntConfigValue(conf, "num_prespawn_children", 1);
+    NumPreSpawnedChildren = getConfigValue<unsigned int>(conf, "num_prespawn_children", 1);
 
-    const auto maxConcurrency = getUIntConfigValue(conf, "per_document.max_concurrency", 4);
+    const auto maxConcurrency = getConfigValue<unsigned int>(conf, "per_document.max_concurrency", 4);
     if (maxConcurrency > 0)
     {
         setenv("MAX_CONCURRENCY", std::to_string(maxConcurrency).c_str(), 1);
     }
 
+    Log::warn("Launch this in your browser:");
+    Log::warn(lcl_getLaunchURI());
+
     // In Trial Versions we might want to set some limits.
     LOOLWSD::NumDocBrokers = 0;
     LOOLWSD::NumConnections = 0;
@@ -1339,9 +1393,13 @@ void LOOLWSD::initialize(Application& self)
     ServerApplication::initialize(self);
 }
 
-#if ENABLE_SSL
 void LOOLWSD::initializeSSL()
 {
+    if (!LOOLWSD::isSSLEnabled())
+    {
+        return;
+    }
+
     const auto ssl_cert_file_path = getPathFromConfig("ssl.cert_file_path");
     Log::info("SSL Cert file: " + ssl_cert_file_path);
 
@@ -1378,7 +1436,6 @@ void LOOLWSD::initializeSSL()
     Poco::Net::Context::Ptr sslClientContext = new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, sslClientParams);
     Poco::Net::SSLManager::instance().initializeClient(consoleClientHandler, invalidClientCertHandler, sslClientContext);
 }
-#endif
 
 void LOOLWSD::uninitialize()
 {
@@ -1403,6 +1460,10 @@ void LOOLWSD::defineOptions(OptionSet& optionSet)
                         .repeatable(false)
                         .argument("port number"));
 
+    optionSet.addOption(Option("disable-ssl", "", "Disable SSL security layer.")
+                        .required(false)
+                        .repeatable(false));
+
     optionSet.addOption(Option("override", "o", "Override any setting by providing fullxmlpath=value.")
                         .required(false)
                         .repeatable(true)
@@ -1439,6 +1500,8 @@ void LOOLWSD::handleOption(const std::string& optionName,
         DisplayVersion = true;
     else if (optionName == "port")
         ClientPortNumber = std::stoi(value);
+    else if (optionName == "disable-ssl")
+        _overrideSettings["ssl.enable"] = "false";
     else if (optionName == "override")
     {
         std::string optName;
@@ -1513,9 +1576,7 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
         std::cout << "loolwsd " << version << " - " << hash << std::endl;
     }
 
-#if ENABLE_SSL
     initializeSSL();
-#endif
 
     char *locale = setlocale(LC_ALL, nullptr);
     if (locale == nullptr || std::strcmp(locale, "C") == 0)
@@ -1585,13 +1646,11 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
     params2->setMaxThreads(MAX_SESSIONS);
 
     // Start a server listening on the port for clients
-#if ENABLE_SSL
-    SecureServerSocket svs(ClientPortNumber);
-#else
-    ServerSocket svs(ClientPortNumber);
-#endif
+
+    std::unique_ptr<ServerSocket> psvs(lcl_getServerSocket(ClientPortNumber));
+
     ThreadPool threadPool(NumPreSpawnedChildren*6, MAX_SESSIONS * 2);
-    HTTPServer srv(new ClientRequestHandlerFactory(fileServer), threadPool, svs, params1);
+    HTTPServer srv(new ClientRequestHandlerFactory(fileServer), threadPool, *psvs, params1);
     Log::info("Starting master server listening on " + std::to_string(ClientPortNumber));
     srv.start();
 
@@ -1757,10 +1816,12 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
         Util::removeFile(path, true);
     }
 
-#if ENABLE_SSL
-    Poco::Net::uninitializeSSL();
-    Poco::Crypto::uninitializeCrypto();
-#endif
+    if (LOOLWSD::isSSLEnabled())
+    {
+        Poco::Net::uninitializeSSL();
+        Poco::Crypto::uninitializeCrypto();
+    }
+
 
     Log::info("Process [loolwsd] finished.");
 
diff --git a/loolwsd/LOOLWSD.hpp b/loolwsd/LOOLWSD.hpp
index b750bda..3a0fda6 100644
--- a/loolwsd/LOOLWSD.hpp
+++ b/loolwsd/LOOLWSD.hpp
@@ -43,7 +43,6 @@ public:
     static std::string ServerName;
     static std::string FileServerRoot;
     static std::string LOKitVersion;
-    static bool SSLEnabled;
     static std::atomic<unsigned> NumDocBrokers;
     static std::atomic<unsigned> NumConnections;
 
@@ -53,6 +52,12 @@ public:
         return Util::encodeId(++NextSessionId, 4);
     }
 
+    static
+    bool isSSLEnabled()
+    {
+        return LOOLWSD::SSLEnabled.get();
+    }
+
 protected:
     void initialize(Poco::Util::Application& self) override;
     void uninitialize() override;
@@ -61,16 +66,37 @@ protected:
     int main(const std::vector<std::string>& args) override;
 
 private:
+    static Util::RuntimeCostant<bool> SSLEnabled;
+
     void initializeSSL();
     void displayHelp();
     Poco::Process::PID createForKit();
 
+
+    class ConfigValueGetter
+    {
+        Poco::Util::LayeredConfiguration& mconfig;
+        const std::string& mname;
+
+    public:
+        ConfigValueGetter(Poco::Util::LayeredConfiguration& config,
+                          const std::string& name)
+            : mconfig(config)
+            , mname(name)
+        {}
+
+        void operator()(unsigned int& value) { value = mconfig.getUInt(mname); }
+        void operator()(bool& value) { value = mconfig.getBool(mname); }
+    };
+
+    template<typename T>
     static
-    bool getSafeUIntConfig(Poco::Util::LayeredConfiguration& config, const std::string& name, unsigned int& value)
+    bool getSafeConfig(Poco::Util::LayeredConfiguration& config,
+                       const std::string& name, T& value)
     {
         try
         {
-            value = config.getUInt(name);
+            ConfigValueGetter(config, name)(value);
             return true;
         }
         catch (Poco::SyntaxException)
@@ -80,12 +106,14 @@ private:
         return false;
     }
 
+    template<typename T>
     static
-    unsigned int getUIntConfigValue(Poco::Util::LayeredConfiguration& config, const std::string& name, const unsigned int def)
+    T getConfigValue(Poco::Util::LayeredConfiguration& config,
+                     const std::string& name, const T def)
     {
-        unsigned int value = def;
-        if (getSafeUIntConfig(config, name, value) ||
-            getSafeUIntConfig(config, name + "[@default]", value))
+        T value = def;
+        if (getSafeConfig(config, name, value) ||
+            getSafeConfig(config, name + "[@default]", value))
         {
             return value;
         }
diff --git a/loolwsd/Makefile.am b/loolwsd/Makefile.am
index 5546181..5e7186d 100644
--- a/loolwsd/Makefile.am
+++ b/loolwsd/Makefile.am
@@ -138,10 +138,8 @@ clean-local:
 	if test "z at SYSTEMPLATE_PATH@" != "z"; then rm -rf "@SYSTEMPLATE_PATH@"; fi
 
 run: all @JAILS_PATH@ @SYSTEMPLATE_PATH@/system_stamp
-	@echo "Launching loolwsd - launch this in your browser:"
+	@echo "Launching loolwsd"
 	@cp $(abs_top_srcdir)/test/data/hello.odt $(abs_top_srcdir)/test/data/hello-world.odt
-	@PROTOCOL="http" ; if test "z at ENABLE_SSL@" != "z"; then PROTOCOL="https" ; fi ; \
-		echo "   $$PROTOCOL://localhost:9980/loleaflet/@LOOLWSD_VERSION_HASH@/loleaflet.html?file_path=file://$(abs_top_srcdir)/test/data/hello-world.odt"
 	@echo
 	./loolwsd --o:sys_template_path="@SYSTEMPLATE_PATH@" --o:lo_template_path="@LO_PATH@" \
 			  --o:child_root_path="@JAILS_PATH@" --o:storage.filesystem[@allow]=true \
diff --git a/loolwsd/Storage.cpp b/loolwsd/Storage.cpp
index 372ea2f..0b8bfda 100644
--- a/loolwsd/Storage.cpp
+++ b/loolwsd/Storage.cpp
@@ -28,6 +28,7 @@
 #include "Auth.hpp"
 #include "Common.hpp"
 #include "Exceptions.hpp"
+#include "LOOLWSD.hpp"
 #include "Log.hpp"
 #include "Unit.hpp"
 #include "Util.hpp"
@@ -236,6 +237,17 @@ bool LocalStorage::saveLocalFileToStorage()
     return true;
 }
 
+namespace {
+
+static inline
+Poco::Net::HTTPClientSession* lcl_getHTTPClientSession(const Poco::URI& uri)
+{
+    return (LOOLWSD::isSSLEnabled()) ? new Poco::Net::HTTPSClientSession(uri.getHost(), uri.getPort(), Poco::Net::SSLManager::instance().defaultClientContext())
+                       : new Poco::Net::HTTPClientSession(uri.getHost(), uri.getPort());
+}
+
+} // anonymous namespace
+
 ///////////////////
 // WopiStorage Impl
 ///////////////////
@@ -243,17 +255,14 @@ StorageBase::FileInfo WopiStorage::getFileInfo(const Poco::URI& uri)
 {
     Log::debug("Getting info for wopi uri [" + uri.toString() + "].");
 
-#if ENABLE_SSL
-    Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort(), Poco::Net::SSLManager::instance().defaultClientContext());
-#else
-    Poco::Net::HTTPClientSession session(uri.getHost(), uri.getPort());
-#endif
+    std::unique_ptr<Poco::Net::HTTPClientSession> psession(lcl_getHTTPClientSession(uri));
+
     Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, uri.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1);
     request.set("User-Agent", "LOOLWSD WOPI Agent");
-    session.sendRequest(request);
+    psession->sendRequest(request);
 
     Poco::Net::HTTPResponse response;
-    std::istream& rs = session.receiveResponse(response);
+    std::istream& rs = psession->receiveResponse(response);
 
     auto logger = Log::trace();
     logger << "WOPI::CheckFileInfo header for URI [" << uri.toString() << "]:\n";
@@ -303,17 +312,14 @@ std::string WopiStorage::loadStorageFileToLocal()
     const auto url = uriObject.getPath() + "/contents?" + uriObject.getQuery();
     Log::debug("Wopi requesting: " + url);
 
-#if ENABLE_SSL
-    Poco::Net::HTTPSClientSession session(uriObject.getHost(), uriObject.getPort(), Poco::Net::SSLManager::instance().defaultClientContext());
-#else
-    Poco::Net::HTTPClientSession session(uriObject.getHost(), uriObject.getPort());
-#endif
+    std::unique_ptr<Poco::Net::HTTPClientSession> psession(lcl_getHTTPClientSession(uriObject));
+
     Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, url, Poco::Net::HTTPMessage::HTTP_1_1);
     request.set("User-Agent", "LOOLWSD WOPI Agent");
-    session.sendRequest(request);
+    psession->sendRequest(request);
 
     Poco::Net::HTTPResponse response;
-    std::istream& rs = session.receiveResponse(response);
+    std::istream& rs = psession->receiveResponse(response);
 
     auto logger = Log::trace();
     logger << "WOPI::GetFile header for URI [" << _uri << "]:\n";
@@ -348,22 +354,19 @@ bool WopiStorage::saveLocalFileToStorage()
     const auto url = uriObject.getPath() + "/contents?" + uriObject.getQuery();
     Log::debug("Wopi posting: " + url);
 
-#if ENABLE_SSL
-    Poco::Net::HTTPSClientSession session(uriObject.getHost(), uriObject.getPort(), Poco::Net::SSLManager::instance().defaultClientContext());
-#else
-    Poco::Net::HTTPClientSession session(uriObject.getHost(), uriObject.getPort());
-#endif
+    std::unique_ptr<Poco::Net::HTTPClientSession> psession(lcl_getHTTPClientSession(uriObject));
+
     Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, url, Poco::Net::HTTPMessage::HTTP_1_1);
     request.set("X-WOPIOverride", "PUT");
     request.setContentType("application/octet-stream");
     request.setContentLength(size);
 
-    std::ostream& os = session.sendRequest(request);
+    std::ostream& os = psession->sendRequest(request);
     std::ifstream ifs(_jailedFilePath);
     Poco::StreamCopier::copyStream(ifs, os);
 
     Poco::Net::HTTPResponse response;
-    std::istream& rs = session.receiveResponse(response);
+    std::istream& rs = psession->receiveResponse(response);
     std::ostringstream oss;
     Poco::StreamCopier::copyStream(rs, oss);
 
diff --git a/loolwsd/Util.hpp b/loolwsd/Util.hpp
index 138d791..8b866a3 100644
--- a/loolwsd/Util.hpp
+++ b/loolwsd/Util.hpp
@@ -185,7 +185,44 @@ namespace Util
         std::set<std::string> _denied;
     };
 
-};
+    template<typename T>
+    class RuntimeCostant
+    {
+        T mValue;
+        bool mInitialized;
+
+    public:
+        RuntimeCostant()
+            : mValue()
+            , mInitialized(false)
+        {}
+
+        const T& get()
+        {
+            if(mInitialized)
+            {
+                return mValue;
+            }
+            else
+            {
+                throw std::runtime_error("RuntimeCostant instance read before being initialized.");
+            }
+        }
+
+        void set(const T& value)
+        {
+            if(mInitialized)
+            {
+                throw std::runtime_error("RuntimeCostant instance already initialized.");
+            }
+            else
+            {
+                mInitialized = true;
+                mValue = value;
+            }
+        }
+    };
+} // end namespace Util
 
 #endif
 
diff --git a/loolwsd/loolwsd.xml.in b/loolwsd/loolwsd.xml.in
index b3251e4..6366dd6 100644
--- a/loolwsd/loolwsd.xml.in
+++ b/loolwsd/loolwsd.xml.in
@@ -26,6 +26,7 @@
     </logging>
 
     <ssl desc="SSL settings">
+        <enable type="bool" default="true">true</enable>
         <cert_file_path desc="Path to the cert file" relative="false">/etc/loolwsd/cert.pem</cert_file_path>
         <key_file_path desc="Path to the key file" relative="false">/etc/loolwsd/key.pem</key_file_path>
         <ca_file_path desc="Path to the ca file" relative="false">/etc/loolwsd/ca-chain.cert.pem</ca_file_path>


More information about the Libreoffice-commits mailing list