common/Crypto.cpp | 10 +++ common/Crypto.hpp | 7 ++ loleaflet/dist/admin/admin.html | 5 + loleaflet/dist/admin/adminAnalytics.html | 5 + loleaflet/dist/admin/adminHistory.html | 6 +- loleaflet/dist/admin/adminSettings.html | 5 + loleaflet/dist/loleaflet.html | 4 - wsd/FileServer.cpp | 86 +++++++++++++++++++++++++++++-- wsd/FileServer.hpp | 2 9 files changed, 115 insertions(+), 15 deletions(-)
New commits: commit 61981d6c2cbb5d5371b43ea9d52af3076bf85f42 Author: Henry Castro <[email protected]> Date: Wed Apr 25 15:53:38 2018 -0400 respond different logo brands when it has support Change-Id: Icddc8b67a20fd829c90c3c5d8eb6942da9c5e74d Reviewed-on: https://gerrit.libreoffice.org/53583 Reviewed-by: Jan Holesovsky <[email protected]> Tested-by: Jan Holesovsky <[email protected]> diff --git a/common/Crypto.cpp b/common/Crypto.cpp index 2c125a2f0..705de2590 100644 --- a/common/Crypto.cpp +++ b/common/Crypto.cpp @@ -127,6 +127,16 @@ int SupportKey::validDaysRemaining() return days; } +DateTime SupportKey::expiry() const +{ + return _impl->_expiry; +} + +std::string SupportKey::data() const +{ + return _impl->_data; +} + #endif // ENABLE_SUPPORT_KEY /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/common/Crypto.hpp b/common/Crypto.hpp index 94b194cc2..079a4f742 100644 --- a/common/Crypto.hpp +++ b/common/Crypto.hpp @@ -15,6 +15,9 @@ #include <memory> struct SupportKeyImpl; +namespace Poco { + class DateTime; +} class SupportKey { std::unique_ptr<SupportKeyImpl> _impl; @@ -28,6 +31,10 @@ public: /// How many days until key expires int validDaysRemaining(); + + Poco::DateTime expiry() const; + + std::string data() const; }; #endif diff --git a/loleaflet/dist/admin/admin.html b/loleaflet/dist/admin/admin.html index 306da27f7..f23d510ca 100644 --- a/loleaflet/dist/admin/admin.html +++ b/loleaflet/dist/admin/admin.html @@ -19,8 +19,8 @@ </head> <body> <script src="/loleaflet/dist/admin-bundle.js"></script> - <script src="/loleaflet/dist/branding.js"></script> - <script>if (brandProductName) {l10nstrings.strProductName = brandProductName}</script> + <!--%BRANDING_JS%--> + <script>if (typeof brandProductName !== 'undefined') {l10nstrings.strProductName = brandProductName}</script> <script>document.title = l10nstrings.strProductName + ' - ' + l10nstrings.strAdminConsole</script> <script> if (window.location.protocol == "https:") { @@ -141,5 +141,6 @@ <li><a tabindex="-1" href="#"><script>document.write(l10nstrings.strKill)</script></a></li> </ul> </div> +<!--%FOOTER%--> </body> </html> diff --git a/loleaflet/dist/admin/adminAnalytics.html b/loleaflet/dist/admin/adminAnalytics.html index 34b78c30a..1e801fcb1 100644 --- a/loleaflet/dist/admin/adminAnalytics.html +++ b/loleaflet/dist/admin/adminAnalytics.html @@ -19,8 +19,8 @@ </head> <body> <script src="/loleaflet/dist/admin-bundle.js"></script> - <script src="/loleaflet/dist/branding.js"></script> - <script>if (brandProductName) {l10nstrings.strProductName = brandProductName}</script> + <!--%BRANDING_JS%--> + <script>if (typeof brandProductName !== 'undefined') {l10nstrings.strProductName = brandProductName}</script> <script>document.title = l10nstrings.strProductName + ' - ' + l10nstrings.strAdminConsole</script> <script> if (window.location.protocol == "https:") { @@ -105,5 +105,6 @@ </div> </div> </div> +<!--%FOOTER%--> </body> </html> diff --git a/loleaflet/dist/admin/adminHistory.html b/loleaflet/dist/admin/adminHistory.html index 76dec2c9b..7245a3d04 100644 --- a/loleaflet/dist/admin/adminHistory.html +++ b/loleaflet/dist/admin/adminHistory.html @@ -20,8 +20,8 @@ </head> <body> <script src="/loleaflet/dist/admin-bundle.js"></script> - <script src="/loleaflet/dist/branding.js"></script> - <script>if (brandProductName) {l10nstrings.strProductName = brandProductName}</script> + <!--%BRANDING_JS%--> + <script>if (typeof brandProductName !== 'undefined') {l10nstrings.strProductName = brandProductName}</script> <script>document.title = l10nstrings.strProductName + ' - ' + l10nstrings.strAdminConsole</script> <script> if (window.location.protocol == "https:") { @@ -71,7 +71,7 @@ </div> </div> </div> - +<!--%FOOTER%--> <!-- Bootstrap core JavaScript ================================================== --> diff --git a/loleaflet/dist/admin/adminSettings.html b/loleaflet/dist/admin/adminSettings.html index 7ca0061a4..c7b21879d 100644 --- a/loleaflet/dist/admin/adminSettings.html +++ b/loleaflet/dist/admin/adminSettings.html @@ -19,8 +19,8 @@ </head> <body> <script src="/loleaflet/dist/admin-bundle.js"></script> - <script src="/loleaflet/dist/branding.js"></script> - <script>if (brandProductName) {l10nstrings.strProductName = brandProductName}</script> + <!--%BRANDING_JS%--> + <script>if (typeof brandProductName !== 'undefined') {l10nstrings.strProductName = brandProductName}</script> <script>document.title = l10nstrings.strProductName + ' - ' + l10nstrings.strAdminConsole</script> <script> if (window.location.protocol == "https:") { @@ -97,5 +97,6 @@ </div> </div> </div> + <!--%FOOTER%--> </body> </html> diff --git a/loleaflet/dist/loleaflet.html b/loleaflet/dist/loleaflet.html index 2ec8f8f92..470b0acad 100644 --- a/loleaflet/dist/loleaflet.html +++ b/loleaflet/dist/loleaflet.html @@ -18,7 +18,7 @@ }; window.addEventListener('message', PostMessageReadyListener, false); </script> -<link rel="stylesheet" href="/loleaflet/%VERSION%/branding.css"> <!-- add your logo here --> +<!--%BRANDING_CSS%--> <!-- add your logo here --> <link rel="localizations" href="/loleaflet/%VERSION%/l10n/localizations.json" type="application/vnd.oftn.l10n+json"/> <link rel="localizations" href="/loleaflet/%VERSION%/l10n/locore-localizations.json" type="application/vnd.oftn.l10n+json" /> <link rel="localizations" href="/loleaflet/%VERSION%/l10n/uno-localizations.json" type="application/vnd.oftn.l10n+json" /> @@ -98,7 +98,7 @@ window.outOfFocusTimeoutSecs = %OUT_OF_FOCUS_TIMEOUT_SECS%; window.idleTimeoutSecs = %IDLE_TIMEOUT_SECS%; </script> - <script src="/loleaflet/%VERSION%/branding.js"></script> <!-- logo onclick handler --> + <!--%BRANDING_JS%--> <!-- logo onclick handler --> <script src="/loleaflet/%VERSION%/bundle.js"></script> <script src="/loleaflet/%VERSION%/toolbar/w2ui.min.js"></script> <script src="/loleaflet/%VERSION%/toolbar/toolbar.js"></script> diff --git a/wsd/FileServer.cpp b/wsd/FileServer.cpp index db02203a2..01a12c86a 100644 --- a/wsd/FileServer.cpp +++ b/wsd/FileServer.cpp @@ -39,12 +39,16 @@ #include <Poco/URI.h> #include "Auth.hpp" -#include "Common.hpp" +#include <Common.hpp> +#include <Crypto.hpp> #include "FileServer.hpp" #include "LOOLWSD.hpp" #include "Log.hpp" #include "Protocol.hpp" +#define BRAND_SUPPORTED "branding" +#define BRAND_UNSUPPORTED "branding-CODE" + using Poco::Net::HTMLForm; using Poco::Net::HTTPBasicCredentials; using Poco::Net::HTTPRequest; @@ -288,11 +292,17 @@ void FileServerRequestHandler::handleRequest(const HTTPRequest& request, Poco::M if (request.getMethod() == HTTPRequest::HTTP_GET) { if (endPoint == "admin.html" || - endPoint == "admin-bundle.js" || - endPoint == "admin-localizations.js" || endPoint == "adminSettings.html" || + endPoint == "adminHistory.html" || endPoint == "adminAnalytics.html") { + preprocessAdminFile(request, socket); + return; + } + + if (endPoint == "admin-bundle.js" || + endPoint == "admin-localizations.js") + { noCache = true; if (!LOOLWSD::AdminEnabled) @@ -542,6 +552,8 @@ std::string FileServerRequestHandler::getRequestPathname(const HTTPRequest& requ void FileServerRequestHandler::preprocessFile(const HTTPRequest& request, Poco::MemoryInputStream& message, const std::shared_ptr<StreamSocket>& socket) { + static const std::string linkCSS = "<link rel=\"stylesheet\" href=\"/loleaflet/" LOOLWSD_VERSION_HASH "/%s.css\">"; + static const std::string scriptJS = "<script src=\"/loleaflet/" LOOLWSD_VERSION_HASH "/%s.js\"></script>"; const auto host = ((LOOLWSD::isSSLEnabled() || LOOLWSD::isSSLTermination()) ? "wss://" : "ws://") + (LOOLWSD::ServerName.empty() ? request.getHost() : LOOLWSD::ServerName); const auto params = Poco::URI(request.getURI()).getQueryParameters(); @@ -590,7 +602,26 @@ void FileServerRequestHandler::preprocessFile(const HTTPRequest& request, Poco:: Poco::replaceInPlace(preprocess, std::string("%HOST%"), host); Poco::replaceInPlace(preprocess, std::string("%VERSION%"), std::string(LOOLWSD_VERSION_HASH)); + std::string brandCSS(Poco::format(linkCSS, std::string(BRAND_UNSUPPORTED))); + std::string brandJS(Poco::format(scriptJS, std::string(BRAND_UNSUPPORTED))); + const auto& config = Application::instance().config(); +#if ENABLE_SUPPORT_KEY + const std::string keyString = config.getString("support_key", ""); + SupportKey key(keyString); + if (key.verify() && key.validDaysRemaining() > 0) + { + brandCSS = Poco::format(linkCSS, std::string(BRAND_SUPPORTED)); + brandJS = Poco::format(scriptJS, std::string(BRAND_SUPPORTED)); + } +#elif ENABLE_DEBUG + brandCSS = ""; + brandJS = ""; +#endif + + Poco::replaceInPlace(preprocess, std::string("<!--%BRANDING_CSS%-->"), brandCSS); + Poco::replaceInPlace(preprocess, std::string("<!--%BRANDING_JS%-->"), brandJS); + const auto loleafletLogging = config.getString("loleaflet_logging", "false"); Poco::replaceInPlace(preprocess, std::string("%LOLEAFLET_LOGGING%"), loleafletLogging); const auto outOfFocusTimeoutSecs= config.getString("per_view.out_of_focus_timeout_secs", "60"); @@ -734,4 +765,53 @@ void FileServerRequestHandler::preprocessFile(const HTTPRequest& request, Poco:: LOG_DBG("Sent file: " << relPath << ": " << preprocess); } +void FileServerRequestHandler::preprocessAdminFile(const HTTPRequest& request,const std::shared_ptr<StreamSocket>& socket) +{ + Poco::Net::HTTPResponse response; + static const std::string scriptJS("<script src=\"/loleaflet/dist/%s.js\"></script>"); + static const std::string footerPage("<div class=\"footer navbar-fixed-bottom text-info text-center\"><strong>Key:</strong> %s <strong>Expiry Date:</strong> %s</div>"); + + if (!FileServerRequestHandler::isAdminLoggedIn(request, response)) + throw Poco::Net::NotAuthenticatedException("Invalid admin login"); + + const std::string relPath = getRequestPathname(request); + LOG_DBG("Preprocessing file: " << relPath); + std::string adminFile = *getUncompressedFile(relPath); + std::string brandJS(Poco::format(scriptJS, std::string(BRAND_UNSUPPORTED))); + std::string brandFooter; + +#if ENABLE_SUPPORT_KEY + const auto& config = Application::instance().config(); + const std::string keyString = config.getString("support_key", ""); + SupportKey key(keyString); + + if (key.verify() && key.validDaysRemaining() > 0) + { + brandJS = Poco::format(scriptJS, std::string(BRAND_SUPPORTED)); + brandFooter = Poco::format(footerPage, key.data(), Poco::DateTimeFormatter::format(key.expiry(), Poco::DateTimeFormat::RFC822_FORMAT)); + } +#elif ENABLE_DEBUG + brandJS = ""; +#endif + + Poco::replaceInPlace(adminFile, std::string("<!--%BRANDING_JS%-->"), brandJS); + Poco::replaceInPlace(adminFile, std::string("<!--%FOOTER%-->"), brandFooter); + + // Ask UAs to block if they detect any XSS attempt + response.add("X-XSS-Protection", "1; mode=block"); + // No referrer-policy + response.add("Referrer-Policy", "no-referrer"); + response.add("X-Content-Type-Options", "nosniff"); + response.set("User-Agent", HTTP_AGENT_STRING); + response.set("Date", Poco::DateTimeFormatter::format(Poco::Timestamp(), Poco::DateTimeFormat::HTTP_FORMAT)); + + response.setContentType("text/html"); + response.setChunkedTransferEncoding(false); + + std::ostringstream oss; + response.write(oss); + oss << adminFile; + socket->send(oss.str()); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/wsd/FileServer.hpp b/wsd/FileServer.hpp index c3ff59b7b..8bcc662c7 100644 --- a/wsd/FileServer.hpp +++ b/wsd/FileServer.hpp @@ -21,7 +21,7 @@ class FileServerRequestHandler static std::string getRequestPathname(const Poco::Net::HTTPRequest& request); static void preprocessFile(const Poco::Net::HTTPRequest& request, Poco::MemoryInputStream& message, const std::shared_ptr<StreamSocket>& socket); - + static void preprocessAdminFile(const Poco::Net::HTTPRequest& request, const std::shared_ptr<StreamSocket>& socket); public: /// Evaluate if the cookie exists, and if not, ask for the credentials. static bool isAdminLoggedIn(const Poco::Net::HTTPRequest& request, Poco::Net::HTTPResponse& response); _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
