diff options
author | Peter Powell <petpow@saberuk.com> | 2019-06-07 10:14:54 +0100 |
---|---|---|
committer | Peter Powell <petpow@saberuk.com> | 2019-06-07 10:44:20 +0100 |
commit | 8e734ee8a1a562be6bfde7fff7d7c8446179c039 (patch) | |
tree | 2b131294e69aecc8691efe6ee7e74efbb43436b7 | |
parent | 1e60f38babe109dd69a5f668dbb34680f4007b98 (diff) |
Validate the exemptchanops parameter better and check permissions.
Closes #1055.
-rw-r--r-- | src/modules/m_exemptchanops.cpp | 69 |
1 files changed, 53 insertions, 16 deletions
diff --git a/src/modules/m_exemptchanops.cpp b/src/modules/m_exemptchanops.cpp index 61b20fc9b..7a40063fc 100644 --- a/src/modules/m_exemptchanops.cpp +++ b/src/modules/m_exemptchanops.cpp @@ -31,21 +31,61 @@ class ExemptChanOps : public ListModeBase { } + static PrefixMode* FindMode(const std::string& mode) + { + if (mode.length() == 1) + return ServerInstance->Modes->FindPrefixMode(mode[0]); + + ModeHandler* mh = ServerInstance->Modes->FindMode(mode, MODETYPE_CHANNEL); + return mh ? mh->IsPrefixMode() : NULL; + } + + static bool ParseEntry(const std::string& entry, std::string& restriction, std::string& prefix) + { + // The entry must be in the format <restriction>:<prefix>. + std::string::size_type colon = entry.find(':'); + if (colon == std::string::npos || colon == entry.length()-1) + return false; + + restriction.assign(entry, 0, colon); + prefix.assign(entry, colon + 1); + return true; + } + + ModResult AccessCheck(User* source, Channel* channel, std::string& parameter, bool adding) CXX11_OVERRIDE + { + std::string restriction; + std::string prefix; + if (!ParseEntry(parameter, restriction, prefix)) + return MOD_RES_PASSTHRU; + + PrefixMode* pm = FindMode(prefix); + if (!pm) + return MOD_RES_PASSTHRU; + + if (channel->GetPrefixValue(source) >= pm->GetLevelRequired(adding)) + return MOD_RES_PASSTHRU; + + source->WriteNumeric(ERR_CHANOPRIVSNEEDED, channel->name, InspIRCd::Format("You must be able to %s mode %c (%s) to %s a restriction containing it", + adding ? "set" : "unset", pm->GetModeChar(), pm->name.c_str(), adding ? "add" : "remove")); + return MOD_RES_DENY; + } + bool ValidateParam(User* user, Channel* chan, std::string& word) CXX11_OVERRIDE { - std::string::size_type p = word.find(':'); - if (p == std::string::npos) + std::string restriction; + std::string prefix; + if (!ParseEntry(word, restriction, prefix)) { user->WriteNumeric(Numerics::InvalidModeParameter(chan, this, word, "Invalid exemptchanops entry, format is <restriction>:<prefix>")); return false; } - std::string restriction(word, 0, p); // If there is a '-' in the restriction string ignore it and everything after it // to support "auditorium-vis" and "auditorium-see" in m_auditorium - p = restriction.find('-'); - if (p != std::string::npos) - restriction.erase(p); + std::string::size_type dash = restriction.find('-'); + if (dash != std::string::npos) + restriction.erase(dash); if (!ServerInstance->Modes->FindMode(restriction, MODETYPE_CHANNEL)) { @@ -53,6 +93,12 @@ class ExemptChanOps : public ListModeBase return false; } + if (prefix != "*" && !FindMode(prefix)) + { + user->WriteNumeric(Numerics::InvalidModeParameter(chan, this, word, "Unknown prefix mode")); + return false; + } + return true; } }; @@ -67,15 +113,6 @@ class ExemptHandler : public CheckExemption::EventListener { } - PrefixMode* FindMode(const std::string& mid) - { - if (mid.length() == 1) - return ServerInstance->Modes->FindPrefixMode(mid[0]); - - ModeHandler* mh = ServerInstance->Modes->FindMode(mid, MODETYPE_CHANNEL); - return mh ? mh->IsPrefixMode() : NULL; - } - ModResult OnCheckExemption(User* user, Channel* chan, const std::string& restriction) CXX11_OVERRIDE { unsigned int mypfx = chan->GetPrefixValue(user); @@ -95,7 +132,7 @@ class ExemptHandler : public CheckExemption::EventListener } } - PrefixMode* mh = FindMode(minmode); + PrefixMode* mh = ExemptChanOps::FindMode(minmode); if (mh && mypfx >= mh->GetPrefixRank()) return MOD_RES_ALLOW; if (mh || minmode == "*") |