diff options
author | Nicolas Werner <nicolas.werner@hotmail.de> | 2023-03-12 03:45:49 +0100 |
---|---|---|
committer | Nicolas Werner <nicolas.werner@hotmail.de> | 2023-03-14 18:16:08 +0100 |
commit | 4bf6e58511562ac699fdc8dc985916d0fcb17094 (patch) | |
tree | 338e0c41152ece1cd34209d25545ab99fdd682bb /src | |
parent | Make via implementation closer to the spec (diff) | |
download | nheko-4bf6e58511562ac699fdc8dc985916d0fcb17094.tar.xz |
Evaluate ACLs when calculating vias
Diffstat (limited to 'src')
-rw-r--r-- | src/Utils.cpp | 54 |
1 files changed, 52 insertions, 2 deletions
diff --git a/src/Utils.cpp b/src/Utils.cpp index 2a0c4673..54bd51ab 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -1273,6 +1273,51 @@ utils::roomVias(const std::string &roomid) auto powerlevels = cache::client()->getStateEvent<mtx::events::state::PowerLevels>(roomid).value_or( mtx::events::StateEvent<mtx::events::state::PowerLevels>{}); + auto acls = cache::client()->getStateEvent<mtx::events::state::ServerAcl>(roomid); + + std::vector<QRegularExpression> allowedServers; + std::vector<QRegularExpression> deniedServers; + + if (acls) { + auto globToRegexp = [](const std::string &globExp) { + auto rawReg = QRegularExpression::escape(QString::fromStdString(globExp)) + .replace("\\*", ".*") + .replace("\\?", "."); + return QRegularExpression(QRegularExpression::anchoredPattern(rawReg), + QRegularExpression::DotMatchesEverythingOption | + QRegularExpression::DontCaptureOption); + }; + + allowedServers.reserve(acls->content.allow.size()); + for (const auto &s : acls->content.allow) + allowedServers.push_back(globToRegexp(s)); + deniedServers.reserve(acls->content.deny.size()); + for (const auto &s : acls->content.deny) + allowedServers.push_back(globToRegexp(s)); + + nhlog::ui()->critical("ACL: {}", nlohmann::json(acls->content).dump(2)); + } + + auto isHostAllowed = [&acls, &allowedServers, &deniedServers](const std::string &host) { + if (!acls) + return true; + + auto url = QUrl::fromEncoded( + "https://" + QByteArray::fromRawData(host.data(), host.size()), QUrl::StrictMode); + if (url.hasQuery() || url.hasFragment()) + return false; + + auto hostname = url.host(); + + for (const auto &d : deniedServers) + if (d.match(hostname).hasMatch()) + return false; + for (const auto &a : allowedServers) + if (a.match(hostname).hasMatch()) + return true; + + return false; + }; std::unordered_set<std::string> users_with_high_pl; std::set<std::string> users_with_high_pl_in_room; @@ -1281,7 +1326,10 @@ utils::roomVias(const std::string &roomid) for (const auto &user : powerlevels.content.users) { if (user.second >= powerlevels.content.events_default && user.second >= powerlevels.content.state_default) { - users_with_high_pl.insert(user.first); + auto host = + mtx::identifiers::parse<mtx::identifiers::User>(user.first).hostname(); + if (isHostAllowed(host)) + users_with_high_pl.insert(user.first); } } @@ -1294,7 +1342,9 @@ utils::roomVias(const std::string &roomid) users_with_high_pl_in_room.insert(m); } - // TODO(Nico): remove acled servers + std::erase_if(usercount_by_server, [&isHostAllowed](const auto &item) { + return !isHostAllowed(item.first); + }); // add the highest powerlevel user auto max_pl_user = std::max_element( |