summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorAdam- <Adam-@5417fbe8-f217-4b02-8779-1006273d7864>2009-10-30 01:04:13 +0000
committerAdam- <Adam-@5417fbe8-f217-4b02-8779-1006273d7864>2009-10-30 01:04:13 +0000
commit6a9fa9f4d2ead592eb51a014491ce3aaee2029e8 (patch)
tree454479f2c8ef69a52e461416be42fd94d8b15955 /src/core
parent5fc268b7509f20cbf1243b99f2669033b93db00e (diff)
Rewrote all of the defcon code, and moved most of it to os_defcon. This fixes defcon to have the ability to use modes introduced to Anope at a later time than on startup (eg, from the IRCd), amongst other things
git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@2597 5417fbe8-f217-4b02-8779-1006273d7864
Diffstat (limited to 'src/core')
-rw-r--r--src/core/cs_register.c6
-rw-r--r--src/core/cs_set.c5
-rw-r--r--src/core/ms_sendall.c5
-rw-r--r--src/core/ms_staff.c5
-rw-r--r--src/core/ns_group.c5
-rw-r--r--src/core/ns_register.c6
-rw-r--r--src/core/os_defcon.c436
7 files changed, 419 insertions, 49 deletions
diff --git a/src/core/cs_register.c b/src/core/cs_register.c
index 89985fb93..62737d4aa 100644
--- a/src/core/cs_register.c
+++ b/src/core/cs_register.c
@@ -41,12 +41,6 @@ class CommandCSRegister : public Command
return MOD_CONT;
}
- if (checkDefCon(DEFCON_NO_NEW_CHANNELS))
- {
- notice_lang(s_ChanServ, u, OPER_DEFCON_DENIED);
- return MOD_CONT;
- }
-
if (*chan == '&')
notice_lang(s_ChanServ, u, CHAN_REGISTER_NOT_LOCAL);
else if (*chan != '#')
diff --git a/src/core/cs_set.c b/src/core/cs_set.c
index 0036a752a..716144d2c 100644
--- a/src/core/cs_set.c
+++ b/src/core/cs_set.c
@@ -193,11 +193,6 @@ class CommandCSSet : public Command
ChannelMode *cm;
ChannelModeParam *cmp;
- if (checkDefCon(DEFCON_NO_MLOCK_CHANGE)) {
- notice_lang(s_ChanServ, u, OPER_DEFCON_DENIED);
- return MOD_CONT;
- }
-
ci->ClearMLock();
if (ModeManager::FindChannelModeByName(CMODE_REGISTERED))
diff --git a/src/core/ms_sendall.c b/src/core/ms_sendall.c
index b9636f5fb..56dfbf1c2 100644
--- a/src/core/ms_sendall.c
+++ b/src/core/ms_sendall.c
@@ -33,11 +33,6 @@ class CommandMSSendAll : public Command
notice_lang(s_MemoServ, u, MEMO_SEND_DISABLED);
return MOD_CONT;
}
- else if (checkDefCon(DEFCON_NO_NEW_MEMOS))
- {
- notice_lang(s_MemoServ, u, OPER_DEFCON_DENIED);
- return MOD_CONT;
- }
for (i = 0; i < 1024; ++i)
{
diff --git a/src/core/ms_staff.c b/src/core/ms_staff.c
index af2e510f4..e472a0108 100644
--- a/src/core/ms_staff.c
+++ b/src/core/ms_staff.c
@@ -33,11 +33,6 @@ class CommandMSStaff : public Command
notice_lang(s_MemoServ, u, MEMO_SEND_DISABLED);
return MOD_CONT;
}
- else if (checkDefCon(DEFCON_NO_NEW_MEMOS))
- {
- notice_lang(s_MemoServ, u, OPER_DEFCON_DENIED);
- return MOD_CONT;
- }
for (i = 0; i < 1024; ++i)
{
diff --git a/src/core/ns_group.c b/src/core/ns_group.c
index ec00ec69d..47499bd75 100644
--- a/src/core/ns_group.c
+++ b/src/core/ns_group.c
@@ -43,11 +43,6 @@ class CommandNSGroup : public Command
notice_lang(s_NickServ, u, NICK_GROUP_DISABLED);
return MOD_CONT;
}
- if (checkDefCon(DEFCON_NO_NEW_NICKS))
- {
- notice_lang(s_NickServ, u, OPER_DEFCON_DENIED);
- return MOD_CONT;
- }
if (!ircdproto->IsNickValid(u->nick))
{
diff --git a/src/core/ns_register.c b/src/core/ns_register.c
index 2e580e61c..f0d4c693f 100644
--- a/src/core/ns_register.c
+++ b/src/core/ns_register.c
@@ -201,12 +201,6 @@ class CommandNSRegister : public CommandNSConfirm
return MOD_CONT;
}
- if (checkDefCon(DEFCON_NO_NEW_NICKS))
- {
- notice_lang(s_NickServ, u, OPER_DEFCON_DENIED);
- return MOD_CONT;
- }
-
if (!is_oper(u) && NickRegDelay && time(NULL) - u->my_signon < NickRegDelay)
{
notice_lang(s_NickServ, u, NICK_REG_DELAY, NickRegDelay);
diff --git a/src/core/os_defcon.c b/src/core/os_defcon.c
index 4227bc458..426fac779 100644
--- a/src/core/os_defcon.c
+++ b/src/core/os_defcon.c
@@ -16,6 +16,44 @@
#include "module.h"
void defcon_sendlvls(User *u);
+void runDefCon();
+void defconParseModeString(const char *str);
+void resetDefCon(int level);
+static char *defconReverseModes(const char *modes);
+class DefConTimeout;
+static DefConTimeout *timeout;
+
+class DefConTimeout : public Timer
+{
+ int level;
+
+ public:
+ DefConTimeout(int newlevel) : Timer(DefConTimeOut), level(newlevel) { }
+
+ void Tick(time_t)
+ {
+ if (DefConLevel != level)
+ {
+ DefConLevel = level;
+ FOREACH_MOD(I_OnDefconLevel, OnDefconLevel(level));
+ alog("Defcon level timeout, returning to lvl %d", level);
+ ircdproto->SendGlobops(s_OperServ, getstring(OPER_DEFCON_WALL), s_OperServ, level);
+
+ if (GlobalOnDefcon)
+ {
+ if (DefConOffMessage)
+ oper_global(NULL, "%s", DefConOffMessage);
+ else
+ oper_global(NULL, getstring(DEFCON_GLOBAL), DefConLevel);
+
+ if (GlobalOnDefconMore && !DefConOffMessage)
+ oper_global(NULL, "%s", DefconMessage);
+ }
+
+ runDefCon();
+ }
+ }
+};
class CommandOSDEFCON : public Command
{
@@ -30,12 +68,6 @@ class CommandOSDEFCON : public Command
int newLevel = 0;
const char *langglobal = getstring(DEFCON_GLOBAL);
- if (!DefConLevel) /* If we dont have a .conf setting! */
- {
- notice_lang(s_OperServ, u, OPER_DEFCON_NO_CONF);
- return MOD_CONT;
- }
-
if (!lvl)
{
notice_lang(s_OperServ, u, OPER_DEFCON_CHANGED, DefConLevel);
@@ -52,7 +84,15 @@ class CommandOSDEFCON : public Command
FOREACH_MOD(I_OnDefconLevel, OnDefconLevel(newLevel));
- DefContimer = time(NULL);
+ if (timeout)
+ {
+ TimerManager::DelTimer(timeout);
+ timeout = NULL;
+ }
+
+ if (DefConTimeOut)
+ timeout = new DefConTimeout(5);
+
notice_lang(s_OperServ, u, OPER_DEFCON_CHANGED, DefConLevel);
defcon_sendlvls(u);
alog("Defcon level changed to %d by Oper %s", newLevel, u->nick);
@@ -97,12 +137,209 @@ class OSDEFCON : public Module
this->SetVersion("$Id$");
this->SetType(CORE);
+ if (!DefConLevel)
+ {
+ throw ModuleException("Invalid configuration settings");
+ }
+
+ Implementation i[] = { I_OnPreUserConnect, I_OnChannelModeSet, I_OnChannelModeUnset, I_OnPreCommandRun, I_OnPreCommand, I_OnUserConnect, I_OnChannelModeAdd, I_OnChannelCreate };
+ ModuleManager::Attach(i, this, 8);
+
this->AddCommand(OPERSERV, new CommandOSDEFCON());
+
+ defconParseModeString(DefConChanModes);
}
+
void OperServHelp(User *u)
{
notice_lang(s_OperServ, u, OPER_HELP_CMD_DEFCON);
}
+
+ EventReturn OnPreUserConnect(User *u)
+ {
+ std::string mask;
+
+ if (u && is_sync(u->server) && CheckDefCon(DEFCON_AKILL_NEW_CLIENTS) && !is_ulined(u->server->name))
+ {
+ if (CheckDefCon(DEFCON_AKILL_NEW_CLIENTS))
+ {
+ mask = "*@" + std::string(u->host);
+ alog("DEFCON: adding akill for %s", mask.c_str());
+ add_akill(NULL, mask.c_str(), s_OperServ,
+ time(NULL) + DefConAKILL,
+ DefConAkillReason ? DefConAkillReason :
+ "DEFCON AKILL");
+ }
+
+ if (CheckDefCon(DEFCON_NO_NEW_CLIENTS) || CheckDefCon(DEFCON_AKILL_NEW_CLIENTS))
+ kill_user(s_OperServ, u->nick, DefConAkillReason);
+
+ return EVENT_STOP;
+ }
+
+ return EVENT_CONTINUE;
+ }
+
+ void OnChannelModeSet(Channel *c, ChannelModeName Name)
+ {
+ ChannelMode *cm = ModeManager::FindChannelModeByName(Name);
+
+ if (CheckDefCon(DEFCON_FORCE_CHAN_MODES) && cm && DefConModesCI.HasMLock(Name, false))
+ {
+ c->RemoveMode(Name);
+ ircdproto->SendMode(findbot(s_OperServ), c->name, "-%c", cm->ModeChar);
+ }
+ }
+
+ void OnChannelModeUnset(Channel *c, ChannelModeName Name)
+ {
+ ChannelMode *cm = ModeManager::FindChannelModeByName(Name);
+
+ if (CheckDefCon(DEFCON_FORCE_CHAN_MODES) && cm && DefConModesCI.HasMLock(Name, true))
+ {
+ std::string param;
+ DefConModesCI.GetParam(Name, &param);
+
+ c->SetMode(Name);
+
+ std::string buf = "+" + std::string(&cm->ModeChar);
+ if (!param.empty())
+ buf += " " + param;
+ ircdproto->SendMode(findbot(s_OperServ), c->name, buf.c_str());
+ }
+ }
+
+ EventReturn OnPreCommandRun(const char *service, User *u, const char *cmd, Command *c)
+ {
+ if (!c)
+ {
+ if (CheckDefCon(DEFCON_SILENT_OPER_ONLY) && !is_oper(u))
+ return EVENT_STOP;
+ }
+ if ((CheckDefCon(DEFCON_OPER_ONLY) || CheckDefCon(DEFCON_SILENT_OPER_ONLY)) && !is_oper(u))
+ {
+ if (!CheckDefCon(DEFCON_SILENT_OPER_ONLY))
+ {
+ notice_lang(service, u, OPER_DEFCON_DENIED);
+ }
+
+ return EVENT_STOP;
+ }
+
+ return EVENT_CONTINUE;
+ }
+
+ EventReturn OnPreCommand(User *u, const std::string &service, const ci::string &command, const std::vector<ci::string> &params)
+ {
+ if (service == s_NickServ)
+ {
+ if (command == "SET")
+ {
+ if (!params.empty() && params[0] == "MLOCK")
+ {
+ if (CheckDefCon(DEFCON_NO_MLOCK_CHANGE))
+ {
+ notice_lang(s_ChanServ, u, OPER_DEFCON_DENIED);
+ return EVENT_STOP;
+ }
+ }
+ }
+ else if (command == "REGISTER" || command == "GROUP")
+ {
+ if (CheckDefCon(DEFCON_NO_NEW_NICKS))
+ {
+ notice_lang(s_NickServ, u, OPER_DEFCON_DENIED);
+ return EVENT_STOP;
+ }
+ }
+ }
+ else if (service == s_ChanServ)
+ {
+ if (command == "REGISTER")
+ {
+ if (CheckDefCon(DEFCON_NO_NEW_CHANNELS))
+ {
+ notice_lang(s_ChanServ, u, OPER_DEFCON_DENIED);
+ return EVENT_STOP;
+ }
+ }
+ }
+ else if (service == s_MemoServ)
+ {
+ if (command == "SEND" || command == "SENDALL")
+ {
+ if (CheckDefCon(DEFCON_NO_NEW_MEMOS))
+ {
+ notice_lang(s_MemoServ, u, OPER_DEFCON_DENIED);
+ return EVENT_STOP;
+ }
+ }
+ }
+
+ return EVENT_CONTINUE;
+ }
+
+ void OnUserConnect(User *u)
+ {
+ Session *session = findsession(u->host);
+ Exception *exception = find_hostip_exception(u->host, u->hostip);
+
+ if (CheckDefCon(DEFCON_REDUCE_SESSION) && !exception)
+ {
+ if (session && session->count > DefConSessionLimit)
+ {
+ if (SessionLimitExceeded)
+ ircdproto->SendMessage(findbot(s_OperServ), u->nick, SessionLimitExceeded, u->host);
+ if (SessionLimitDetailsLoc)
+ ircdproto->SendMessage(findbot(s_OperServ), u->nick, "%s", SessionLimitDetailsLoc);
+
+ kill_user(s_OperServ, u->nick, "Session limit exceeded");
+ session->hits++;
+ if (MaxSessionKill && session->hits >= MaxSessionKill)
+ {
+ char akillmask[BUFSIZE];
+ snprintf(akillmask, sizeof(akillmask), "*@%s", u->host);
+ add_akill(NULL, akillmask, s_OperServ, time(NULL) + SessionAutoKillExpiry, "Session limit exceeded");
+ ircdproto->SendGlobops(s_OperServ, "Added a temporary AKILL for \2%s\2 due to excessive connections", akillmask);
+ }
+ }
+ }
+ }
+
+ void OnChannelModeAdd(ChannelMode *cm)
+ {
+ if (DefConChanModes)
+ {
+ std::string modes = DefConChanModes;
+
+ if (modes.find(cm->ModeChar) != std::string::npos)
+ {
+ /* New mode has been added to Anope, check to see if defcon
+ * requires it
+ */
+ defconParseModeString(DefConChanModes);
+ }
+ }
+ }
+
+ void OnChannelCreate(Channel *c)
+ {
+ char *myModes;
+ int ac;
+ const char **av;
+
+ if (CheckDefCon(DEFCON_FORCE_CHAN_MODES))
+ {
+ myModes = sstrdup(DefConChanModes);
+ ac = split_buf(myModes, &av, 1);
+
+ ircdproto->SendMode(findbot(s_OperServ), c->name, "%s", DefConChanModes);
+ chan_set_modes(s_OperServ, c, ac, av, 1);
+
+ free(av);
+ delete [] myModes;
+ }
+ }
};
/**
@@ -110,26 +347,191 @@ class OSDEFCON : public Module
**/
void defcon_sendlvls(User *u)
{
- if (checkDefCon(DEFCON_NO_NEW_CHANNELS))
+ if (CheckDefCon(DEFCON_NO_NEW_CHANNELS))
notice_lang(s_OperServ, u, OPER_HELP_DEFCON_NO_NEW_CHANNELS);
- if (checkDefCon(DEFCON_NO_NEW_NICKS))
+ if (CheckDefCon(DEFCON_NO_NEW_NICKS))
notice_lang(s_OperServ, u, OPER_HELP_DEFCON_NO_NEW_NICKS);
- if (checkDefCon(DEFCON_NO_MLOCK_CHANGE))
+ if (CheckDefCon(DEFCON_NO_MLOCK_CHANGE))
notice_lang(s_OperServ, u, OPER_HELP_DEFCON_NO_MLOCK_CHANGE);
- if (checkDefCon(DEFCON_FORCE_CHAN_MODES) && DefConChanModes)
+ if (CheckDefCon(DEFCON_FORCE_CHAN_MODES) && DefConChanModes)
notice_lang(s_OperServ, u, OPER_HELP_DEFCON_FORCE_CHAN_MODES, DefConChanModes);
- if (checkDefCon(DEFCON_REDUCE_SESSION))
+ if (CheckDefCon(DEFCON_REDUCE_SESSION))
notice_lang(s_OperServ, u, OPER_HELP_DEFCON_REDUCE_SESSION, DefConSessionLimit);
- if (checkDefCon(DEFCON_NO_NEW_CLIENTS))
+ if (CheckDefCon(DEFCON_NO_NEW_CLIENTS))
notice_lang(s_OperServ, u, OPER_HELP_DEFCON_NO_NEW_CLIENTS);
- if (checkDefCon(DEFCON_OPER_ONLY))
+ if (CheckDefCon(DEFCON_OPER_ONLY))
notice_lang(s_OperServ, u, OPER_HELP_DEFCON_OPER_ONLY);
- if (checkDefCon(DEFCON_SILENT_OPER_ONLY))
+ if (CheckDefCon(DEFCON_SILENT_OPER_ONLY))
notice_lang(s_OperServ, u, OPER_HELP_DEFCON_SILENT_OPER_ONLY);
- if (checkDefCon(DEFCON_AKILL_NEW_CLIENTS))
+ if (CheckDefCon(DEFCON_AKILL_NEW_CLIENTS))
notice_lang(s_OperServ, u, OPER_HELP_DEFCON_AKILL_NEW_CLIENTS);
- if (checkDefCon(DEFCON_NO_NEW_MEMOS))
+ if (CheckDefCon(DEFCON_NO_NEW_MEMOS))
notice_lang(s_OperServ, u, OPER_HELP_DEFCON_NO_NEW_MEMOS);
}
+void runDefCon()
+{
+ char *newmodes;
+
+ if (CheckDefCon(DEFCON_FORCE_CHAN_MODES))
+ {
+ if (DefConChanModes && !DefConModesSet)
+ {
+ if (DefConChanModes[0] == '+' || DefConChanModes[0] == '-')
+ {
+ alog("DEFCON: setting %s on all chan's", DefConChanModes);
+ DefConModesSet = 1;
+ do_mass_mode(DefConChanModes);
+ }
+ }
+ }
+ else
+ {
+ if (DefConChanModes && (DefConModesSet != 0))
+ {
+ if (DefConChanModes[0] == '+' || DefConChanModes[0] == '-')
+ {
+ DefConModesSet = 0;
+ if ((newmodes = defconReverseModes(DefConChanModes)))
+ {
+ alog("DEFCON: setting %s on all chan's", newmodes);
+ do_mass_mode(newmodes);
+ delete [] newmodes;
+ }
+ }
+ }
+ }
+}
+
+/* Parse the defcon mlock mode string and set the correct global vars.
+ *
+ * @param str mode string to parse
+ * @return 1 if accepted, 0 if failed
+ */
+void defconParseModeString(const char *str)
+{
+ int add = -1; /* 1 if adding, 0 if deleting, -1 if neither */
+ unsigned char mode;
+ ChannelMode *cm;
+ ChannelModeParam *cmp;
+ std::string modes, param;
+
+ if (!str)
+ return;
+
+ spacesepstream ss(str);
+
+ DefConModesCI.ClearMLock();
+ ss.GetToken(modes);
+
+ /* Loop while there are modes to set */
+ for (unsigned i = 0; i < modes.size(); ++i)
+ {
+ mode = modes[i];
+
+ switch (mode)
+ {
+ case '+':
+ add = 1;
+ continue;
+ case '-':
+ add = 0;
+ continue;
+ default:
+ if (add < 0)
+ continue;
+ }
+
+ if ((cm = ModeManager::FindChannelModeByChar(mode)))
+ {
+ if (!cm->CanSet(NULL))
+ {
+ alog("DefConChanModes mode character '%c' cannot be locked", mode);
+ continue;
+ }
+ else if (add)
+ {
+ DefConModesCI.SetMLock(cm->Name, true);
+ DefConModesCI.RemoveMLock(cm->Name, false);
+
+ if (cm->Type == MODE_PARAM)
+ {
+ cmp = static_cast<ChannelModeParam *>(cm);
+
+ if (!ss.GetToken(param))
+ {
+ alog("DefConChanModes mode character '%c' has no parameter while one is expected", mode);
+ continue;
+ }
+
+ if (!cmp->IsValid(param.c_str()))
+ continue;
+
+ DefConModesCI.SetParam(cmp->Name, param);
+ }
+ }
+ else
+ {
+ DefConModesCI.RemoveMLock(cm->Name, true);
+
+ if (DefConModesCI.HasMLock(cm->Name, true))
+ {
+ DefConModesCI.RemoveMLock(cm->Name, true);
+
+ if (cm->Type == MODE_PARAM)
+ {
+ cmp = static_cast<ChannelModeParam *>(cm);
+
+ DefConModesCI.UnsetParam(cmp->Name);
+ }
+ }
+ }
+ }
+ }
+
+ if ((cm = ModeManager::FindChannelModeByName(CMODE_REDIRECT)))
+ {
+ /* We can't mlock +L if +l is not mlocked as well. */
+ if (DefConModesCI.HasMLock(cm->Name, true) && !DefConModesCI.HasMLock(CMODE_LIMIT, true))
+ {
+ DefConModesCI.RemoveMLock(CMODE_REDIRECT, true);
+ DefConModesCI.UnsetParam(CMODE_REDIRECT);
+ alog("DefConChanModes must lock mode +l as well to lock mode +L");
+ }
+ }
+
+ /* Some ircd we can't set NOKNOCK without INVITE */
+ /* So check if we need there is a NOKNOCK MODE and that we need INVITEONLY */
+ if (ircd->knock_needs_i && (cm = ModeManager::FindChannelModeByName(CMODE_NOKNOCK)))
+ {
+ if (DefConModesCI.HasMLock(cm->Name, true) && !DefConModesCI.HasMLock(CMODE_INVITE, true))
+ {
+ DefConModesCI.RemoveMLock(CMODE_NOKNOCK, true);
+ alog("DefConChanModes must lock mode +i as well to lock mode +K");
+ }
+ }
+}
+
+static char *defconReverseModes(const char *modes)
+{
+ char *newmodes = NULL;
+ unsigned i = 0;
+ if (!modes) {
+ return NULL;
+ }
+ if (!(newmodes = new char[strlen(modes) + 1])) {
+ return NULL;
+ }
+ for (i = 0; i < strlen(modes); i++) {
+ if (modes[i] == '+')
+ newmodes[i] = '-';
+ else if (modes[i] == '-')
+ newmodes[i] = '+';
+ else
+ newmodes[i] = modes[i];
+ }
+ newmodes[i] = '\0';
+ return newmodes;
+}
+
MODULE_INIT(OSDEFCON)