[Libreoffice-commits] online.git: 44 commits - bundled/include common/JsonUtil.hpp common/Log.cpp common/Log.hpp common/Protocol.hpp common/Seccomp.cpp common/Seccomp.hpp common/Session.cpp common/Session.hpp common/Util.cpp common/Util.hpp configure.ac kit/ChildSession.cpp kit/ChildSession.hpp kit/ForKit.cpp kit/Kit.cpp kit/KitHelper.hpp kit/Kit.hpp loolwsd.xml.in net/Socket.cpp net/Socket.hpp test/WhiteBoxTests.cpp tools/WebSocketDump.cpp wsd/AdminModel.cpp wsd/ClientSession.cpp wsd/DocumentBroker.cpp wsd/DocumentBroker.hpp wsd/LOOLWSD.cpp wsd/LOOLWSD.hpp wsd/Storage.cpp wsd/Storage.hpp wsd/TileCache.cpp
Libreoffice Gerrit user
logerrit at kemper.freedesktop.org
Wed Oct 17 00:13:20 UTC 2018
bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h | 1
common/JsonUtil.hpp | 4
common/Log.cpp | 43 +--
common/Log.hpp | 153 +++++++++++-
common/Protocol.hpp | 42 ---
common/Seccomp.cpp | 5
common/Seccomp.hpp | 3
common/Session.cpp | 73 +++---
common/Session.hpp | 16 +
common/Util.cpp | 121 +++++++++-
common/Util.hpp | 105 ++++++++
configure.ac | 34 ++
kit/ChildSession.cpp | 119 ++++++----
kit/ChildSession.hpp | 8
kit/ForKit.cpp | 12 -
kit/Kit.cpp | 155 +++++++++----
kit/Kit.hpp | 6
kit/KitHelper.hpp | 2
loolwsd.xml.in | 6
net/Socket.cpp | 21 +
net/Socket.hpp | 22 +
test/WhiteBoxTests.cpp | 186 +++++++++++++++
tools/WebSocketDump.cpp | 2
wsd/AdminModel.cpp | 5
wsd/ClientSession.cpp | 18 -
wsd/DocumentBroker.cpp | 90 ++++---
wsd/DocumentBroker.hpp | 4
wsd/LOOLWSD.cpp | 226 ++++++++++++-------
wsd/LOOLWSD.hpp | 15 +
wsd/Storage.cpp | 224 +++++++++++++-----
wsd/Storage.hpp | 24 +-
wsd/TileCache.cpp | 10
32 files changed, 1336 insertions(+), 419 deletions(-)
New commits:
commit df08d6688fa076c7f6a981606790fb6ac5d9bff5
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Thu Aug 23 21:38:01 2018 -0400
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: disable anonymization when allow_logging_pii=true
Anonymizing is useless with trace anyway, since no
trace log entry anonymizes, it's more useful to
disable anonymization to help troubleshoot (which is
the reason for enabling tracing in the first place).
Change-Id: I437207e7a798c2288a5d5eb33446cb16491bfbf6
Reviewed-on: https://gerrit.libreoffice.org/59534
Reviewed-by: Andras Timar <andras.timar at collabora.com>
Tested-by: Andras Timar <andras.timar at collabora.com>
(cherry picked from commit a2809fd27277fd01d0dafdc0c4f0435fdf85db36)
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 37560a424..37ebfe4a8 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -897,16 +897,12 @@ void LOOLWSD::initialize(Application& self)
#else
AnonymizeUsernames = getConfigValue<bool>(conf, "logging.anonymize.usernames", false);
#endif
- if (AnonymizeUsernames)
- setenv("LOOL_ANONYMIZE_USERNAMES", AnonymizeUsernames ? "1" : "0", true);
#if LOOLWSD_ANONYMIZE_FILENAMES
AnonymizeFilenames = true;
#else
AnonymizeFilenames = getConfigValue<bool>(conf, "logging.anonymize.filenames", false);
#endif
- if (AnonymizeFilenames)
- setenv("LOOL_ANONYMIZE_FILENAMES", AnonymizeFilenames ? "1" : "0", true);
if ((AnonymizeFilenames || AnonymizeUsernames) && LogLevel == "trace")
{
@@ -914,6 +910,10 @@ void LOOLWSD::initialize(Application& self)
{
LOG_WRN("Enabling trace logging while anonymization is enabled due to logging.anonymize.allow_logging_pii setting. "
"This will leak personally identifiable information!");
+
+ // Disable anonymization as it's useless now.
+ AnonymizeFilenames = false;
+ AnonymizeUsernames = false;
}
else
{
@@ -930,6 +930,12 @@ void LOOLWSD::initialize(Application& self)
}
}
+ if (AnonymizeFilenames)
+ setenv("LOOL_ANONYMIZE_FILENAMES", "1", true);
+
+ if (AnonymizeUsernames)
+ setenv("LOOL_ANONYMIZE_USERNAMES", "1", true);
+
{
std::string proto = getConfigValue<std::string>(conf, "net.proto", "");
if (!Poco::icompare(proto, "ipv4"))
commit 3eb1051777e83072a3f4513bda39a1d825c555fa
Author: Jan Holesovsky <kendy at collabora.com>
AuthorDate: Tue Jul 17 20:22:06 2018 +0200
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: Don't try to anonymize the /contents at the end.
Change-Id: Ib3737f4afc6d708b7d06acb36f4044df9f5fbe84
Reviewed-on: https://gerrit.libreoffice.org/57586
Reviewed-by: Aron Budea <aron.budea at collabora.com>
Tested-by: Aron Budea <aron.budea at collabora.com>
(cherry picked from commit 9bab03070140227f850112716277c82f2fc41424)
(cherry picked from commit d2f7adca4a8d528e1cac33d877de906d28d34d65)
diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp
index 9bded69cd..3ceaf673e 100644
--- a/wsd/Storage.cpp
+++ b/wsd/Storage.cpp
@@ -609,7 +609,10 @@ std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth)
Poco::URI uriObject(_uri);
uriObject.setPath(uriObject.getPath() + "/contents");
auth.authorizeURI(uriObject);
- const std::string uriAnonym = LOOLWSD::anonymizeUrl(uriObject.toString());
+
+ Poco::URI uriObjectAnonym(_uri);
+ uriObjectAnonym.setPath(LOOLWSD::anonymizeUrl(uriObjectAnonym.getPath()) + "/contents");
+ const std::string uriAnonym = uriObjectAnonym.toString();
LOG_DBG("Wopi requesting: " << uriAnonym);
commit 9a8e4fc0e89c6b31ce020cfdf7aa54ec306ddc71
Author: Jan Holesovsky <kendy at collabora.com>
AuthorDate: Wed Jul 18 16:18:03 2018 +0200
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: safer string splitting
Reviewed-on: https://gerrit.libreoffice.org/57644
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
(cherry picked from commit 17d1fdda7a0c29df12c43b956418c83b59bfe0da)
Change-Id: I88b82a3754c4f5e280f00be8e27614c3fe49eff8
diff --git a/common/Util.hpp b/common/Util.hpp
index 57827b8e1..d3a5ba115 100644
--- a/common/Util.hpp
+++ b/common/Util.hpp
@@ -597,7 +597,13 @@ namespace Util
std::pair<std::string, std::string> split(const char* s, const int length, const char delimeter = ' ', bool removeDelim = true)
{
const size_t size = getDelimiterPosition(s, length, delimeter);
- return std::make_pair(std::string(s, size), std::string(s+size+removeDelim));
+
+ std::string after;
+ int after_pos = size + (removeDelim? 1: 0);
+ if (after_pos < length)
+ after = std::string(s + after_pos, length - after_pos);
+
+ return std::make_pair(std::string(s, size), after);
}
/// Split a string in two at the delimeter, removing it.
@@ -611,8 +617,14 @@ namespace Util
inline
std::pair<std::string, std::string> splitLast(const char* s, const int length, const char delimeter = ' ', bool removeDelim = true)
{
- const auto size = getLastDelimiterPosition(s, length, delimeter);
- return std::make_pair(std::string(s, size), std::string(s+size+removeDelim));
+ const size_t size = getLastDelimiterPosition(s, length, delimeter);
+
+ std::string after;
+ int after_pos = size + (removeDelim? 1: 0);
+ if (after_pos < length)
+ after = std::string(s + after_pos, length - after_pos);
+
+ return std::make_pair(std::string(s, size), after);
}
/// Split a string in two at the delimeter, removing it.
commit 0fa7ad50d9088dc95f94e83f579ce55316d7372e
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Aug 1 22:25:38 2018 -0400
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: warn when allow_logging_pii forces trace with anonymization
Also move anonymization initialization after logging is initialized.
Change-Id: I5c3753f0b11ae9c3376235e22af204eb3a57f5c8
(cherry picked from commit 02076bdb9128ffe7c26d8bcf420b659ec1d68280)
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 86da4b9c2..37560a424 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -853,39 +853,6 @@ void LOOLWSD::initialize(Application& self)
setenv("LOOL_LOGCOLOR", "1", true);
}
- // Get anonymization settings.
-#if LOOLWSD_ANONYMIZE_USERNAMES
- AnonymizeUsernames = true;
-#else
- AnonymizeUsernames = getConfigValue<bool>(conf, "logging.anonymize.usernames", false);
-#endif
- if (AnonymizeUsernames)
- setenv("LOOL_ANONYMIZE_USERNAMES", AnonymizeUsernames ? "1" : "0", true);
-
-#if LOOLWSD_ANONYMIZE_FILENAMES
- AnonymizeFilenames = true;
-#else
- AnonymizeFilenames = getConfigValue<bool>(conf, "logging.anonymize.filenames", false);
-#endif
- if (AnonymizeFilenames)
- setenv("LOOL_ANONYMIZE_FILENAMES", AnonymizeFilenames ? "1" : "0", true);
-
- if (AnonymizeFilenames || AnonymizeUsernames)
- {
- if (LogLevel == "trace" && !getConfigValue<bool>(conf, "logging.anonymize.allow_logging_pii", false))
- {
- const char failure[] = "Anonymization and trace-level logging are incompatible. "
- "Please reduce logging level to debug or lower in loolwsd.xml to prevent leaking sensitive user data.";
- LOG_FTL(failure);
- std::cerr << '\n' << failure << std::endl;
-#if ENABLE_DEBUG
- std::cerr << "\nIf you have used 'make run', edit loolwsd.xml and make sure you have removed '--o:logging.level=trace' from the command line in Makefile.am.\n" << std::endl;
-#endif
- Log::shutdown();
- _exit(Application::EXIT_SOFTWARE);
- }
- }
-
const auto logToFile = getConfigValue<bool>(conf, "logging.file[@enable]", false);
std::map<std::string, std::string> logProperties;
for (std::size_t i = 0; ; ++i)
@@ -924,6 +891,45 @@ void LOOLWSD::initialize(Application& self)
LOG_INF("Setting log-level to [trace] and delaying setting to configured [" << LogLevel << "] until after WSD initialization.");
}
+ // Get anonymization settings.
+#if LOOLWSD_ANONYMIZE_USERNAMES
+ AnonymizeUsernames = true;
+#else
+ AnonymizeUsernames = getConfigValue<bool>(conf, "logging.anonymize.usernames", false);
+#endif
+ if (AnonymizeUsernames)
+ setenv("LOOL_ANONYMIZE_USERNAMES", AnonymizeUsernames ? "1" : "0", true);
+
+#if LOOLWSD_ANONYMIZE_FILENAMES
+ AnonymizeFilenames = true;
+#else
+ AnonymizeFilenames = getConfigValue<bool>(conf, "logging.anonymize.filenames", false);
+#endif
+ if (AnonymizeFilenames)
+ setenv("LOOL_ANONYMIZE_FILENAMES", AnonymizeFilenames ? "1" : "0", true);
+
+ if ((AnonymizeFilenames || AnonymizeUsernames) && LogLevel == "trace")
+ {
+ if (getConfigValue<bool>(conf, "logging.anonymize.allow_logging_pii", false))
+ {
+ LOG_WRN("Enabling trace logging while anonymization is enabled due to logging.anonymize.allow_logging_pii setting. "
+ "This will leak personally identifiable information!");
+ }
+ else
+ {
+ static const char failure[] = "Anonymization and trace-level logging are incompatible. "
+ "Please reduce logging level to debug or lower in loolwsd.xml to prevent leaking sensitive user data.";
+ LOG_FTL(failure);
+ std::cerr << '\n' << failure << std::endl;
+#if ENABLE_DEBUG
+ std::cerr << "\nIf you have used 'make run', edit loolwsd.xml and make sure you have removed "
+ "'--o:logging.level=trace' from the command line in Makefile.am.\n" << std::endl;
+#endif
+ Log::shutdown();
+ _exit(Application::EXIT_SOFTWARE);
+ }
+ }
+
{
std::string proto = getConfigValue<std::string>(conf, "net.proto", "");
if (!Poco::icompare(proto, "ipv4"))
commit a80c5e70c4866e4dc799a5f16ac10d23ef66adae
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Aug 1 22:04:33 2018 -0400
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: minor cleanup of CheckFileInfo logging
Change-Id: I45a7d281a640cbadfd42f1411f53946ae0142653
(cherry picked from commit 9a35fcd269877f3b42bb34c0d1b3bd6e98450d7d)
diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp
index 2b8379cab..9bded69cd 100644
--- a/wsd/Storage.cpp
+++ b/wsd/Storage.cpp
@@ -498,6 +498,11 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
Poco::JSON::Object::Ptr object;
if (JsonUtil::parseJSON(wopiResponse, object))
{
+ if (LOOLWSD::AnonymizeFilenames || LOOLWSD::AnonymizeUsernames)
+ LOG_DBG("WOPI::CheckFileInfo (" << callDuration.count() * 1000. << " ms): anonymizing...");
+ else
+ LOG_DBG("WOPI::CheckFileInfo (" << callDuration.count() * 1000. << " ms): " << wopiResponse);
+
JsonUtil::findJSONValue(object, "BaseFileName", filename);
JsonUtil::findJSONValue(object, "OwnerId", ownerId);
JsonUtil::findJSONValue(object, "UserId", userId);
@@ -545,10 +550,9 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
object->remove("UserId");
object->remove("UserFriendlyName");
}
- }
- // Log either an original or anonymized version, depending on anonymization flags.
- LOG_DBG("WOPI::CheckFileInfo (" << callDuration.count() * 1000. << " ms): " << wopiResponse);
+ LOG_DBG("WOPI::CheckFileInfo (" << callDuration.count() * 1000. << " ms): " << wopiResponse);
+ }
JsonUtil::findJSONValue(object, "Size", size);
JsonUtil::findJSONValue(object, "UserExtraInfo", userExtraInfo);
@@ -576,10 +580,12 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
else
{
if (LOOLWSD::AnonymizeFilenames || LOOLWSD::AnonymizeUsernames)
- LOG_ERR("WOPI::CheckFileInfo failed or no valid JSON payload returned. Access denied.");
- else
- LOG_ERR("WOPI::CheckFileInfo failed or no valid JSON payload returned. Access denied. "
- "Original response: [" << wopiResponse << "].");
+ wopiResponse = "obfuscated";
+
+ LOG_ERR("WOPI::CheckFileInfo (" << callDuration.count() * 1000. <<
+ " ms) failed or no valid JSON payload returned. Access denied. "
+ "Original response: [" << wopiResponse << "].");
+
throw UnauthorizedRequestException("Access denied. WOPI::CheckFileInfo failed on: " + uriAnonym);
}
commit 9bfe8b70e2d8f728d2d5314f419568d96fe83a9f
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Aug 1 22:03:53 2018 -0400
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: don't warn on missing json
Change-Id: I28086152fbf9fc82ddead1a2feb80f21ffdcd208
(cherry picked from commit 7b48be5a9dde4fcec01b8804559ffa4f9c19d53c)
diff --git a/common/JsonUtil.hpp b/common/JsonUtil.hpp
index 057344ec5..c7fa20ac2 100644
--- a/common/JsonUtil.hpp
+++ b/common/JsonUtil.hpp
@@ -106,7 +106,7 @@ bool findJSONValue(Poco::JSON::Object::Ptr &object, const std::string& key, T& v
// Check each property name against given key
// and warn for mis-spells with tolerance of 2.
- for (const std::string& userInput: propertyNames)
+ for (const std::string& userInput : propertyNames)
{
if (key != userInput)
{
@@ -134,7 +134,7 @@ bool findJSONValue(Poco::JSON::Object::Ptr &object, const std::string& key, T& v
return true;
}
- LOG_WRN("Missing JSON property [" << key << "]");
+ LOG_INF("Missing JSON property [" << key << "] will default to [" << value << "].");
return false;
}
diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp
index 3e038bbff..2b8379cab 100644
--- a/wsd/Storage.cpp
+++ b/wsd/Storage.cpp
@@ -397,10 +397,13 @@ Poco::Timestamp iso8601ToTimestamp(const std::string& iso8601Time, const std::st
Poco::Timestamp timestamp = Poco::Timestamp::fromEpochTime(0);
try
{
- int timeZoneDifferential;
- Poco::DateTime dateTime;
- Poco::DateTimeParser::parse(Poco::DateTimeFormat::ISO8601_FRAC_FORMAT, iso8601Time, dateTime, timeZoneDifferential);
- timestamp = dateTime.timestamp();
+ if (!iso8601Time.empty())
+ {
+ int timeZoneDifferential;
+ Poco::DateTime dateTime;
+ Poco::DateTimeParser::parse(Poco::DateTimeFormat::ISO8601_FRAC_FORMAT, iso8601Time, dateTime, timeZoneDifferential);
+ timestamp = dateTime.timestamp();
+ }
}
catch (const Poco::SyntaxException& exc)
{
commit 4e186aca18c0db027a9d70dbd789edb72960afc8
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Sat Jul 21 15:58:35 2018 -0400
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: fixed remaining anonymization issues
(cherry picked from commit b7f5809a792e2a0b816d3cfd96511cdd93582d15)
Change-Id: I756ccd4b810fdc4dd62a83c1704c59c6a947e615
diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index 7341a7fcd..fe2fc458c 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -657,7 +657,7 @@ bool ChildSession::downloadAs(const char* /*buffer*/, int /*length*/, const std:
}
// Obfuscate the new name.
- Util::mapAnonymized(name, _docManager.getObfuscatedFileId());
+ Util::mapAnonymized(Util::getFilenameFromURL(name), _docManager.getObfuscatedFileId());
getTokenString(tokens[3], "format", format);
@@ -979,8 +979,8 @@ bool ChildSession::unoCommand(const char* /*buffer*/, int /*length*/, const std:
else
{
getLOKitDocument()->postUnoCommand(tokens[1].c_str(),
- Poco::cat(std::string(" "), tokens.begin() + 2, tokens.end()).c_str(),
- bNotify);
+ Poco::cat(std::string(" "), tokens.begin() + 2, tokens.end()).c_str(),
+ bNotify);
}
return true;
@@ -1149,8 +1149,6 @@ bool ChildSession::saveAs(const char* /*buffer*/, int /*length*/, const std::vec
return false;
}
- const std::string urlAnonym = anonymizeUrl(url);
-
// if the url is a 'wopi:///something/blah.odt', then save to a temporary
Poco::URI wopiURL(url);
if (wopiURL.getScheme() == "wopi")
@@ -1184,17 +1182,20 @@ bool ChildSession::saveAs(const char* /*buffer*/, int /*length*/, const std::vec
{
std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
- getLOKitDocument()->setView(_viewId);
-
if (filterOptions.empty() && format == "html")
{
// Opt-in to avoid linked images, those would not leave the chroot.
filterOptions = "EmbedImages";
}
- LOG_DBG("Calling LOK's saveAs with: url='" << urlAnonym << "', format='" <<
- (format.empty() ? "(nullptr)" : format.c_str()) << "', filterOptions='" <<
- (filterOptions.empty() ? "(nullptr)" : filterOptions.c_str()) << "'.");
+ // We don't have the FileId at this point, just a new filename to save-as.
+ // So here the filename will be obfuscated with some hashing, which later will
+ // get a proper FileId that we will use going forward.
+ LOG_DBG("Calling LOK's saveAs with: '" << anonymizeUrl(wopiFilename) << "', '" <<
+ (format.size() == 0 ? "(nullptr)" : format.c_str()) << "', '" <<
+ (filterOptions.size() == 0 ? "(nullptr)" : filterOptions.c_str()) << "'.");
+
+ getLOKitDocument()->setView(_viewId);
success = getLOKitDocument()->saveAs(url.c_str(),
format.empty() ? nullptr : format.c_str(),
@@ -1336,30 +1337,28 @@ void ChildSession::rememberEventsForInactiveUser(const int type, const std::stri
}
}
-void ChildSession::updateSpeed()
-{
+void ChildSession::updateSpeed() {
+
std::chrono::steady_clock::time_point now(std::chrono::steady_clock::now());
- while (_cursorInvalidatedEvent.size() != 0 &&
- std::chrono::duration_cast<std::chrono::milliseconds>(now - _cursorInvalidatedEvent.front()).count() > _eventStorageIntervalMs)
+ while(_cursorInvalidatedEvent.size() != 0 &&
+ std::chrono::duration_cast<std::chrono::milliseconds>(now - _cursorInvalidatedEvent.front()).count() > _eventStorageIntervalMs)
{
_cursorInvalidatedEvent.pop();
}
-
_cursorInvalidatedEvent.push(now);
_docManager.updateEditorSpeeds(_viewId, _cursorInvalidatedEvent.size());
}
-int ChildSession::getSpeed()
-{
+int ChildSession::getSpeed() {
+
std::chrono::steady_clock::time_point now(std::chrono::steady_clock::now());
- while (_cursorInvalidatedEvent.size() > 0 &&
- std::chrono::duration_cast<std::chrono::milliseconds>(now - _cursorInvalidatedEvent.front()).count() > _eventStorageIntervalMs)
+ while(_cursorInvalidatedEvent.size() > 0 &&
+ std::chrono::duration_cast<std::chrono::milliseconds>(now - _cursorInvalidatedEvent.front()).count() > _eventStorageIntervalMs)
{
_cursorInvalidatedEvent.pop();
}
-
return _cursorInvalidatedEvent.size();
}
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 3e23314c4..015deb26e 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -686,7 +686,7 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
std::string localPathEncoded;
Poco::URI::encode(localPath, "#", localPathEncoded);
_uriJailed = Poco::URI(Poco::URI("file://"), localPathEncoded).toString();
- _uriJailedAnonym = Poco::URI(Poco::URI("file://"), LOOLWSD::anonymizeUrl(localPathEncoded)).toString();
+ _uriJailedAnonym = Poco::URI(Poco::URI("file://"), LOOLWSD::anonymizeUrl(localPath)).toString();
_filename = fileInfo._filename;
@@ -789,6 +789,14 @@ bool DocumentBroker::saveToStorageInternal(const std::string& sessionId,
const Authorization auth = it->second->getAuthorization();
const std::string uri = isSaveAs ? saveAsPath : it->second->getPublicUri().toString();
+
+ // Map the FileId from the docKey to the new filename to anonymize the new filename as the FileId.
+ const std::string newFilename = Util::getFilenameFromURL(uri);
+ const std::string fileId = Util::getFilenameFromURL(_docKey);
+ if (LOOLWSD::AnonymizeFilenames)
+ LOG_DBG("New filename [" << LOOLWSD::anonymizeUrl(newFilename) << "] will be known by its fileId [" << fileId << "]");
+
+ Util::mapAnonymized(newFilename, fileId);
const std::string uriAnonym = LOOLWSD::anonymizeUrl(uri);
// If the file timestamp hasn't changed, skip saving.
diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp
index bb3b03c1e..3e038bbff 100644
--- a/wsd/Storage.cpp
+++ b/wsd/Storage.cpp
@@ -768,16 +768,21 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization&
{
// Anonymize the filename
std::string url;
- JsonUtil::findJSONValue(object, "Url", url);
- std::string decodedUrl;
- Poco::URI::decode(url, decodedUrl);
- const std::string obfuscatedFileId = Util::getFilenameFromURL(decodedUrl);
-
std::string filename;
- JsonUtil::findJSONValue(object, "Name", filename);
- const std::string filenameOnly = Util::getFilenameFromURL(filename);
- Util::mapAnonymized(filenameOnly, obfuscatedFileId);
- object->set("Name", LOOLWSD::anonymizeUrl(filename));
+ if (JsonUtil::findJSONValue(object, "Url", url) &&
+ JsonUtil::findJSONValue(object, "Name", filename))
+ {
+ // Get the FileId form the URL, which we use as the anonymized filename.
+ std::string decodedUrl;
+ Poco::URI::decode(url, decodedUrl);
+ const std::string obfuscatedFileId = Util::getFilenameFromURL(decodedUrl);
+ Util::mapAnonymized(obfuscatedFileId, obfuscatedFileId); // Identity, to avoid re-anonymizing.
+
+ const std::string filenameOnly = Util::getFilenameFromURL(filename);
+ Util::mapAnonymized(filenameOnly, obfuscatedFileId);
+ object->set("Name", LOOLWSD::anonymizeUrl(filename));
+ }
+
// Stringify to log.
std::ostringstream ossResponse;
object->stringify(ossResponse);
commit 5d6a228a8b7685de4ba03bd2abf036076191b4ec
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Thu Jul 19 01:22:07 2018 -0400
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: don't anonymize 'contents' URI
Reviewed-on: https://gerrit.libreoffice.org/57707
Reviewed-by: Jan Holesovsky <kendy at collabora.com>
Tested-by: Jan Holesovsky <kendy at collabora.com>
(cherry picked from commit 7cadf9da49c2b804f30f1e8c2d2998c768b9d365)
Change-Id: Ia66729453a1f7db6105a0332de0f8bad3835f3f5
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 45094fa09..86da4b9c2 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -3035,6 +3035,9 @@ int LOOLWSD::innerMain()
#endif
+ // URI with /contents are public and we don't need to anonymize them.
+ Util::mapAnonymized("contents", "contents");
+
// Start the server.
srv.start(ClientPortNumber);
commit ff6f49c598dee5ffd5977179ba4b0be02a77c6ae
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Jul 18 10:30:22 2018 -0400
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: more string split tests
Change-Id: Idd6e99954b11238eaf64e11e7969d0aee1612557
Reviewed-on: https://gerrit.libreoffice.org/57648
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
(cherry picked from commit f64e0fba92ad80776572255951b2e0d76bc76e73)
diff --git a/test/WhiteBoxTests.cpp b/test/WhiteBoxTests.cpp
index 9f8287e46..30f8327bf 100644
--- a/test/WhiteBoxTests.cpp
+++ b/test/WhiteBoxTests.cpp
@@ -183,6 +183,28 @@ void WhiteBoxTests::testSplitting()
CPPUNIT_ASSERT_EQUAL(std::string("a"), first);
CPPUNIT_ASSERT_EQUAL(std::string(""), second);
+
+ // Split first, remove delim.
+ std::tie(first, second) = Util::split(std::string("a."), '.', true);
+ CPPUNIT_ASSERT_EQUAL(std::string("a"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string(""), second);
+
+ // Split first, keep delim.
+ std::tie(first, second) = Util::split(std::string("a."), '.', false);
+ CPPUNIT_ASSERT_EQUAL(std::string("a"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string("."), second);
+
+ // Split first, remove delim.
+ std::tie(first, second) = Util::splitLast(std::string("a."), '.', true);
+ CPPUNIT_ASSERT_EQUAL(std::string("a"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string(""), second);
+
+ // Split first, keep delim.
+ std::tie(first, second) = Util::splitLast(std::string("a."), '.', false);
+ CPPUNIT_ASSERT_EQUAL(std::string("a"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string("."), second);
+
+
// Split first, remove delim.
std::tie(first, second) = Util::split(std::string("aa.bb"), '.', true);
CPPUNIT_ASSERT_EQUAL(std::string("aa"), first);
commit b6333ada8d8ee31aa97ec1dea31f8905b8a45d1f
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Tue Jul 17 02:01:05 2018 -0400
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: anonymization improvements and unittests
Also support anonymization of downloadas documents
and renaming of documents.
Reviewed-on: https://gerrit.libreoffice.org/57541
Reviewed-by: Jan Holesovsky <kendy at collabora.com>
Tested-by: Jan Holesovsky <kendy at collabora.com>
(cherry picked from commit 78248a542c9ca31bf9ad4cad9b55d78690384395)
Change-Id: I81a80e6290217659987d73f625e5f0fb81cb7ef2
diff --git a/common/Util.cpp b/common/Util.cpp
index 3c8e9d27f..048526a49 100644
--- a/common/Util.cpp
+++ b/common/Util.cpp
@@ -614,6 +614,42 @@ namespace Util
return true;
}
+ /// Split a string in two at the delimeter and give the delimiter to the first.
+ static
+ std::pair<std::string, std::string> splitLast2(const char* s, const int length, const char delimeter = ' ')
+ {
+ if (s != nullptr && length > 0)
+ {
+ const int pos = getLastDelimiterPosition(s, length, delimeter);
+ if (pos < length)
+ return std::make_pair(std::string(s, pos + 1), std::string(s + pos + 1));
+ }
+
+ // Not found; return in first.
+ return std::make_pair(std::string(s, length), std::string());
+ }
+
+ std::tuple<std::string, std::string, std::string, std::string> splitUrl(const std::string& url)
+ {
+ // In case we have a URL that has parameters.
+ std::string base;
+ std::string params;
+ std::tie(base, params) = Util::split(url, '?', false);
+
+ std::string filename;
+ std::tie(base, filename) = Util::splitLast2(base.c_str(), base.size(), '/');
+ if (filename.empty())
+ {
+ // If no '/', then it's only filename.
+ std::swap(base, filename);
+ }
+
+ std::string ext;
+ std::tie(filename, ext) = Util::splitLast(filename, '.', false);
+
+ return std::make_tuple(base, filename, ext, params);
+ }
+
static std::map<std::string, std::string> AnonymizedStrings;
static std::atomic<unsigned> AnonymizationSalt(0);
static std::mutex AnonymizedMutex;
@@ -656,45 +692,25 @@ namespace Util
return res;
}
- static std::string anonymizeFilename(const std::string& filename)
+ std::string getFilenameFromURL(const std::string& url)
{
- // Preserve the extension.
- std::string basename;
+ std::string base;
+ std::string filename;
std::string ext;
- const std::size_t mid = filename.find_last_of('.');
- if (mid != std::string::npos)
- {
- basename = filename.substr(0, mid);
- ext = filename.substr(mid);
- }
- else
- basename = filename;
-
- return Util::anonymize(basename) + ext;
- }
-
- std::string getFilenameFromPath(const std::string& path)
- {
- const std::size_t mid = path.find_last_of('/');
- if (mid != std::string::npos)
- return path.substr(mid + 1);
-
- // No path, treat as filename only.
- return path;
+ std::string params;
+ std::tie(base, filename, ext, params) = Util::splitUrl(url);
+ return filename;
}
std::string anonymizeUrl(const std::string& url)
{
- const std::size_t mid = url.find_last_of('/');
- if (mid != std::string::npos)
- {
- const std::string path = url.substr(0, mid + 1);
- const std::string filename = url.substr(mid + 1);
- return path + Util::anonymizeFilename(filename);
- }
+ std::string base;
+ std::string filename;
+ std::string ext;
+ std::string params;
+ std::tie(base, filename, ext, params) = Util::splitUrl(url);
- // No path, treat as filename only.
- return Util::anonymizeFilename(url);
+ return base + Util::anonymize(filename) + ext + params;
}
}
diff --git a/common/Util.hpp b/common/Util.hpp
index c252d253e..57827b8e1 100644
--- a/common/Util.hpp
+++ b/common/Util.hpp
@@ -332,6 +332,18 @@ namespace Util
return false;
}
+ inline size_t getLastDelimiterPosition(const char* message, const int length, const char delim)
+ {
+ if (message && length > 0)
+ {
+ const char *founddelim = static_cast<const char *>(memrchr(message, delim, length));
+ const auto size = (founddelim == nullptr ? length : founddelim - message);
+ return size;
+ }
+
+ return 0;
+ }
+
/// Return the symbolic name for an errno value, or in decimal if not handled here.
inline std::string symbolicErrno(int e)
{
@@ -582,19 +594,38 @@ namespace Util
/// Split a string in two at the delimeter, removing it.
inline
- std::pair<std::string, std::string> split(const char* s, const int length, const char delimeter = ' ')
+ std::pair<std::string, std::string> split(const char* s, const int length, const char delimeter = ' ', bool removeDelim = true)
{
const size_t size = getDelimiterPosition(s, length, delimeter);
- return std::make_pair(std::string(s, size), std::string(s+size+1));
+ return std::make_pair(std::string(s, size), std::string(s+size+removeDelim));
}
/// Split a string in two at the delimeter, removing it.
inline
- std::pair<std::string, std::string> split(const std::string& s, const char delimeter = ' ')
+ std::pair<std::string, std::string> split(const std::string& s, const char delimeter = ' ', bool removeDelim = true)
{
- return split(s.c_str(), s.size(), delimeter);
+ return split(s.c_str(), s.size(), delimeter, removeDelim);
}
+ /// Split a string in two at the delimeter.
+ inline
+ std::pair<std::string, std::string> splitLast(const char* s, const int length, const char delimeter = ' ', bool removeDelim = true)
+ {
+ const auto size = getLastDelimiterPosition(s, length, delimeter);
+ return std::make_pair(std::string(s, size), std::string(s+size+removeDelim));
+ }
+
+ /// Split a string in two at the delimeter, removing it.
+ inline
+ std::pair<std::string, std::string> splitLast(const std::string& s, const char delimeter = ' ', bool removeDelim = true)
+ {
+ return splitLast(s.c_str(), s.size(), delimeter, removeDelim);
+ }
+
+ /// Splits a URL into path (with protocol), filename, extension, parameters.
+ /// All components are optional, depending on what the URL represents (can be a unix path).
+ std::tuple<std::string, std::string, std::string, std::string> splitUrl(const std::string& url);
+
/// Check for the URI scheme validity.
/// For now just a basic sanity check, can be extended if necessary.
bool isValidURIScheme(const std::string& scheme);
@@ -614,8 +645,8 @@ namespace Util
/// Anonymize the basename of filenames only, preserving the path and extension.
std::string anonymizeUrl(const std::string& url);
- /// Extract and return the filename given a path (i.e. the token after last '/').
- std::string getFilenameFromPath(const std::string& path);
+ /// Extract and return the filename given a url or path.
+ std::string getFilenameFromURL(const std::string& url);
/// Given one or more patterns to allow, and one or more to deny,
/// the match member will return true if, and only if, the subject
diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index af38fd790..7341a7fcd 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -656,6 +656,9 @@ bool ChildSession::downloadAs(const char* /*buffer*/, int /*length*/, const std:
return false;
}
+ // Obfuscate the new name.
+ Util::mapAnonymized(name, _docManager.getObfuscatedFileId());
+
getTokenString(tokens[3], "format", format);
if (getTokenString(tokens[4], "options", filterOptions))
diff --git a/kit/ChildSession.hpp b/kit/ChildSession.hpp
index b275156fe..b23edd8c4 100644
--- a/kit/ChildSession.hpp
+++ b/kit/ChildSession.hpp
@@ -69,6 +69,8 @@ public:
/// setting a view followed by a tile render, etc.
virtual std::mutex& getDocumentMutex() = 0;
+ virtual std::string getObfuscatedFileId() = 0;
+
virtual std::shared_ptr<TileQueue>& getTileQueue() = 0;
virtual bool sendFrame(const char* buffer, int length, WSOpCode opCode = WSOpCode::Text) = 0;
diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index abdb0238f..31531afbf 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -116,7 +116,6 @@ static std::shared_ptr<Document> document;
static bool AnonymizeFilenames = false;
static bool AnonymizeUsernames = false;
static std::string ObfuscatedFileId;
-static std::string ObfuscatedUserId;
#endif
#if ENABLE_DEBUG
@@ -789,6 +788,7 @@ public:
_docKey(docKey),
_docId(docId),
_url(url),
+ _obfuscatedFileId(Util::getFilenameFromURL(docKey)),
_tileQueue(std::move(tileQueue)),
_socketPoll(socketPoll),
_websocketHandler(websocketHandler),
@@ -1995,6 +1995,11 @@ private:
return _documentMutex;
}
+ std::string getObfuscatedFileId() override
+ {
+ return _obfuscatedFileId;
+ }
+
private:
std::shared_ptr<lok::Office> _loKit;
const std::string _jailId;
@@ -2003,6 +2008,7 @@ private:
/// Short numerical ID. Unique during the lifetime of WSD.
const std::string _docId;
const std::string _url;
+ const std::string _obfuscatedFileId;
std::string _jailedUrl;
std::string _renderOpts;
@@ -2106,7 +2112,7 @@ protected:
const std::string& sessionId = tokens[1];
const std::string& docKey = tokens[2];
const std::string& docId = tokens[3];
- const std::string fileId = Util::getFilenameFromPath(docKey);
+ const std::string fileId = Util::getFilenameFromURL(docKey);
Util::mapAnonymized(fileId, fileId); // Identity mapping, since fileId is already obfuscated
std::string url;
diff --git a/test/WhiteBoxTests.cpp b/test/WhiteBoxTests.cpp
index a26ccf686..9f8287e46 100644
--- a/test/WhiteBoxTests.cpp
+++ b/test/WhiteBoxTests.cpp
@@ -27,6 +27,7 @@ class WhiteBoxTests : public CPPUNIT_NS::TestFixture
CPPUNIT_TEST_SUITE(WhiteBoxTests);
CPPUNIT_TEST(testLOOLProtocolFunctions);
+ CPPUNIT_TEST(testSplitting);
CPPUNIT_TEST(testMessageAbbreviation);
CPPUNIT_TEST(testTokenizer);
CPPUNIT_TEST(testReplace);
@@ -36,10 +37,12 @@ class WhiteBoxTests : public CPPUNIT_NS::TestFixture
CPPUNIT_TEST(testRectanglesIntersect);
CPPUNIT_TEST(testAuthorization);
CPPUNIT_TEST(testJson);
+ CPPUNIT_TEST(testAnonymization);
CPPUNIT_TEST_SUITE_END();
void testLOOLProtocolFunctions();
+ void testSplitting();
void testMessageAbbreviation();
void testTokenizer();
void testReplace();
@@ -49,6 +52,7 @@ class WhiteBoxTests : public CPPUNIT_NS::TestFixture
void testRectanglesIntersect();
void testAuthorization();
void testJson();
+ void testAnonymization();
};
void WhiteBoxTests::testLOOLProtocolFunctions()
@@ -142,6 +146,115 @@ void WhiteBoxTests::testLOOLProtocolFunctions()
CPPUNIT_ASSERT_EQUAL(std::string(""), Util::trim(s));
}
+void WhiteBoxTests::testSplitting()
+{
+ CPPUNIT_ASSERT_EQUAL(std::string(), Util::getDelimitedInitialSubstring(nullptr, 5, '\n'));
+ CPPUNIT_ASSERT_EQUAL(std::string(), Util::getDelimitedInitialSubstring(nullptr, -1, '\n'));
+ CPPUNIT_ASSERT_EQUAL(std::string(), Util::getDelimitedInitialSubstring("abc", 0, '\n'));
+ CPPUNIT_ASSERT_EQUAL(std::string(), Util::getDelimitedInitialSubstring("abc", -1, '\n'));
+ CPPUNIT_ASSERT_EQUAL(std::string("ab"), Util::getDelimitedInitialSubstring("abc", 2, '\n'));
+
+ std::string first;
+ std::string second;
+
+ std::tie(first, second) = Util::split(std::string(""), '.', true);
+ std::tie(first, second) = Util::split(std::string(""), '.', false);
+
+ std::tie(first, second) = Util::splitLast(std::string(""), '.', true);
+ std::tie(first, second) = Util::splitLast(std::string(""), '.', false);
+
+ // Split first, remove delim.
+ std::tie(first, second) = Util::split(std::string("a"), '.', true);
+ CPPUNIT_ASSERT_EQUAL(std::string("a"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string(""), second);
+
+ // Split first, keep delim.
+ std::tie(first, second) = Util::split(std::string("a"), '.', false);
+ CPPUNIT_ASSERT_EQUAL(std::string("a"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string(""), second);
+
+ // Split first, remove delim.
+ std::tie(first, second) = Util::splitLast(std::string("a"), '.', true);
+ CPPUNIT_ASSERT_EQUAL(std::string("a"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string(""), second);
+
+ // Split first, keep delim.
+ std::tie(first, second) = Util::splitLast(std::string("a"), '.', false);
+ CPPUNIT_ASSERT_EQUAL(std::string("a"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string(""), second);
+
+ // Split first, remove delim.
+ std::tie(first, second) = Util::split(std::string("aa.bb"), '.', true);
+ CPPUNIT_ASSERT_EQUAL(std::string("aa"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string("bb"), second);
+
+ // Split first, keep delim.
+ std::tie(first, second) = Util::split(std::string("aa.bb"), '.', false);
+ CPPUNIT_ASSERT_EQUAL(std::string("aa"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string(".bb"), second);
+
+ CPPUNIT_ASSERT_EQUAL(5UL, Util::getLastDelimiterPosition("aa.bb.cc", 8, '.'));
+
+ // Split last, remove delim.
+ std::tie(first, second) = Util::splitLast(std::string("aa.bb.cc"), '.', true);
+ CPPUNIT_ASSERT_EQUAL(std::string("aa.bb"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string("cc"), second);
+
+ // Split last, keep delim.
+ std::tie(first, second) = Util::splitLast(std::string("aa.bb.cc"), '.', false);
+ CPPUNIT_ASSERT_EQUAL(std::string("aa.bb"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string(".cc"), second);
+
+ // Split last, remove delim.
+ std::tie(first, second) = Util::splitLast(std::string("/owncloud/index.php/apps/richdocuments/wopi/files/13_ocgdpzbkm39u"), '/', true);
+ CPPUNIT_ASSERT_EQUAL(std::string("/owncloud/index.php/apps/richdocuments/wopi/files"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string("13_ocgdpzbkm39u"), second);
+
+ // Split last, keep delim.
+ std::tie(first, second) = Util::splitLast(std::string("/owncloud/index.php/apps/richdocuments/wopi/files/13_ocgdpzbkm39u"), '/', false);
+ CPPUNIT_ASSERT_EQUAL(std::string("/owncloud/index.php/apps/richdocuments/wopi/files"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string("/13_ocgdpzbkm39u"), second);
+
+ std::string third;
+ std::string fourth;
+
+ std::tie(first, second, third, fourth) = Util::splitUrl("filename");
+ CPPUNIT_ASSERT_EQUAL(std::string(""), first);
+ CPPUNIT_ASSERT_EQUAL(std::string("filename"), second);
+ CPPUNIT_ASSERT_EQUAL(std::string(""), third);
+ CPPUNIT_ASSERT_EQUAL(std::string(""), fourth);
+
+ std::tie(first, second, third, fourth) = Util::splitUrl("filename.ext");
+ CPPUNIT_ASSERT_EQUAL(std::string(""), first);
+ CPPUNIT_ASSERT_EQUAL(std::string("filename"), second);
+ CPPUNIT_ASSERT_EQUAL(std::string(".ext"), third);
+ CPPUNIT_ASSERT_EQUAL(std::string(""), fourth);
+
+ std::tie(first, second, third, fourth) = Util::splitUrl("/path/to/filename");
+ CPPUNIT_ASSERT_EQUAL(std::string("/path/to/"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string("filename"), second);
+ CPPUNIT_ASSERT_EQUAL(std::string(""), third);
+ CPPUNIT_ASSERT_EQUAL(std::string(""), fourth);
+
+ std::tie(first, second, third, fourth) = Util::splitUrl("http://domain.com/path/filename");
+ CPPUNIT_ASSERT_EQUAL(std::string("http://domain.com/path/"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string("filename"), second);
+ CPPUNIT_ASSERT_EQUAL(std::string(""), third);
+ CPPUNIT_ASSERT_EQUAL(std::string(""), fourth);
+
+ std::tie(first, second, third, fourth) = Util::splitUrl("http://domain.com/path/filename.ext");
+ CPPUNIT_ASSERT_EQUAL(std::string("http://domain.com/path/"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string("filename"), second);
+ CPPUNIT_ASSERT_EQUAL(std::string(".ext"), third);
+ CPPUNIT_ASSERT_EQUAL(std::string(""), fourth);
+
+ std::tie(first, second, third, fourth) = Util::splitUrl("http://domain.com/path/filename.ext?params=3&command=5");
+ CPPUNIT_ASSERT_EQUAL(std::string("http://domain.com/path/"), first);
+ CPPUNIT_ASSERT_EQUAL(std::string("filename"), second);
+ CPPUNIT_ASSERT_EQUAL(std::string(".ext"), third);
+ CPPUNIT_ASSERT_EQUAL(std::string("?params=3&command=5"), fourth);
+}
+
void WhiteBoxTests::testMessageAbbreviation()
{
CPPUNIT_ASSERT_EQUAL(std::string(), Util::getDelimitedInitialSubstring(nullptr, 5, '\n'));
@@ -387,6 +500,11 @@ public:
return _mutex;
}
+ std::string getObfuscatedFileId() override
+ {
+ return std::string();
+ }
+
std::shared_ptr<TileQueue>& getTileQueue() override
{
return _tileQueue;
@@ -505,6 +623,40 @@ void WhiteBoxTests::testJson()
CPPUNIT_ASSERT_EQUAL(std::string("user at user.com"), sValue);
}
+void WhiteBoxTests::testAnonymization()
+{
+ static const std::string name = "some name with space";
+ CPPUNIT_ASSERT_EQUAL(std::string("#0#77d#"), Util::anonymizeUrl(name));
+ Util::mapAnonymized(name, name);
+ CPPUNIT_ASSERT_EQUAL(name, Util::anonymizeUrl(name));
+
+ static const std::string filename = "filename.ext";
+ CPPUNIT_ASSERT_EQUAL(std::string("#1#341#.ext"), Util::anonymizeUrl(filename));
+ Util::mapAnonymized("filename", "filename");
+ CPPUNIT_ASSERT_EQUAL(name, Util::anonymizeUrl(name));
+
+ static const std::string filenameTestx = "testx (6).odt";
+ CPPUNIT_ASSERT_EQUAL(std::string("#2#2df#.odt"), Util::anonymizeUrl(filenameTestx));
+ Util::mapAnonymized("testx (6)", "testx (6)");
+ CPPUNIT_ASSERT_EQUAL(filenameTestx, Util::anonymizeUrl(filenameTestx));
+
+ static const std::string path = "/path/to/filename.ext";
+ CPPUNIT_ASSERT_EQUAL(path, Util::anonymizeUrl(path));
+
+ static const std::string plainUrl = "http://localhost/owncloud/index.php/apps/richdocuments/wopi/files/736_ocgdpzbkm39u?access_token=Hn0zttjbwkvGWb5BHbDa5ArgTykJAyBl&access_token_ttl=0&permission=edit";
+ const std::string urlAnonymized = Util::replace(plainUrl, "736_ocgdpzbkm39u", "#3#5a1#");
+ CPPUNIT_ASSERT_EQUAL(urlAnonymized, Util::anonymizeUrl(plainUrl));
+ Util::mapAnonymized("736_ocgdpzbkm39u", "736_ocgdpzbkm39u");
+ CPPUNIT_ASSERT_EQUAL(plainUrl, Util::anonymizeUrl(plainUrl));
+
+ static const std::string fileUrl = "http://localhost/owncloud/index.php/apps/richdocuments/wopi/files/736_ocgdpzbkm39u/secret.odt?access_token=Hn0zttjbwkvGWb5BHbDa5ArgTykJAyBl&access_token_ttl=0&permission=edit";
+ const std::string urlAnonymized2 = Util::replace(fileUrl, "secret", "#4#286#");
+ CPPUNIT_ASSERT_EQUAL(urlAnonymized2, Util::anonymizeUrl(fileUrl));
+ Util::mapAnonymized("secret", "736_ocgdpzbkm39u");
+ const std::string urlAnonymized3 = Util::replace(fileUrl, "secret", "736_ocgdpzbkm39u");
+ CPPUNIT_ASSERT_EQUAL(urlAnonymized3, Util::anonymizeUrl(fileUrl));
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(WhiteBoxTests);
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 4277c8da6..3e23314c4 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -527,10 +527,13 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
std::ostringstream ossWopiInfo;
wopiInfo->stringify(ossWopiInfo);
+ const std::string wopiInfoString = ossWopiInfo.str();
+ LOG_TRC("Sending wopi info to client: " << wopiInfoString);
+
// Contains PostMessageOrigin property which is necessary to post messages to parent
// frame. Important to send this message immediately and not enqueue it so that in case
// document load fails, loleaflet is able to tell its parent frame via PostMessage API.
- session->sendMessage("wopi: " + ossWopiInfo.str());
+ session->sendMessage("wopi: " + wopiInfoString);
// Mark the session as 'Document owner' if WOPI hosts supports it
if (userId == _storage->getFileInfo()._ownerId)
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 4b27ab947..45094fa09 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -2019,7 +2019,9 @@ private:
else if (reqPathTokens.count() > 2 && reqPathTokens[0] == "lool" && reqPathTokens[2] == "ws" &&
request.find("Upgrade") != request.end() && Poco::icompare(request["Upgrade"], "websocket") == 0)
{
- handleClientWsUpgrade(request, reqPathTokens[1], disposition);
+ std::string decodedUri;
+ Poco::URI::decode(reqPathTokens[1], decodedUri);
+ handleClientWsUpgrade(request, decodedUri, disposition);
}
else
{
@@ -2472,6 +2474,14 @@ private:
#endif
}
+ LOG_INF("URL [" << url << "].");
+ const auto uriPublic = DocumentBroker::sanitizeURI(url);
+ LOG_INF("URI [" << uriPublic.getPath() << "].");
+ const auto docKey = DocumentBroker::getDocKey(uriPublic);
+ LOG_INF("DocKey [" << docKey << "].");
+ const std::string fileId = Util::getFilenameFromURL(docKey);
+ Util::mapAnonymized(fileId, fileId); // Identity mapping, since fileId is already obfuscated
+
LOG_INF("Starting GET request handler for session [" << _id << "] on url [" << LOOLWSD::anonymizeUrl(url) << "].");
// Indicate to the client that document broker is searching.
@@ -2479,12 +2489,8 @@ private:
LOG_TRC("Sending to Client [" << status << "].");
ws.sendMessage(status);
- const Poco::URI uriPublic = DocumentBroker::sanitizeURI(url);
- const std::string docKey = DocumentBroker::getDocKey(uriPublic);
- const std::string fileId = Util::getFilenameFromPath(docKey);
- Util::mapAnonymized(fileId, fileId); // Identity mapping, since fileId is already obfuscated
LOG_INF("Sanitized URI [" << LOOLWSD::anonymizeUrl(url) << "] to [" << LOOLWSD::anonymizeUrl(uriPublic.toString()) <<
- "] and mapped to docKey [" << docKey << "] for session [" << _id << "].");
+ "] and mapped to docKey [" << docKey << "] for session [" << _id << "].");
// Check if readonly session is required
bool isReadOnly = false;
diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp
index 776406dad..bb3b03c1e 100644
--- a/wsd/Storage.cpp
+++ b/wsd/Storage.cpp
@@ -42,6 +42,7 @@
#include <Poco/StreamCopier.h>
#include <Poco/Timestamp.h>
+#include <Poco/URI.h>
#include "Auth.hpp"
#include <Common.hpp>
@@ -502,7 +503,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
// Anonymize key values.
if (LOOLWSD::AnonymizeFilenames || LOOLWSD::AnonymizeUsernames)
{
- Util::mapAnonymized(filename, Util::getFilenameFromPath(_uri.toString()));
+ Util::mapAnonymized(Util::getFilenameFromURL(filename), Util::getFilenameFromURL(_uri.toString()));
JsonUtil::findJSONValue(object, "ObfuscatedUserId", obfuscatedUserId, false);
if (!obfuscatedUserId.empty())
@@ -766,9 +767,17 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization&
if (JsonUtil::parseJSON(responseString, object))
{
// Anonymize the filename
+ std::string url;
+ JsonUtil::findJSONValue(object, "Url", url);
+ std::string decodedUrl;
+ Poco::URI::decode(url, decodedUrl);
+ const std::string obfuscatedFileId = Util::getFilenameFromURL(decodedUrl);
+
std::string filename;
JsonUtil::findJSONValue(object, "Name", filename);
- object->set("Name", LOOLWSD::anonymizeUsername(filename));
+ const std::string filenameOnly = Util::getFilenameFromURL(filename);
+ Util::mapAnonymized(filenameOnly, obfuscatedFileId);
+ object->set("Name", LOOLWSD::anonymizeUrl(filename));
// Stringify to log.
std::ostringstream ossResponse;
object->stringify(ossResponse);
commit 00a44d6e817756dc1a5f9a8628c01e27293249c4
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Mon Jul 16 21:42:17 2018 -0400
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: flush logs before existing
This is important for when we abort with some explanation.
Often said explanation doesn't show up anywhere to be useful.
Also, issue fatal logs for abnormal exist and use SFL to log errno.
Reviewed-on: https://gerrit.libreoffice.org/57540
Reviewed-by: Jan Holesovsky <kendy at collabora.com>
Tested-by: Jan Holesovsky <kendy at collabora.com>
(cherry picked from commit ad7964393eadb68873b820e0a620fb40f1e1b06a)
Change-Id: Ic67064ef40ef6e93d26e5847ecd32bdd49c3cc8b
diff --git a/common/Log.cpp b/common/Log.cpp
index a12f9e9bc..2136de15a 100644
--- a/common/Log.cpp
+++ b/common/Log.cpp
@@ -20,6 +20,7 @@
#include <cstring>
#include <ctime>
#include <iomanip>
+#include <iostream>
#include <sstream>
#include <string>
@@ -182,6 +183,17 @@ namespace Log
{
return Poco::Logger::get(Source.inited ? Source.name : std::string());
}
+
+ void shutdown()
+ {
+ logger().shutdown();
+
+ // Flush
+ std::flush(std::cout);
+ fflush(stdout);
+ std::flush(std::cerr);
+ fflush(stderr);
+ }
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/common/Log.hpp b/common/Log.hpp
index 543124361..9d6dae00d 100644
--- a/common/Log.hpp
+++ b/common/Log.hpp
@@ -35,13 +35,19 @@ inline std::ostream& operator<< (std::ostream& os, const Poco::Timestamp& ts)
namespace Log
{
+ /// Initialize the logging system.
void initialize(const std::string& name,
const std::string& logLevel,
const bool withColor,
const bool logToFile,
const std::map<std::string, std::string>& config);
+
+ /// Returns the underlying logging system.
Poco::Logger& logger();
+ /// Shutdown and release the logging system.
+ void shutdown();
+
char* prefix(char* buffer, std::size_t len, const char* level);
inline bool traceEnabled() { return logger().trace(); }
@@ -222,7 +228,6 @@ namespace Log
{ \
if (FILEP) \
LOG << "| " << __FILE__ << ':' << __LINE__; \
- LOG.flush(); \
} while (false)
#define LOG_BODY_(LOG, PRIO, LVL, X, FILEP) \
diff --git a/common/Seccomp.cpp b/common/Seccomp.cpp
index 888f5937d..eb17c4818 100644
--- a/common/Seccomp.cpp
+++ b/common/Seccomp.cpp
@@ -74,6 +74,7 @@ static void handleSysSignal(int /* signal */,
SigUtil::dumpBacktrace();
+ Log::shutdown();
_exit(1);
}
diff --git a/common/Util.cpp b/common/Util.cpp
index f824ca2c7..3c8e9d27f 100644
--- a/common/Util.cpp
+++ b/common/Util.cpp
@@ -240,6 +240,7 @@ namespace Util
int ret = execvp(params[0], ¶ms[0]);
if (ret < 0)
std::cerr << "Failed to exec command '" << cmd << "' with error '" << strerror(errno) << "'\n";
+ Log::shutdown();
_exit(42);
}
// else spawning process still
diff --git a/kit/ForKit.cpp b/kit/ForKit.cpp
index c5fffba72..38c15d215 100644
--- a/kit/ForKit.cpp
+++ b/kit/ForKit.cpp
@@ -530,7 +530,11 @@ int main(int argc, char** argv)
// Initialize LoKit
if (!globalPreinit(loTemplate))
+ {
+ LOG_FTL("Failed to preinit lokit.");
+ Log::shutdown();
std::_Exit(Application::EXIT_SOFTWARE);
+ }
if (Util::getProcessThreadCount() != 1)
LOG_ERR("Error: forkit has more than a single thread after pre-init");
@@ -544,6 +548,7 @@ int main(int argc, char** argv)
if (forKitPid < 0)
{
LOG_FTL("Failed to create a kit process.");
+ Log::shutdown();
std::_Exit(Application::EXIT_SOFTWARE);
}
@@ -580,6 +585,7 @@ int main(int argc, char** argv)
#endif
LOG_INF("ForKit process finished.");
+ Log::shutdown();
std::_Exit(returnValue);
}
#endif
diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index 414f56273..abdb0238f 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -226,8 +226,9 @@ namespace
}
catch (const std::exception& exc)
{
- LOG_ERR("Copying of '" << fpath << "' to " << newPath.toString() <<
+ LOG_FTL("Copying of '" << fpath << "' to " << newPath.toString() <<
" failed: " << exc.what() << ". Exiting.");
+ Log::shutdown();
std::_Exit(Application::EXIT_SOFTWARE);
}
}
@@ -333,7 +334,8 @@ namespace
caps = cap_get_proc();
if (caps == nullptr)
{
- LOG_SYS("cap_get_proc() failed.");
+ LOG_SFL("cap_get_proc() failed.");
+ Log::shutdown();
std::_Exit(1);
}
@@ -344,13 +346,15 @@ namespace
if (cap_set_flag(caps, CAP_EFFECTIVE, sizeof(cap_list)/sizeof(cap_list[0]), cap_list, CAP_CLEAR) == -1 ||
cap_set_flag(caps, CAP_PERMITTED, sizeof(cap_list)/sizeof(cap_list[0]), cap_list, CAP_CLEAR) == -1)
{
- LOG_SYS("cap_set_flag() failed.");
+ LOG_SFL("cap_set_flag() failed.");
+ Log::shutdown();
std::_Exit(1);
}
if (cap_set_proc(caps) == -1)
{
- LOG_SYS("cap_set_proc() failed.");
+ LOG_SFL("cap_set_proc() failed.");
+ Log::shutdown();
std::_Exit(1);
}
@@ -506,7 +510,7 @@ class PngCache
int width, int height,
int bufferWidth, int bufferHeight,
std::vector<char>& output, LibreOfficeKitTileMode mode,
- TileBinaryHash hash, TileWireId wid, TileWireId /* oldWid */)
+ TileBinaryHash hash, TileWireId wid, TileWireId /*oldWid*/)
{
LOG_DBG("PNG cache with hash " << hash << " missed.");
/*
@@ -907,7 +911,8 @@ public:
#ifndef MOBILEAPP
if (num_sessions == 0)
{
- LOG_INF("Document [" << anonymizeUrl(_url) << "] has no more views, exiting bluntly.");
+ LOG_FTL("Document [" << anonymizeUrl(_url) << "] has no more views, exiting bluntly.");
+ Log::shutdown();
std::_Exit(Application::EXIT_OK);
}
#endif
@@ -1389,6 +1394,7 @@ private:
if (_sessions.empty())
{
LOG_INF("Document [" << anonymizeUrl(_url) << "] has no more views, exiting bluntly.");
+ Log::shutdown();
std::_Exit(Application::EXIT_OK);
}
#endif
@@ -1773,7 +1779,7 @@ private:
std::vector<char> vect(size);
vect.assign(data, data + size);
- // TODO loolnb - this is probably wrong...
+ // TODO this is probably wrong...
session->handleMessage(/* fin = */ false, WSOpCode::Binary, vect);
return true;
}
@@ -2205,6 +2211,7 @@ void lokit_main(
}
Util::rng::reseed();
+
const std::string LogLevel = logLevel ? logLevel : "trace";
const bool bTraceStartup = (std::getenv("LOOL_TRACE_STARTUP") != nullptr);
Log::initialize("kit", bTraceStartup ? "trace" : logLevel, logColor != nullptr, logToFile, logProperties);
@@ -2324,13 +2331,15 @@ void lokit_main(
LOG_INF("chroot(\"" << jailPath.toString() << "\")");
if (chroot(jailPath.toString().c_str()) == -1)
{
- LOG_SYS("chroot(\"" << jailPath.toString() << "\") failed.");
+ LOG_SFL("chroot(\"" << jailPath.toString() << "\") failed.");
+ Log::shutdown();
std::_Exit(Application::EXIT_SOFTWARE);
}
if (chdir("/") == -1)
{
- LOG_SYS("chdir(\"/\") in jail failed.");
+ LOG_SFL("chdir(\"/\") in jail failed.");
+ Log::shutdown();
std::_Exit(Application::EXIT_SOFTWARE);
}
@@ -2372,6 +2381,7 @@ void lokit_main(
if (!loKit)
{
LOG_FTL("LibreOfficeKit initialization failed. Exiting.");
+ Log::shutdown();
std::_Exit(Application::EXIT_SOFTWARE);
}
}
@@ -2381,7 +2391,8 @@ void lokit_main(
{
if (!noSeccomp)
{
- LOG_ERR("LibreOfficeKit seccomp security lockdown failed. Exiting.");
+ LOG_FTL("LibreOfficeKit seccomp security lockdown failed. Exiting.");
+ Log::shutdown();
std::_Exit(Application::EXIT_SOFTWARE);
}
@@ -2497,6 +2508,7 @@ void lokit_main(
// Trap the signal handler, if invoked,
// to prevent exiting.
LOG_INF("Process finished.");
+ Log::shutdown();
std::unique_lock<std::mutex> lock(SigHandlerTrap);
std::_Exit(Application::EXIT_OK);
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 8e961e60b..4b27ab947 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -805,7 +805,8 @@ void LOOLWSD::initialize(Application& self)
{ "tile_cache_persistent", "true" },
{ "trace.path[@compress]", "true" },
{ "trace.path[@snapshot]", "false" },
- { "trace[@enable]", "false" } };
+ { "trace[@enable]", "false" }
+ };
// Set default values, in case they are missing from the config file.
AutoPtr<AppConfigMap> defConfig(new AppConfigMap(DefAppConfig));
@@ -880,6 +881,7 @@ void LOOLWSD::initialize(Application& self)
#if ENABLE_DEBUG
std::cerr << "\nIf you have used 'make run', edit loolwsd.xml and make sure you have removed '--o:logging.level=trace' from the command line in Makefile.am.\n" << std::endl;
#endif
+ Log::shutdown();
_exit(Application::EXIT_SOFTWARE);
}
}
@@ -2241,18 +2243,18 @@ private:
Poco::URI uriPublic = DocumentBroker::sanitizeURI(fromPath);
const std::string docKey = DocumentBroker::getDocKey(uriPublic);
- // This lock could become a bottleneck.
- // In that case, we can use a pool and index by publicPath.
- std::unique_lock<std::mutex> docBrokersLock(DocBrokersMutex);
+ // This lock could become a bottleneck.
+ // In that case, we can use a pool and index by publicPath.
+ std::unique_lock<std::mutex> docBrokersLock(DocBrokersMutex);
- LOG_DBG("New DocumentBroker for docKey [" << docKey << "].");
- auto docBroker = std::make_shared<DocumentBroker>(fromPath, uriPublic, docKey, LOOLWSD::ChildRoot);
+ LOG_DBG("New DocumentBroker for docKey [" << docKey << "].");
+ auto docBroker = std::make_shared<DocumentBroker>(fromPath, uriPublic, docKey, LOOLWSD::ChildRoot);
- cleanupDocBrokers();
+ cleanupDocBrokers();
- LOG_DBG("New DocumentBroker for docKey [" << docKey << "].");
- DocBrokers.emplace(docKey, docBroker);
- LOG_TRC("Have " << DocBrokers.size() << " DocBrokers after inserting [" << docKey << "].");
+ LOG_DBG("New DocumentBroker for docKey [" << docKey << "].");
+ DocBrokers.emplace(docKey, docBroker);
+ LOG_TRC("Have " << DocBrokers.size() << " DocBrokers after inserting [" << docKey << "].");
// Load the document.
// TODO: Move to DocumentBroker.
@@ -2301,7 +2303,7 @@ private:
std::vector<char> saveasRequest(saveas.begin(), saveas.end());
clientSession->handleMessage(true, WSOpCode::Text, saveasRequest);
});
- });
+ });
sent = true;
}
@@ -2846,6 +2848,7 @@ private:
{
LOG_FTL("Failed to listen on Prisoner port(s) (" <<
MasterPortNumber << '-' << port << "). Exiting.");
+ Log::shutdown();
_exit(Application::EXIT_SOFTWARE);
}
@@ -2875,7 +2878,6 @@ private:
#endif
factory = std::make_shared<PlainSocketFactory>();
-
std::shared_ptr<ServerSocket> socket = getServerSocket(
ClientListenAddr, port, WebServerPoll, factory);
#ifdef BUILDING_TESTS
@@ -2953,13 +2955,11 @@ int LOOLWSD::innerMain()
LOG_FTL("Missing --systemplate option");
throw MissingOptionException("systemplate");
}
-
if (LoTemplate.empty())
{
LOG_FTL("Missing --lotemplate option");
throw MissingOptionException("lotemplate");
}
-
if (ChildRoot.empty())
{
LOG_FTL("Missing --childroot option");
commit 053161b3f514d2a96278f8e3edc91da1b6c761c0
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Fri Jul 13 00:18:30 2018 -0400
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: move string utilities into Util
Reviewed-on: https://gerrit.libreoffice.org/57539
Reviewed-by: Jan Holesovsky <kendy at collabora.com>
Tested-by: Jan Holesovsky <kendy at collabora.com>
(cherry picked from commit fb2671c4145edd4d4e359f0dcf5cc84835487cd4)
Change-Id: Idc578dff4e8ee5e48c1b7780d3feb2d21c6a9b13
diff --git a/common/Protocol.hpp b/common/Protocol.hpp
index 61e16d31f..23b7d96e8 100644
--- a/common/Protocol.hpp
+++ b/common/Protocol.hpp
@@ -22,6 +22,8 @@
#include <Poco/Net/WebSocket.h>
+#include <Util.hpp>
+
#define LOK_USE_UNSTABLE_API
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
@@ -145,45 +147,11 @@ namespace LOOLProtocol
return getTokenInteger(tokenize(message), name, value);
}
- inline size_t getDelimiterPosition(const char* message, const int length, const char delim)
- {
- if (message && length > 0)
- {
- const char *founddelim = static_cast<const char *>(std::memchr(message, delim, length));
- const size_t size = (founddelim == nullptr ? length : founddelim - message);
- return size;
- }
-
- return 0;
- }
-
- inline
- std::string getDelimitedInitialSubstring(const char *message, const int length, const char delim)
- {
- const size_t size = getDelimiterPosition(message, length, delim);
- return std::string(message, size);
- }
-
- /// Split a string in two at the delimeter, removing it.
- inline
- std::pair<std::string, std::string> split(const char* s, const int length, const char delimeter = ' ')
- {
- const size_t size = getDelimiterPosition(s, length, delimeter);
- return std::make_pair(std::string(s, size), std::string(s+size+1));
- }
-
- /// Split a string in two at the delimeter, removing it.
- inline
- std::pair<std::string, std::string> split(const std::string& s, const char delimeter = ' ')
- {
- return split(s.c_str(), s.size(), delimeter);
- }
-
/// Returns the first token of a message.
inline
std::string getFirstToken(const char *message, const int length, const char delim = ' ')
{
- return getDelimitedInitialSubstring(message, length, delim);
+ return Util::getDelimitedInitialSubstring(message, length, delim);
}
template <typename T>
@@ -247,7 +215,7 @@ namespace LOOLProtocol
inline
std::string getFirstLine(const char *message, const int length)
{
- return getDelimitedInitialSubstring(message, length, '\n');
+ return Util::getDelimitedInitialSubstring(message, length, '\n');
}
/// Returns the first line of any data which payload char*.
@@ -283,7 +251,7 @@ namespace LOOLProtocol
inline std::string getAbbreviatedMessage(const std::string& message)
{
- const size_t pos = getDelimiterPosition(message.data(), std::min(message.size(), 500UL), '\n');
+ const size_t pos = Util::getDelimiterPosition(message.data(), std::min(message.size(), 501UL), '\n');
// If first line is less than the length (minus newline), add ellipsis.
if (pos < static_cast<std::string::size_type>(message.size()) - 1)
diff --git a/common/Util.hpp b/common/Util.hpp
index 70c77c85e..c252d253e 100644
--- a/common/Util.hpp
+++ b/common/Util.hpp
@@ -561,6 +561,40 @@ namespace Util
}
}
+ inline size_t getDelimiterPosition(const char* message, const int length, const char delim)
+ {
+ if (message && length > 0)
+ {
+ const char *founddelim = static_cast<const char *>(std::memchr(message, delim, length));
+ const size_t size = (founddelim == nullptr ? length : founddelim - message);
+ return size;
+ }
+
+ return 0;
+ }
+
+ inline
+ std::string getDelimitedInitialSubstring(const char *message, const int length, const char delim)
+ {
+ const size_t size = getDelimiterPosition(message, length, delim);
+ return std::string(message, size);
+ }
+
+ /// Split a string in two at the delimeter, removing it.
+ inline
+ std::pair<std::string, std::string> split(const char* s, const int length, const char delimeter = ' ')
+ {
+ const size_t size = getDelimiterPosition(s, length, delimeter);
+ return std::make_pair(std::string(s, size), std::string(s+size+1));
+ }
+
+ /// Split a string in two at the delimeter, removing it.
+ inline
+ std::pair<std::string, std::string> split(const std::string& s, const char delimeter = ' ')
+ {
+ return split(s.c_str(), s.size(), delimeter);
+ }
+
/// Check for the URI scheme validity.
/// For now just a basic sanity check, can be extended if necessary.
bool isValidURIScheme(const std::string& scheme);
diff --git a/kit/ForKit.cpp b/kit/ForKit.cpp
index ae2a5fe6d..c5fffba72 100644
--- a/kit/ForKit.cpp
+++ b/kit/ForKit.cpp
@@ -452,7 +452,7 @@ int main(int argc, char** argv)
std::vector<std::string> tokens = LOOLProtocol::tokenize(rlimits, ';');
for (const std::string& cmdLimit : tokens)
{
- const std::pair<std::string, std::string> pair = LOOLProtocol::split(cmdLimit, ':');
+ const std::pair<std::string, std::string> pair = Util::split(cmdLimit, ':');
std::vector<std::string> tokensLimit = { "setconfig", pair.first, pair.second };
if (!Rlimit::handleSetrlimitCommand(tokensLimit))
{
diff --git a/test/WhiteBoxTests.cpp b/test/WhiteBoxTests.cpp
index 6ae763f7f..a26ccf686 100644
--- a/test/WhiteBoxTests.cpp
+++ b/test/WhiteBoxTests.cpp
@@ -144,11 +144,11 @@ void WhiteBoxTests::testLOOLProtocolFunctions()
void WhiteBoxTests::testMessageAbbreviation()
{
- CPPUNIT_ASSERT_EQUAL(std::string(), LOOLProtocol::getDelimitedInitialSubstring(nullptr, 5, '\n'));
- CPPUNIT_ASSERT_EQUAL(std::string(), LOOLProtocol::getDelimitedInitialSubstring(nullptr, -1, '\n'));
- CPPUNIT_ASSERT_EQUAL(std::string(), LOOLProtocol::getDelimitedInitialSubstring("abc", 0, '\n'));
- CPPUNIT_ASSERT_EQUAL(std::string(), LOOLProtocol::getDelimitedInitialSubstring("abc", -1, '\n'));
- CPPUNIT_ASSERT_EQUAL(std::string("ab"), LOOLProtocol::getDelimitedInitialSubstring("abc", 2, '\n'));
+ CPPUNIT_ASSERT_EQUAL(std::string(), Util::getDelimitedInitialSubstring(nullptr, 5, '\n'));
+ CPPUNIT_ASSERT_EQUAL(std::string(), Util::getDelimitedInitialSubstring(nullptr, -1, '\n'));
+ CPPUNIT_ASSERT_EQUAL(std::string(), Util::getDelimitedInitialSubstring("abc", 0, '\n'));
+ CPPUNIT_ASSERT_EQUAL(std::string(), Util::getDelimitedInitialSubstring("abc", -1, '\n'));
+ CPPUNIT_ASSERT_EQUAL(std::string("ab"), Util::getDelimitedInitialSubstring("abc", 2, '\n'));
CPPUNIT_ASSERT_EQUAL(std::string(), LOOLProtocol::getAbbreviatedMessage(nullptr, 5));
CPPUNIT_ASSERT_EQUAL(std::string(), LOOLProtocol::getAbbreviatedMessage(nullptr, -1));
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index 4e9270f02..a764a951e 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -869,7 +869,7 @@ bool ClientSession::handleKitToClientMessage(const char* buffer, const int lengt
else
{
// Set the initial settings per the user's request.
- const std::pair<std::string, std::string> unoStatePair = LOOLProtocol::split(tokens[1], '=');
+ const std::pair<std::string, std::string> unoStatePair = Util::split(tokens[1], '=');
if (!docBroker->isInitialSettingSet(unoStatePair.first))
{
commit b516891815120be811d32f2be170101ffa80c0cd
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Thu Jul 12 18:00:33 2018 -0400
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: prevent anonymization to empty strings
Change-Id: Ib4f90db5d39e7bf2e2f0b6566b1927363e6afcec
Reviewed-on: https://gerrit.libreoffice.org/57377
Reviewed-by: Jan Holesovsky <kendy at collabora.com>
Tested-by: Jan Holesovsky <kendy at collabora.com>
(cherry picked from commit 84245aa61e89cda6a9075a7059b5a7d839389719)
diff --git a/common/Util.cpp b/common/Util.cpp
index 05eed2f47..f824ca2c7 100644
--- a/common/Util.cpp
+++ b/common/Util.cpp
@@ -619,6 +619,9 @@ namespace Util
void mapAnonymized(const std::string& plain, const std::string& anonymized)
{
+ if (plain.empty() || anonymized.empty())
+ return;
+
LOG_TRC("Anonymizing [" << plain << "] -> [" << anonymized << "].");
std::unique_lock<std::mutex> lock(AnonymizedMutex);
@@ -633,7 +636,10 @@ namespace Util
const auto it = AnonymizedStrings.find(text);
if (it != AnonymizedStrings.end())
+ {
+ LOG_TRC("Found anonymized [" << text << "] -> [" << it->second << "].");
return it->second;
+ }
}
// We just need something irreversible, short, and
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index e4f8790a5..4e9270f02 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -408,12 +408,12 @@ bool ClientSession::loadDocument(const char* /*buffer*/, int /*length*/,
std::string encodedUserId;
Poco::URI::encode(_userId, "", encodedUserId);
oss << " authorid=" << encodedUserId;
- oss << " xauthorid=" << LOOLWSD::anonymizeUsername(encodedUserId);
+ oss << " xauthorid=" << LOOLWSD::anonymizeUsername(_userId);
std::string encodedUserName;
Poco::URI::encode(_userName, "", encodedUserName);
oss << " author=" << encodedUserName;
- oss << " xauthor=" << LOOLWSD::anonymizeUsername(encodedUserName);
+ oss << " xauthor=" << LOOLWSD::anonymizeUsername(_userName);
}
if (!_userExtraInfo.empty())
commit 4587dde56fe4ea1b1863cabe8b10229c6a5135dd
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Tue Jul 10 23:09:27 2018 -0400
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: anonymize filename by using the WOPI file ID
Reviewed-on: https://gerrit.libreoffice.org/57254
Reviewed-by: Jan Holesovsky <kendy at collabora.com>
Tested-by: Jan Holesovsky <kendy at collabora.com>
(cherry picked from commit 5e3568ff1029da948f05d1c0e0c56c6d0706690e)
Change-Id: I869cae3846c8630b192246bc68cc90e70c50d1fd
diff --git a/common/Session.cpp b/common/Session.cpp
index fc9aa21e5..34c608924 100644
--- a/common/Session.cpp
+++ b/common/Session.cpp
@@ -163,6 +163,10 @@ void Session::parseDocOptions(const std::vector<std::string>& tokens, int& part,
}
}
+ Util::mapAnonymized(_userId, _userIdAnonym);
+ Util::mapAnonymized(_userName, _userNameAnonym);
+ Util::mapAnonymized(_jailedFilePath, _jailedFilePathAnonym);
+
if (tokens.size() > offset)
{
if (getTokenString(tokens[offset], "options", _docOptions))
diff --git a/common/Util.cpp b/common/Util.cpp
index afb58e46f..05eed2f47 100644
--- a/common/Util.cpp
+++ b/common/Util.cpp
@@ -615,12 +615,26 @@ namespace Util
static std::map<std::string, std::string> AnonymizedStrings;
static std::atomic<unsigned> AnonymizationSalt(0);
+ static std::mutex AnonymizedMutex;
+
+ void mapAnonymized(const std::string& plain, const std::string& anonymized)
+ {
+ LOG_TRC("Anonymizing [" << plain << "] -> [" << anonymized << "].");
+
+ std::unique_lock<std::mutex> lock(AnonymizedMutex);
+
+ AnonymizedStrings[plain] = anonymized;
+ }
std::string anonymize(const std::string& text)
{
- const auto it = AnonymizedStrings.find(text);
- if (it != AnonymizedStrings.end())
- return it->second;
+ {
+ std::unique_lock<std::mutex> lock(AnonymizedMutex);
+
+ const auto it = AnonymizedStrings.find(text);
+ if (it != AnonymizedStrings.end())
+ return it->second;
+ }
// We just need something irreversible, short, and
// quite simple.
@@ -631,7 +645,7 @@ namespace Util
// Generate the anonymized string. The '#' is to hint that it's anonymized.
// Prepend with salt to make it unique, in case we get collisions (which we will, eventually).
const std::string res = '#' + Util::encodeId(AnonymizationSalt++, 0) + '#' + Util::encodeId(hash, 0) + '#';
- AnonymizedStrings[text] = res;
+ mapAnonymized(text, res);
return res;
}
@@ -652,6 +666,16 @@ namespace Util
return Util::anonymize(basename) + ext;
}
+ std::string getFilenameFromPath(const std::string& path)
+ {
+ const std::size_t mid = path.find_last_of('/');
+ if (mid != std::string::npos)
+ return path.substr(mid + 1);
+
+ // No path, treat as filename only.
+ return path;
+ }
+
std::string anonymizeUrl(const std::string& url)
{
const std::size_t mid = url.find_last_of('/');
diff --git a/common/Util.hpp b/common/Util.hpp
index 0ce59a0d0..70c77c85e 100644
--- a/common/Util.hpp
+++ b/common/Util.hpp
@@ -573,9 +573,16 @@ namespace Util
/// Called on strings to be logged or exposed.
std::string anonymize(const std::string& text);
+ /// Sets the anonymized version of a given plain-text string.
+ /// After this, 'anonymize(plain)' will return 'anonymized'.
+ void mapAnonymized(const std::string& plain, const std::string& anonymized);
+
/// Anonymize the basename of filenames only, preserving the path and extension.
std::string anonymizeUrl(const std::string& url);
+ /// Extract and return the filename given a path (i.e. the token after last '/').
+ std::string getFilenameFromPath(const std::string& path);
+
/// Given one or more patterns to allow, and one or more to deny,
/// the match member will return true if, and only if, the subject
/// matches the allowed list, but not the deny.
diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index 93debb60b..414f56273 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -115,6 +115,7 @@ static std::shared_ptr<Document> document;
#ifndef BUILDING_TESTS
static bool AnonymizeFilenames = false;
static bool AnonymizeUsernames = false;
+static std::string ObfuscatedFileId;
static std::string ObfuscatedUserId;
#endif
@@ -2099,6 +2100,8 @@ protected:
const std::string& sessionId = tokens[1];
const std::string& docKey = tokens[2];
const std::string& docId = tokens[3];
+ const std::string fileId = Util::getFilenameFromPath(docKey);
+ Util::mapAnonymized(fileId, fileId); // Identity mapping, since fileId is already obfuscated
std::string url;
URI::decode(docKey, url);
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index fecf421e0..4277c8da6 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -481,7 +481,6 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
{
std::unique_ptr<WopiStorage::WOPIFileInfo> wopifileinfo = wopiStorage->getWOPIFileInfo(session->getAuthorization());
userId = wopifileinfo->_userId;
- LOOLWSD::ObfuscatedUserId = wopifileinfo->_obfuscatedUserId;
username = wopifileinfo->_username;
userExtraInfo = wopifileinfo->_userExtraInfo;
watermarkText = wopifileinfo->_watermarkText;
@@ -1071,7 +1070,7 @@ size_t DocumentBroker::addSessionInternal(const std::shared_ptr<ClientSession>&
const std::string id = session->getId();
// Request a new session from the child kit.
- const std::string aMessage = "session " + id + ' ' + _docKey + ' ' + _docId + ' ' + LOOLWSD::ObfuscatedUserId;
+ const std::string aMessage = "session " + id + ' ' + _docKey + ' ' + _docId;
_childProcess->sendTextFrame(aMessage);
#ifndef MOBILEAPP
@@ -1839,7 +1838,7 @@ void DocumentBroker::dumpState(std::ostream& os)
uint64_t sent, recv;
getIOStats(sent, recv);
- os << " Broker: " << _filename << " pid: " << getPid();
+ os << " Broker: " << LOOLWSD::anonymizeUrl(_filename) << " pid: " << getPid();
if (_markToDestroy)
os << " *** Marked to destroy ***";
else
@@ -1852,9 +1851,9 @@ void DocumentBroker::dumpState(std::ostream& os)
os << "\n recv: " << recv;
os << "\n modified?: " << _isModified;
os << "\n jail id: " << _jailId;
- os << "\n filename: " << _filename;
+ os << "\n filename: " << LOOLWSD::anonymizeUrl(_filename);
os << "\n public uri: " << _uriPublic.toString();
- os << "\n jailed uri: " << _uriJailed;
+ os << "\n jailed uri: " << LOOLWSD::anonymizeUrl(_uriJailed);
os << "\n doc key: " << _docKey;
os << "\n doc id: " << _docId;
os << "\n num sessions: " << _sessions.size();
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 65160c0bf..8e961e60b 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -671,7 +671,6 @@ std::string LOOLWSD::ConfigDir = LOOLWSD_CONFIGDIR "/conf.d";
std::string LOOLWSD::LogLevel = "trace";
bool LOOLWSD::AnonymizeFilenames = false;
bool LOOLWSD::AnonymizeUsernames = false;
-std::string LOOLWSD::ObfuscatedUserId;
Util::RuntimeConstant<bool> LOOLWSD::SSLEnabled;
Util::RuntimeConstant<bool> LOOLWSD::SSLTermination;
unsigned LOOLWSD::MaxConnections;
@@ -806,8 +805,7 @@ void LOOLWSD::initialize(Application& self)
{ "tile_cache_persistent", "true" },
{ "trace.path[@compress]", "true" },
{ "trace.path[@snapshot]", "false" },
- { "trace[@enable]", "false" }
- };
+ { "trace[@enable]", "false" } };
// Set default values, in case they are missing from the config file.
AutoPtr<AppConfigMap> defConfig(new AppConfigMap(DefAppConfig));
@@ -2243,18 +2241,18 @@ private:
Poco::URI uriPublic = DocumentBroker::sanitizeURI(fromPath);
const std::string docKey = DocumentBroker::getDocKey(uriPublic);
- // This lock could become a bottleneck.
- // In that case, we can use a pool and index by publicPath.
- std::unique_lock<std::mutex> docBrokersLock(DocBrokersMutex);
+ // This lock could become a bottleneck.
+ // In that case, we can use a pool and index by publicPath.
+ std::unique_lock<std::mutex> docBrokersLock(DocBrokersMutex);
- LOG_DBG("New DocumentBroker for docKey [" << docKey << "].");
- auto docBroker = std::make_shared<DocumentBroker>(fromPath, uriPublic, docKey, LOOLWSD::ChildRoot);
+ LOG_DBG("New DocumentBroker for docKey [" << docKey << "].");
+ auto docBroker = std::make_shared<DocumentBroker>(fromPath, uriPublic, docKey, LOOLWSD::ChildRoot);
- cleanupDocBrokers();
+ cleanupDocBrokers();
- LOG_DBG("New DocumentBroker for docKey [" << docKey << "].");
- DocBrokers.emplace(docKey, docBroker);
- LOG_TRC("Have " << DocBrokers.size() << " DocBrokers after inserting [" << docKey << "].");
+ LOG_DBG("New DocumentBroker for docKey [" << docKey << "].");
+ DocBrokers.emplace(docKey, docBroker);
+ LOG_TRC("Have " << DocBrokers.size() << " DocBrokers after inserting [" << docKey << "].");
// Load the document.
// TODO: Move to DocumentBroker.
@@ -2303,7 +2301,7 @@ private:
std::vector<char> saveasRequest(saveas.begin(), saveas.end());
clientSession->handleMessage(true, WSOpCode::Text, saveasRequest);
});
- });
+ });
sent = true;
}
@@ -2481,8 +2479,10 @@ private:
const Poco::URI uriPublic = DocumentBroker::sanitizeURI(url);
const std::string docKey = DocumentBroker::getDocKey(uriPublic);
+ const std::string fileId = Util::getFilenameFromPath(docKey);
+ Util::mapAnonymized(fileId, fileId); // Identity mapping, since fileId is already obfuscated
LOG_INF("Sanitized URI [" << LOOLWSD::anonymizeUrl(url) << "] to [" << LOOLWSD::anonymizeUrl(uriPublic.toString()) <<
- "] and mapped to docKey [" << docKey << "] for session [" << _id << "].");
+ "] and mapped to docKey [" << docKey << "] for session [" << _id << "].");
// Check if readonly session is required
bool isReadOnly = false;
@@ -2875,6 +2875,7 @@ private:
#endif
factory = std::make_shared<PlainSocketFactory>();
+
std::shared_ptr<ServerSocket> socket = getServerSocket(
ClientListenAddr, port, WebServerPoll, factory);
#ifdef BUILDING_TESTS
@@ -2952,11 +2953,13 @@ int LOOLWSD::innerMain()
LOG_FTL("Missing --systemplate option");
throw MissingOptionException("systemplate");
}
+
if (LoTemplate.empty())
{
LOG_FTL("Missing --lotemplate option");
throw MissingOptionException("lotemplate");
}
+
if (ChildRoot.empty())
{
LOG_FTL("Missing --childroot option");
diff --git a/wsd/LOOLWSD.hpp b/wsd/LOOLWSD.hpp
index 1c1dad34f..9e8f7b254 100644
--- a/wsd/LOOLWSD.hpp
+++ b/wsd/LOOLWSD.hpp
@@ -66,7 +66,6 @@ public:
static std::string LogLevel;
static bool AnonymizeFilenames;
static bool AnonymizeUsernames;
- static std::string ObfuscatedUserId;
static std::atomic<unsigned> NumConnections;
static bool TileCachePersistent;
static std::unique_ptr<TraceFileWriter> TraceDumper;
@@ -150,10 +149,7 @@ public:
/// Will use the Obfuscated User ID if one is provied via WOPI.
static std::string anonymizeUsername(const std::string& username)
{
- if (AnonymizeUsernames)
- return !ObfuscatedUserId.empty() ? ObfuscatedUserId : Util::anonymize(username);
-
- return username;
+ return AnonymizeUsernames ? Util::anonymize(username) : username;
}
int innerMain();
diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp
index 7eb03758c..776406dad 100644
--- a/wsd/Storage.cpp
+++ b/wsd/Storage.cpp
@@ -502,7 +502,15 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
// Anonymize key values.
if (LOOLWSD::AnonymizeFilenames || LOOLWSD::AnonymizeUsernames)
{
+ Util::mapAnonymized(filename, Util::getFilenameFromPath(_uri.toString()));
+
JsonUtil::findJSONValue(object, "ObfuscatedUserId", obfuscatedUserId, false);
+ if (!obfuscatedUserId.empty())
+ {
+ Util::mapAnonymized(ownerId, obfuscatedUserId);
+ Util::mapAnonymized(userId, obfuscatedUserId);
+ Util::mapAnonymized(userName, obfuscatedUserId);
+ }
// Set anonymized version of the above fields before logging.
// Note: anonymization caches the result, so we don't need to store here.
commit 1d5b6ca20bbc5a1f01a55ecb91bc2951f3c9adae
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Sun Jul 8 22:50:09 2018 -0400
Commit: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Tue Oct 16 20:12:23 2018 -0400
wsd: use obfascated user id when provided by WOPI
Change-Id: I69a17dff0e5e6b27e4538d9fe9019e4d1eebb16f
Reviewed-on: https://gerrit.libreoffice.org/57171
Reviewed-by: Jan Holesovsky <kendy at collabora.com>
Tested-by: Jan Holesovsky <kendy at collabora.com>
(cherry picked from commit 62dadb8aaa5cf9ba8cbbe0bc7f84dfc1076104c1)
diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index 69b5c8cb2..93debb60b 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -115,6 +115,7 @@ static std::shared_ptr<Document> document;
#ifndef BUILDING_TESTS
static bool AnonymizeFilenames = false;
static bool AnonymizeUsernames = false;
+static std::string ObfuscatedUserId;
#endif
#if ENABLE_DEBUG
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 584d95f49..fecf421e0 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -470,7 +470,7 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
assert(_storage != nullptr);
// Call the storage specific fileinfo functions
- std::string userid, username;
+ std::string userId, username;
std::string userExtraInfo;
std::string watermarkText;
std::chrono::duration<double> getInfoCallDuration(0);
@@ -480,7 +480,8 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
if (wopiStorage != nullptr)
{
std::unique_ptr<WopiStorage::WOPIFileInfo> wopifileinfo = wopiStorage->getWOPIFileInfo(session->getAuthorization());
- userid = wopifileinfo->_userid;
+ userId = wopifileinfo->_userId;
+ LOOLWSD::ObfuscatedUserId = wopifileinfo->_obfuscatedUserId;
username = wopifileinfo->_username;
userExtraInfo = wopifileinfo->_userExtraInfo;
watermarkText = wopifileinfo->_watermarkText;
@@ -533,7 +534,7 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
session->sendMessage("wopi: " + ossWopiInfo.str());
// Mark the session as 'Document owner' if WOPI hosts supports it
- if (userid == _storage->getFileInfo()._ownerId)
+ if (userId == _storage->getFileInfo()._ownerId)
{
LOG_DBG("Session [" << sessionId << "] is the document owner");
session->setDocumentOwner(true);
@@ -551,7 +552,7 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
if (localStorage != nullptr)
{
std::unique_ptr<LocalStorage::LocalFileInfo> localfileinfo = localStorage->getLocalFileInfo();
- userid = localfileinfo->_userid;
+ userId = localfileinfo->_userId;
username = localfileinfo->_username;
if (LOOLWSD::IsViewFileExtension(localStorage->getFileExtension()))
@@ -562,14 +563,16 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
}
}
+
#if ENABLE_SUPPORT_KEY
if (!LOOLWSD::OverrideWatermark.empty())
watermarkText = LOOLWSD::OverrideWatermark;
#endif
LOG_DBG("Setting username [" << LOOLWSD::anonymizeUsername(username) << "] and userId [" <<
- LOOLWSD::anonymizeUsername(userid) << "] for session [" << sessionId << "]");
- session->setUserId(userid);
+ LOOLWSD::anonymizeUsername(userId) << "] for session [" << sessionId << "]");
+
+ session->setUserId(userId);
session->setUserName(username);
session->setUserExtraInfo(userExtraInfo);
session->setWatermarkText(watermarkText);
@@ -1068,7 +1071,7 @@ size_t DocumentBroker::addSessionInternal(const std::shared_ptr<ClientSession>&
const std::string id = session->getId();
// Request a new session from the child kit.
- const std::string aMessage = "session " + id + ' ' + _docKey + ' ' + _docId;
+ const std::string aMessage = "session " + id + ' ' + _docKey + ' ' + _docId + ' ' + LOOLWSD::ObfuscatedUserId;
_childProcess->sendTextFrame(aMessage);
#ifndef MOBILEAPP
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index c1c457cb6..65160c0bf 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -671,6 +671,7 @@ std::string LOOLWSD::ConfigDir = LOOLWSD_CONFIGDIR "/conf.d";
std::string LOOLWSD::LogLevel = "trace";
bool LOOLWSD::AnonymizeFilenames = false;
bool LOOLWSD::AnonymizeUsernames = false;
+std::string LOOLWSD::ObfuscatedUserId;
Util::RuntimeConstant<bool> LOOLWSD::SSLEnabled;
Util::RuntimeConstant<bool> LOOLWSD::SSLTermination;
unsigned LOOLWSD::MaxConnections;
@@ -859,14 +860,16 @@ void LOOLWSD::initialize(Application& self)
#else
AnonymizeUsernames = getConfigValue<bool>(conf, "logging.anonymize.usernames", false);
#endif
- setenv("LOOL_ANONYMIZE_USERNAMES", AnonymizeUsernames ? "1" : "0", true);
+ if (AnonymizeUsernames)
+ setenv("LOOL_ANONYMIZE_USERNAMES", AnonymizeUsernames ? "1" : "0", true);
#if LOOLWSD_ANONYMIZE_FILENAMES
AnonymizeFilenames = true;
#else
AnonymizeFilenames = getConfigValue<bool>(conf, "logging.anonymize.filenames", false);
#endif
- setenv("LOOL_ANONYMIZE_FILENAMES", AnonymizeFilenames ? "1" : "0", true);
+ if (AnonymizeFilenames)
+ setenv("LOOL_ANONYMIZE_FILENAMES", AnonymizeFilenames ? "1" : "0", true);
if (AnonymizeFilenames || AnonymizeUsernames)
{
diff --git a/wsd/LOOLWSD.hpp b/wsd/LOOLWSD.hpp
index 5d6ec23b0..1c1dad34f 100644
--- a/wsd/LOOLWSD.hpp
+++ b/wsd/LOOLWSD.hpp
@@ -66,6 +66,7 @@ public:
static std::string LogLevel;
static bool AnonymizeFilenames;
static bool AnonymizeUsernames;
+ static std::string ObfuscatedUserId;
static std::atomic<unsigned> NumConnections;
static bool TileCachePersistent;
static std::unique_ptr<TraceFileWriter> TraceDumper;
@@ -145,10 +146,14 @@ public:
return AnonymizeFilenames ? Util::anonymizeUrl(url) : url;
}
- /// Anonymize usernames.
+ /// Anonymize user names and IDs.
+ /// Will use the Obfuscated User ID if one is provied via WOPI.
static std::string anonymizeUsername(const std::string& username)
{
- return AnonymizeUsernames ? Util::anonymize(username) : username;
+ if (AnonymizeUsernames)
+ return !ObfuscatedUserId.empty() ? ObfuscatedUserId : Util::anonymize(username);
+
+ return username;
}
int innerMain();
diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp
index 06eac803a..7eb03758c 100644
--- a/wsd/Storage.cpp
+++ b/wsd/Storage.cpp
@@ -437,7 +437,6 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
Poco::Net::HTTPResponse response;
std::istream& rs = psession->receiveResponse(response);
-
callDuration = (std::chrono::steady_clock::now() - startTime);
Log::StreamLogger logger = Log::trace();
@@ -473,6 +472,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
std::string ownerId;
std::string userId;
std::string userName;
+ std::string obfuscatedUserId;
std::string userExtraInfo;
std::string watermarkText;
bool canWrite = false;
@@ -502,12 +502,15 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
// Anonymize key values.
if (LOOLWSD::AnonymizeFilenames || LOOLWSD::AnonymizeUsernames)
{
+ JsonUtil::findJSONValue(object, "ObfuscatedUserId", obfuscatedUserId, false);
+
// Set anonymized version of the above fields before logging.
// Note: anonymization caches the result, so we don't need to store here.
if (LOOLWSD::AnonymizeFilenames)
object->set("BaseFileName", LOOLWSD::anonymizeUrl(filename));
- if (LOOLWSD::AnonymizeUsernames)
+ // If obfuscatedUserId is provided, then don't log the originals and use it.
+ if (LOOLWSD::AnonymizeUsernames && obfuscatedUserId.empty())
{
object->set("OwnerId", LOOLWSD::anonymizeUsername(ownerId));
object->set("UserId", LOOLWSD::anonymizeUsername(userId));
@@ -519,6 +522,8 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
wopiResponse = oss.str();
// Remove them for performance reasons; they aren't needed anymore.
+ object->remove("ObfuscatedUserId");
+
if (LOOLWSD::AnonymizeFilenames)
object->remove("BaseFileName");
@@ -570,7 +575,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
_fileInfo = FileInfo({filename, ownerId, modifiedTime, size});
return std::unique_ptr<WopiStorage::WOPIFileInfo>(new WOPIFileInfo(
- {userId, userName, userExtraInfo, watermarkText, canWrite,
+ {userId, obfuscatedUserId, userName, userExtraInfo, watermarkText, canWrite,
postMessageOrigin, hidePrintOption, hideSaveOption, hideExportOption,
enableOwnerTermination, disablePrint, disableExport, disableCopy,
disableInactiveMessages, userCanNotWriteRelative,
@@ -640,7 +645,7 @@ std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth)
return Poco::Path(_jailPath, _fileInfo._filename).toString();
}
}
- catch(const Poco::Exception& pexc)
+ catch (const Poco::Exception& pexc)
{
LOG_ERR("Cannot load document from WOPI storage uri [" + uriAnonym + "]. Error: " <<
pexc.displayText() << (pexc.nested() ? " (" + pexc.nested()->displayText() + ")" : ""));
@@ -824,7 +829,7 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization&
}
}
}
- catch(const Poco::Exception& pexc)
+ catch (const Poco::Exception& pexc)
{
LOG_ERR("Cannot save file to WOPI storage uri [" << uriAnonym << "]. Error: " <<
pexc.displayText() << (pexc.nested() ? " (" + pexc.nested()->displayText() + ")" : ""));
diff --git a/wsd/Storage.hpp b/wsd/Storage.hpp
index c23ed7352..1e9544c2e 100644
--- a/wsd/Storage.hpp
+++ b/wsd/Storage.hpp
@@ -218,14 +218,14 @@ public:
class LocalFileInfo
{
public:
- LocalFileInfo(const std::string& userid,
+ LocalFileInfo(const std::string& userId,
const std::string& username)
- : _userid(userid),
+ : _userId(userId),
_username(username)
{
}
- std::string _userid;
+ std::string _userId;
std::string _username;
};
@@ -269,6 +269,7 @@ public:
};
WOPIFileInfo(const std::string& userid,
+ const std::string& obfuscatedUserId,
const std::string& username,
const std::string& userExtraInfo,
const std::string& watermarkText,
@@ -287,7 +288,8 @@ public:
const TriState disableChangeTrackingRecord,
const TriState hideChangeTrackingControls,
const std::chrono::duration<double> callDuration)
- : _userid(userid),
+ : _userId(userid),
+ _obfuscatedUserId(obfuscatedUserId),
_username(username),
_watermarkText(watermarkText),
_userCanWrite(userCanWrite),
@@ -310,7 +312,9 @@ public:
}
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list