diff options
-rw-r--r-- | include/inspircd.h | 21 | ||||
-rw-r--r-- | src/commands.cpp | 92 | ||||
-rw-r--r-- | src/coremods/core_xline/cmd_eline.cpp | 3 | ||||
-rw-r--r-- | src/coremods/core_xline/cmd_gline.cpp | 3 | ||||
-rw-r--r-- | src/coremods/core_xline/cmd_kline.cpp | 3 | ||||
-rw-r--r-- | src/coremods/core_xline/cmd_qline.cpp | 8 | ||||
-rw-r--r-- | src/coremods/core_xline/cmd_zline.cpp | 8 | ||||
-rw-r--r-- | src/coremods/core_xline/core_xline.cpp | 29 | ||||
-rw-r--r-- | src/coremods/core_xline/core_xline.h | 56 |
9 files changed, 105 insertions, 118 deletions
diff --git a/include/inspircd.h b/include/inspircd.h index 930514169..d1a457cf3 100644 --- a/include/inspircd.h +++ b/include/inspircd.h @@ -571,27 +571,6 @@ class CoreExport InspIRCd */ void Rehash(const std::string& uuid = ""); - /** Check if the given nickmask matches too many users, send errors to the given user - * @param nick A nickmask to match against - * @param user A user to send error text to - * @return True if the nick matches too many users - */ - bool NickMatchesEveryone(const std::string &nick, User* user); - - /** Check if the given IP mask matches too many users, send errors to the given user - * @param ip An ipmask to match against - * @param user A user to send error text to - * @return True if the ip matches too many users - */ - bool IPMatchesEveryone(const std::string &ip, User* user); - - /** Check if the given hostmask matches too many users, send errors to the given user - * @param mask A hostmask to match against - * @param user A user to send error text to - * @return True if the host matches too many users - */ - bool HostMatchesEveryone(const std::string &mask, User* user); - /** Calculate a duration in seconds from a string in the form 1y2w3d4h6m5s * @param str A string containing a time in the form 1y2w3d4h6m5s * (one year, two weeks, three days, four hours, six minutes and five seconds) diff --git a/src/commands.cpp b/src/commands.cpp index 35aada548..d5a89c086 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -25,98 +25,6 @@ #include "xline.h" #include "command_parse.h" -/* All other ircds when doing this check usually just look for a string of *@* or *. We're smarter than that, though. */ - -bool InspIRCd::HostMatchesEveryone(const std::string &mask, User* user) -{ - long matches = 0; - - ConfigTag* insane = Config->ConfValue("insane"); - - if (insane->getBool("hostmasks")) - return false; - - float itrigger = insane->getFloat("trigger", 95.5); - - for (user_hash::iterator u = this->Users->clientlist->begin(); u != this->Users->clientlist->end(); u++) - { - if ((InspIRCd::Match(u->second->MakeHost(), mask, ascii_case_insensitive_map)) || - (InspIRCd::Match(u->second->MakeHostIP(), mask, ascii_case_insensitive_map))) - { - matches++; - } - } - - if (!matches) - return false; - - float percent = ((float)matches / (float)this->Users->clientlist->size()) * 100; - if (percent > itrigger) - { - SNO->WriteToSnoMask('a', "\2WARNING\2: %s tried to set a G/K/E line mask of %s, which covers %.2f%% of the network!",user->nick.c_str(),mask.c_str(),percent); - return true; - } - return false; -} - -bool InspIRCd::IPMatchesEveryone(const std::string &ip, User* user) -{ - long matches = 0; - - ConfigTag* insane = Config->ConfValue("insane"); - - if (insane->getBool("ipmasks")) - return false; - - float itrigger = insane->getFloat("trigger", 95.5); - - for (user_hash::iterator u = this->Users->clientlist->begin(); u != this->Users->clientlist->end(); u++) - { - if (InspIRCd::Match(u->second->GetIPString(), ip, ascii_case_insensitive_map)) - matches++; - } - - if (!matches) - return false; - - float percent = ((float)matches / (float)this->Users->clientlist->size()) * 100; - if (percent > itrigger) - { - SNO->WriteToSnoMask('a', "\2WARNING\2: %s tried to set a Z line mask of %s, which covers %.2f%% of the network!",user->nick.c_str(),ip.c_str(),percent); - return true; - } - return false; -} - -bool InspIRCd::NickMatchesEveryone(const std::string &nick, User* user) -{ - long matches = 0; - - ConfigTag* insane = Config->ConfValue("insane"); - - if (insane->getBool("nickmasks")) - return false; - - float itrigger = insane->getFloat("trigger", 95.5); - - for (user_hash::iterator u = this->Users->clientlist->begin(); u != this->Users->clientlist->end(); u++) - { - if (InspIRCd::Match(u->second->nick, nick)) - matches++; - } - - if (!matches) - return false; - - float percent = ((float)matches / (float)this->Users->clientlist->size()) * 100; - if (percent > itrigger) - { - SNO->WriteToSnoMask('a', "\2WARNING\2: %s tried to set a Q line mask of %s, which covers %.2f%% of the network!",user->nick.c_str(),nick.c_str(),percent); - return true; - } - return false; -} - CmdResult SplitCommand::Handle(const std::vector<std::string>& parms, User* u) { if (IS_LOCAL(u)) diff --git a/src/coremods/core_xline/cmd_eline.cpp b/src/coremods/core_xline/cmd_eline.cpp index c92bed25f..26b49894b 100644 --- a/src/coremods/core_xline/cmd_eline.cpp +++ b/src/coremods/core_xline/cmd_eline.cpp @@ -54,7 +54,8 @@ CmdResult CommandEline::Handle (const std::vector<std::string>& parameters, User return CMD_FAILURE; } - if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user)) + InsaneBan::IPHostMatcher matcher; + if (InsaneBan::MatchesEveryone(ih.first+"@"+ih.second, matcher, user, "E", "hostmasks")) return CMD_FAILURE; unsigned long duration = InspIRCd::Duration(parameters[1]); diff --git a/src/coremods/core_xline/cmd_gline.cpp b/src/coremods/core_xline/cmd_gline.cpp index 44b2192b5..3f042c366 100644 --- a/src/coremods/core_xline/cmd_gline.cpp +++ b/src/coremods/core_xline/cmd_gline.cpp @@ -55,7 +55,8 @@ CmdResult CommandGline::Handle (const std::vector<std::string>& parameters, User return CMD_FAILURE; } - if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user)) + InsaneBan::IPHostMatcher matcher; + if (InsaneBan::MatchesEveryone(ih.first+"@"+ih.second, matcher, user, "G", "hostmasks")) return CMD_FAILURE; else if (target.find('!') != std::string::npos) diff --git a/src/coremods/core_xline/cmd_kline.cpp b/src/coremods/core_xline/cmd_kline.cpp index 686f4b9b3..50ab88398 100644 --- a/src/coremods/core_xline/cmd_kline.cpp +++ b/src/coremods/core_xline/cmd_kline.cpp @@ -55,7 +55,8 @@ CmdResult CommandKline::Handle (const std::vector<std::string>& parameters, User return CMD_FAILURE; } - if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user)) + InsaneBan::IPHostMatcher matcher; + if (InsaneBan::MatchesEveryone(ih.first+"@"+ih.second, matcher, user, "K", "hostmasks")) return CMD_FAILURE; if (target.find('!') != std::string::npos) diff --git a/src/coremods/core_xline/cmd_qline.cpp b/src/coremods/core_xline/cmd_qline.cpp index 24e8581b6..955efeaf0 100644 --- a/src/coremods/core_xline/cmd_qline.cpp +++ b/src/coremods/core_xline/cmd_qline.cpp @@ -35,7 +35,8 @@ CmdResult CommandQline::Handle (const std::vector<std::string>& parameters, User { if (parameters.size() >= 3) { - if (ServerInstance->NickMatchesEveryone(parameters[0],user)) + NickMatcher matcher; + if (InsaneBan::MatchesEveryone(parameters[0], matcher, user, "Q", "nickmasks")) return CMD_FAILURE; if (parameters[0].find('@') != std::string::npos || parameters[0].find('!') != std::string::npos || parameters[0].find('.') != std::string::npos) @@ -82,3 +83,8 @@ CmdResult CommandQline::Handle (const std::vector<std::string>& parameters, User return CMD_SUCCESS; } + +bool CommandQline::NickMatcher::Check(User* user, const std::string& nick) const +{ + return InspIRCd::Match(user->nick, nick); +} diff --git a/src/coremods/core_xline/cmd_zline.cpp b/src/coremods/core_xline/cmd_zline.cpp index 5eeebf175..859be1004 100644 --- a/src/coremods/core_xline/cmd_zline.cpp +++ b/src/coremods/core_xline/cmd_zline.cpp @@ -59,7 +59,8 @@ CmdResult CommandZline::Handle (const std::vector<std::string>& parameters, User ipaddr++; } - if (ServerInstance->IPMatchesEveryone(ipaddr,user)) + IPMatcher matcher; + if (InsaneBan::MatchesEveryone(ipaddr, matcher, user, "Z", "ipmasks")) return CMD_FAILURE; unsigned long duration = InspIRCd::Duration(parameters[1]); @@ -100,3 +101,8 @@ CmdResult CommandZline::Handle (const std::vector<std::string>& parameters, User return CMD_SUCCESS; } + +bool CommandZline::IPMatcher::Check(User* user, const std::string& ip) const +{ + return InspIRCd::Match(user->GetIPString(), ip, ascii_case_insensitive_map); +} diff --git a/src/coremods/core_xline/core_xline.cpp b/src/coremods/core_xline/core_xline.cpp index dcd85b4f6..94183d829 100644 --- a/src/coremods/core_xline/core_xline.cpp +++ b/src/coremods/core_xline/core_xline.cpp @@ -20,6 +20,35 @@ #include "inspircd.h" #include "core_xline.h" +bool InsaneBan::MatchesEveryone(const std::string& mask, MatcherBase& test, User* user, const char* bantype, const char* confkey) +{ + ConfigTag* insane = ServerInstance->Config->ConfValue("insane"); + + if (insane->getBool(confkey)) + return false; + + float itrigger = insane->getFloat("trigger", 95.5); + + long matches = test.Run(mask); + + if (!matches) + return false; + + float percent = ((float)matches / (float)ServerInstance->Users->clientlist->size()) * 100; + if (percent > itrigger) + { + ServerInstance->SNO->WriteToSnoMask('a', "\2WARNING\2: %s tried to set a %s-line mask of %s, which covers %.2f%% of the network!", user->nick.c_str(), bantype, mask.c_str(), percent); + return true; + } + return false; +} + +bool InsaneBan::IPHostMatcher::Check(User* user, const std::string& mask) const +{ + return ((InspIRCd::Match(user->MakeHost(), mask, ascii_case_insensitive_map)) || + (InspIRCd::Match(user->MakeHostIP(), mask, ascii_case_insensitive_map))); +} + class CoreModXLine : public Module { CommandEline cmdeline; diff --git a/src/coremods/core_xline/core_xline.h b/src/coremods/core_xline/core_xline.h index c2e171410..6101d79bf 100644 --- a/src/coremods/core_xline/core_xline.h +++ b/src/coremods/core_xline/core_xline.h @@ -21,6 +21,50 @@ #include "inspircd.h" +class InsaneBan +{ + public: + class MatcherBase + { + public: + virtual long Run(const std::string& mask) = 0; + }; + + template <typename T> + class Matcher : public MatcherBase + { + public: + long Run(const std::string& mask) + { + long matches = 0; + const T* c = static_cast<T*>(this); + const user_hash& users = *ServerInstance->Users->clientlist; + for (user_hash::const_iterator i = users.begin(); i != users.end(); ++i) + { + if (c->Check(i->second, mask)) + matches++; + } + return matches; + } + }; + + class IPHostMatcher : public Matcher<IPHostMatcher> + { + public: + bool Check(User* user, const std::string& mask) const; + }; + + /** Check if the given mask matches too many users according to the config, send an announcement if yes + * @param mask A mask to match against + * @param test The test that determines if a user matches the mask or not + * @param user A user whose nick will be included in the announcement if one is made + * @param bantype Type of the ban being set, will be used in the announcement if one is made + * @param confkey Name of the config key (inside the insane tag) which if false disables any checking + * @return True if the given mask matches too many users, false if not + */ + static bool MatchesEveryone(const std::string& mask, MatcherBase& test, User* user, const char* bantype, const char* confkey); +}; + /** Handle /ELINE. */ class CommandEline : public Command @@ -76,6 +120,12 @@ class CommandKline : public Command */ class CommandQline : public Command { + class NickMatcher : public InsaneBan::Matcher<NickMatcher> + { + public: + bool Check(User* user, const std::string& mask) const; + }; + public: /** Constructor for qline. */ @@ -94,6 +144,12 @@ class CommandQline : public Command */ class CommandZline : public Command { + class IPMatcher : public InsaneBan::Matcher<IPMatcher> + { + public: + bool Check(User* user, const std::string& mask) const; + }; + public: /** Constructor for zline. */ |