*/
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)
#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))
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]);
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)
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)
{
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)
return CMD_SUCCESS;
}
+
+bool CommandQline::NickMatcher::Check(User* user, const std::string& nick) const
+{
+ return InspIRCd::Match(user->nick, nick);
+}
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]);
return CMD_SUCCESS;
}
+
+bool CommandZline::IPMatcher::Check(User* user, const std::string& ip) const
+{
+ return InspIRCd::Match(user->GetIPString(), ip, ascii_case_insensitive_map);
+}
#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;
#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
*/
class CommandQline : public Command
{
+ class NickMatcher : public InsaneBan::Matcher<NickMatcher>
+ {
+ public:
+ bool Check(User* user, const std::string& mask) const;
+ };
+
public:
/** Constructor for qline.
*/
*/
class CommandZline : public Command
{
+ class IPMatcher : public InsaneBan::Matcher<IPMatcher>
+ {
+ public:
+ bool Check(User* user, const std::string& mask) const;
+ };
+
public:
/** Constructor for zline.
*/