diff options
Diffstat (limited to 'modules/extra')
-rw-r--r-- | modules/extra/cs_appendtopic.cpp | 14 | ||||
-rw-r--r-- | modules/extra/cs_enforce.cpp | 10 | ||||
-rw-r--r-- | modules/extra/cs_entrymsg.cpp | 12 | ||||
-rw-r--r-- | modules/extra/cs_set_misc.cpp | 16 | ||||
-rw-r--r-- | modules/extra/cs_tban.cpp | 12 | ||||
-rw-r--r-- | modules/extra/db_mysql.cpp | 87 | ||||
-rw-r--r-- | modules/extra/hs_request.cpp | 47 | ||||
-rw-r--r-- | modules/extra/m_alias.cpp | 9 | ||||
-rw-r--r-- | modules/extra/m_dnsbl.cpp | 44 | ||||
-rw-r--r-- | modules/extra/m_helpchan.cpp | 9 | ||||
-rw-r--r-- | modules/extra/m_ldap.cpp | 4 | ||||
-rw-r--r-- | modules/extra/m_ldap_authentication.cpp | 19 | ||||
-rw-r--r-- | modules/extra/m_ldap_oper.cpp | 4 | ||||
-rw-r--r-- | modules/extra/m_mysql.cpp | 4 | ||||
-rw-r--r-- | modules/extra/m_xmlrpc.cpp | 6 | ||||
-rw-r--r-- | modules/extra/m_xmlrpc_main.cpp | 7 | ||||
-rw-r--r-- | modules/extra/ns_maxemail.cpp | 10 | ||||
-rw-r--r-- | modules/extra/ns_set_misc.cpp | 13 | ||||
-rw-r--r-- | modules/extra/os_defcon.cpp | 693 |
19 files changed, 873 insertions, 147 deletions
diff --git a/modules/extra/cs_appendtopic.cpp b/modules/extra/cs_appendtopic.cpp index b02717d92..dc3b40288 100644 --- a/modules/extra/cs_appendtopic.cpp +++ b/modules/extra/cs_appendtopic.cpp @@ -17,8 +17,7 @@ /*************************************************************************/ #include "module.h" - -#define AUTHOR "SGR" +#include "chanserv.h" /* ------------------------------------------------------------ * Name: cs_appendtopic @@ -110,12 +109,15 @@ class CSAppendTopic : public Module public: CSAppendTopic(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) { - me = this; - - this->SetAuthor(AUTHOR); + this->SetAuthor("SGR"); this->SetType(SUPPORTED); - this->AddCommand(ChanServ, &commandcsappendtopic); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + me = this; + + this->AddCommand(chanserv->Bot(), &commandcsappendtopic); } }; diff --git a/modules/extra/cs_enforce.cpp b/modules/extra/cs_enforce.cpp index 3a8e11735..6e39f33f3 100644 --- a/modules/extra/cs_enforce.cpp +++ b/modules/extra/cs_enforce.cpp @@ -14,6 +14,7 @@ */ #include "module.h" +#include "chanserv.h" static Module *me; @@ -217,12 +218,15 @@ class CSEnforce : public Module public: CSEnforce(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) { - me = this; - this->SetAuthor("Anope"); this->SetType(SUPPORTED); - this->AddCommand(ChanServ, &commandcsenforce); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + me = this; + + this->AddCommand(chanserv->Bot(), &commandcsenforce); } }; diff --git a/modules/extra/cs_entrymsg.cpp b/modules/extra/cs_entrymsg.cpp index 649fd69f8..f424baede 100644 --- a/modules/extra/cs_entrymsg.cpp +++ b/modules/extra/cs_entrymsg.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" struct EntryMsg { @@ -162,13 +163,16 @@ class CSEntryMessage : public Module { this->SetAuthor("Anope"); this->SetType(CORE); + + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); Implementation i[] = { I_OnJoinChannel, I_OnReload, I_OnDatabaseReadMetadata, I_OnDatabaseWriteMetadata }; ModuleManager::Attach(i, this, 4); - this->AddCommand(ChanServ, &commandentrymsg); + this->AddCommand(chanserv->Bot(), &commandentrymsg); - this->OnReload(false); + this->OnReload(); } void OnJoinChannel(User *u, Channel *c) @@ -179,11 +183,11 @@ class CSEntryMessage : public Module if (c->ci->GetExtRegular("cs_entrymsg", messages)) for (unsigned i = 0; i < messages.size(); ++i) - u->SendMessage(whosends(c->ci), "[%s] %s", c->ci->name.c_str(), messages[i].message.c_str()); + u->SendMessage(c->ci->WhoSends(), "[%s] %s", c->ci->name.c_str(), messages[i].message.c_str()); } } - void OnReload(bool) + void OnReload() { ConfigReader config; EntryMsg::MaxEntries = config.ReadInteger("cs_entrymsg", "maxentries", "5", 0, true); diff --git a/modules/extra/cs_set_misc.cpp b/modules/extra/cs_set_misc.cpp index cb654a9a1..4bd7a772a 100644 --- a/modules/extra/cs_set_misc.cpp +++ b/modules/extra/cs_set_misc.cpp @@ -11,6 +11,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetMisc : public Command { @@ -77,8 +78,8 @@ class CSSetMisc : public Module if (Commands.empty()) return; - Command *set = FindCommand(ChanServ, "SET"); - Command *saset = FindCommand(ChanServ, "SASET"); + Command *set = FindCommand(chanserv->Bot(), "SET"); + Command *saset = FindCommand(chanserv->Bot(), "SASET"); if (!set && !saset) return; @@ -114,10 +115,13 @@ class CSSetMisc : public Module this->SetAuthor("Anope"); this->SetType(CORE); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + Implementation i[] = { I_OnReload, I_OnChanInfo, I_OnDatabaseWriteMetadata, I_OnDatabaseReadMetadata }; ModuleManager::Attach(i, this, 4); - OnReload(true); + OnReload(); } ~CSSetMisc() @@ -125,12 +129,12 @@ class CSSetMisc : public Module RemoveAll(); } - void OnReload(bool) + void OnReload() { RemoveAll(); - Command *set = FindCommand(ChanServ, "SET"); - Command *saset = FindCommand(ChanServ, "SASET"); + Command *set = FindCommand(chanserv->Bot(), "SET"); + Command *saset = FindCommand(chanserv->Bot(), "SASET"); if (!set && !saset) return; diff --git a/modules/extra/cs_tban.cpp b/modules/extra/cs_tban.cpp index e3470504d..04d608246 100644 --- a/modules/extra/cs_tban.cpp +++ b/modules/extra/cs_tban.cpp @@ -16,6 +16,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" static Module *me; @@ -110,12 +111,15 @@ class CSTBan : public Module public: CSTBan(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) { - me = this; - - this->AddCommand(ChanServ, &commandcstban); - this->SetAuthor("Anope"); this->SetType(SUPPORTED); + + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + me = this; + + this->AddCommand(chanserv->Bot(), &commandcstban); } }; diff --git a/modules/extra/db_mysql.cpp b/modules/extra/db_mysql.cpp index 9a2c44d47..30a71c809 100644 --- a/modules/extra/db_mysql.cpp +++ b/modules/extra/db_mysql.cpp @@ -1,5 +1,7 @@ #include "module.h" +#include "operserv.h" #include "sql.h" +#include "os_session.h" static Anope::string ToString(const std::vector<Anope::string> &strings) { @@ -89,6 +91,7 @@ class DBMySQL : public Module service_reference<SQLProvider> SQL; public: + service_reference<SessionService> SessionInterface; time_t lastwarn; bool ro; @@ -99,7 +102,8 @@ class DBMySQL : public Module if (readonly && this->ro) { readonly = this->ro = false; - ircdproto->SendGlobops(OperServ, "Found SQL again, going out of readonly mode..."); + if (operserv) + ircdproto->SendGlobops(operserv->Bot(), "Found SQL again, going out of readonly mode..."); } SQL->Run(&sqlinterface, query); @@ -108,7 +112,8 @@ class DBMySQL : public Module { if (Anope::CurTime - Config->UpdateTimeout > lastwarn) { - ircdproto->SendGlobops(OperServ, "Unable to locate SQL reference, is m_mysql loaded? Going to readonly..."); + if (operserv) + ircdproto->SendGlobops(operserv->Bot(), "Unable to locate SQL reference, is m_mysql loaded? Going to readonly..."); readonly = this->ro = true; this->lastwarn = Anope::CurTime; } @@ -120,7 +125,7 @@ class DBMySQL : public Module return SQL ? SQL->Escape(query) : query; } - DBMySQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), sqlinterface(this), SQL("mysql/main") + DBMySQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), sqlinterface(this), SQL("mysql/main"), SessionInterface("session") { me = this; @@ -134,7 +139,8 @@ class DBMySQL : public Module }; ModuleManager::Attach(i, this, 2); - this->AddCommand(OperServ, &commandsqlsync); + if (operserv) + this->AddCommand(operserv->Bot(), &commandsqlsync); if (uplink_server) OnServerConnect(); @@ -542,12 +548,9 @@ class DBMySQL : public Module time_t seton = r.Get(i, "seton").is_pos_number_only() ? convertTo<time_t>(r.Get(i, "seton")) : Anope::CurTime; time_t expires = r.Get(i, "expires").is_pos_number_only() ? convertTo<time_t>(r.Get(i, "expires")) : Anope::CurTime; - XLine *x = SGLine->Add(NULL, NULL, user + "@" + host, expires, reason); + XLine *x = SGLine->Add(user + "@" + host, by, expires, reason); if (x) - { - x->By = by; x->Created = seton; - } } } @@ -562,16 +565,13 @@ class DBMySQL : public Module XLine *x = NULL; if (SNLine && r.Get(i, "type").equals_cs("SNLINE")) - x = SNLine->Add(NULL, NULL, mask, expires, reason); + x = SNLine->Add(mask, by, expires, reason); else if (SQLine && r.Get(i, "type").equals_cs("SQLINE")) - x = SQLine->Add(NULL, NULL, mask, expires, reason); + x = SQLine->Add(mask, by, expires, reason); else if (SZLine && r.Get(i, "type").equals_cs("SZLINE")) - x = SZLine->Add(NULL, NULL, mask, expires, reason); + x = SZLine->Add(mask, by, expires, reason); if (x) - { - x->By = by; x->Created = seton; - } } r = SQL->RunQuery("SELECT * FROM `anope_os_exceptions`"); @@ -583,7 +583,16 @@ class DBMySQL : public Module Anope::string reason = r.Get(i, "reason"); time_t expires = convertTo<time_t>(r.Get(i, "expires")); - exception_add(NULL, mask, limit, reason, creator, expires); + if (SessionInterface) + { + Exception *e = new Exception(); + e->mask = mask; + e->limit = limit; + e->who = creator; + e->reason = reason; + e->time = expires; + SessionInterface->AddException(e); + } } r = SQL->RunQuery("SELECT * FROM `anope_extra`"); @@ -661,7 +670,7 @@ class DBMySQL : public Module BotInfo *service = command->service; ChannelInfo *ci = source.ci; - if (service == NickServ) + if (service->nick == Config->s_NickServ) { if (u->Account() && ((command->name.equals_ci("SET") && !params.empty()) || (command->name.equals_ci("SASET") && u->HasCommand("nickserv/saset") && params.size() > 1))) { @@ -691,7 +700,7 @@ class DBMySQL : public Module } } } - else if (service == ChanServ) + else if (service->nick == Config->s_ChanServ) { if (command->name.equals_ci("SET") && u->Account() && params.size() > 1) { @@ -721,7 +730,7 @@ class DBMySQL : public Module } } } - else if (service == BotServ) + else if (service->nick == Config->s_BotServ) { if (command->name.equals_ci("KICK") && params.size() > 2) { @@ -773,7 +782,7 @@ class DBMySQL : public Module } } } - else if (service == MemoServ) + else if (service->nick == Config->s_MemoServ) { if (command->name.equals_ci("IGNORE") && params.size() > 0) { @@ -1049,18 +1058,12 @@ class DBMySQL : public Module this->RunQuery(query); } - void OnMemoSend(User *, NickCore *nc, Memo *m) - { - this->RunQuery("INSERT INTO `anope_ms_info` (receiver, flags, time, sender, text, serv) VALUES('" + - this->Escape(nc->display) + "', '" + ToString(m->ToString()) + "', " + stringify(m->time) + ", '" + - this->Escape(m->sender) + "', '" + this->Escape(m->text) + "', 'NICK')"); - } - - void OnMemoSend(User *, ChannelInfo *ci, Memo *m) + void OnMemoSend(const Anope::string &source, const Anope::string &target, MemoInfo *mi, Memo *m) { + const Anope::string &mtype = (!target.empty() && target[0] == '#' ? "CHAN" : "NICK"); this->RunQuery("INSERT INTO `anope_ms_info` (receiver, flags, time, sender, text, serv) VALUES('" + - this->Escape(ci->name) + "', '" + ToString(m->ToString()) + "', " + stringify(m->time) + ", '" + - this->Escape(m->sender) + "', '" + this->Escape(m->text) + "', 'CHAN')"); + this->Escape(target) + "', '" + ToString(m->ToString()) + "', " + stringify(m->time) + ", '" + + this->Escape(source) + "', '" + this->Escape(m->text) + "', '" + mtype + "')"); } void OnMemoDel(const NickCore *nc, MemoInfo *mi, Memo *m) @@ -1079,7 +1082,7 @@ class DBMySQL : public Module this->RunQuery("DELETE FROM `anope_ms_info` WHERE `receiver` = '" + this->Escape(ci->name) + "'"); } - EventReturn OnAddAkill(User *, XLine *ak) + EventReturn OnAddAkill(XLine *ak) { this->RunQuery("INSERT INTO `anope_os_akills` (user, host, xby, reason, seton, expire) VALUES('" + this->Escape(ak->GetUser()) + "', '" + this->Escape(ak->GetHost()) + "', '" + this->Escape(ak->By) + "', '" + @@ -1095,7 +1098,7 @@ class DBMySQL : public Module this->RunQuery("TRUNCATE TABLE `anope_os_akills`"); } - EventReturn OnExceptionAdd(User *, Exception *ex) + EventReturn OnExceptionAdd(Exception *ex) { this->RunQuery("INSERT INTO `anope_os_exceptions` (mask, slimit, who, reason, time, expires) VALUES('" + this->Escape(ex->mask) + "', " + stringify(ex->limit) + ", '" + this->Escape(ex->who) + "', '" + this->Escape(ex->reason) + "', " + @@ -1108,7 +1111,7 @@ class DBMySQL : public Module this->RunQuery("DELETE FROM `anope_os_exceptions` WHERE `mask` = '" + this->Escape(ex->mask) + "'"); } - EventReturn OnAddXLine(User *, XLine *x, XLineType Type) + EventReturn OnAddXLine(XLine *x, XLineType Type) { this->RunQuery(Anope::string("INSERT INTO `anope_os_xlines` (type, mask, xby, reason, seton, expire) VALUES('") + (Type == X_SNLINE ? "SNLINE" : (Type == X_SQLINE ? "SQLINE" : "SZLINE")) + "', '" + @@ -1216,7 +1219,7 @@ static void SaveDatabases() { Memo *m = nc->memos.memos[j]; - me->OnMemoSend(NULL, nc, m); + me->OnMemoSend(m->sender, nc->display, &nc->memos, m); } } @@ -1267,35 +1270,35 @@ static void SaveDatabases() { Memo *m = ci->memos.memos[j]; - me->OnMemoSend(NULL, ci, m); + me->OnMemoSend(m->sender, ci->name, &ci->memos, m); } } if (SGLine) for (unsigned i = 0, end = SGLine->GetCount(); i < end; ++i) - me->OnAddAkill(NULL, SGLine->GetEntry(i)); + me->OnAddAkill(SGLine->GetEntry(i)); if (SZLine) for (unsigned i = 0, end = SZLine->GetCount(); i < end; ++i) - me->OnAddXLine(NULL, SZLine->GetEntry(i), X_SZLINE); + me->OnAddXLine(SZLine->GetEntry(i), X_SZLINE); if (SQLine) for (unsigned i = 0, end = SQLine->GetCount(); i < end; ++i) - me->OnAddXLine(NULL, SQLine->GetEntry(i), X_SQLINE); + me->OnAddXLine(SQLine->GetEntry(i), X_SQLINE); if (SNLine) for (unsigned i = 0, end = SNLine->GetCount(); i < end; ++i) - me->OnAddXLine(NULL, SNLine->GetEntry(i), X_SNLINE); + me->OnAddXLine(SNLine->GetEntry(i), X_SNLINE); - for (unsigned i = 0, end = exceptions.size(); i < end; ++i) - me->OnExceptionAdd(NULL, exceptions[i]); + if (me->SessionInterface) + for (SessionService::ExceptionVector::iterator it = me->SessionInterface->GetExceptions().begin(); it != me->SessionInterface->GetExceptions().end(); ++it) + me->OnExceptionAdd(*it); } CommandReturn CommandSQLSync::Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - User *u = source.u; SaveDatabases(); - u->SendMessage(OperServ, _("Updating MySQL.")); + source.Reply(_("Updating MySQL.")); return MOD_CONT; } diff --git a/modules/extra/hs_request.cpp b/modules/extra/hs_request.cpp index 4978035d3..f208d72b3 100644 --- a/modules/extra/hs_request.cpp +++ b/modules/extra/hs_request.cpp @@ -16,6 +16,8 @@ */ #include "module.h" +#include "hostserv.h" +#include "memoserv.h" static bool HSRequestMemoUser = false; static bool HSRequestMemoOper = false; @@ -152,8 +154,8 @@ class CommandHSActivate : public Command na->hostinfo.SetVhost(it->second->ident, it->second->host, u->nick, it->second->time); FOREACH_MOD(I_OnSetVhost, OnSetVhost(na)); - if (HSRequestMemoUser) - memo_send(source, na->nick, _("[auto memo] Your requested vHost has been approved."), 2); + if (HSRequestMemoUser && memoserv) + memoserv->Send(Config->s_HostServ, na->nick, _("[auto memo] Your requested vHost has been approved."), true); me->SendMessage(source, _("vHost for %s has been activated"), na->nick.c_str()); Log(LOG_COMMAND, u, this, NULL) << "for " << na->nick << " for vhost " << (!it->second->ident.empty() ? it->second->ident + "@" : "") << it->second->host; @@ -207,15 +209,15 @@ class CommandHSReject : public Command delete it->second; Requests.erase(it); - if (HSRequestMemoUser) + if (HSRequestMemoUser && memoserv) { - char message[BUFSIZE]; + Anope::string message; if (!reason.empty()) - snprintf(message, sizeof(message), _("[auto memo] Your requested vHost has been rejected. Reason: %s"), reason.c_str()); + message = Anope::printf(_("[auto memo] Your requested vHost has been rejected. Reason: %s"), reason.c_str()); else - snprintf(message, sizeof(message), "%s", _("[auto memo] Your requested vHost has been rejected.")); + message = _("[auto memo] Your requested vHost has been rejected."); - memo_send(source, nick, message, 2); + memoserv->Send(Config->s_HostServ, nick, message, true); } me->SendMessage(source, _("vHost for %s has been rejected"), nick.c_str()); @@ -312,18 +314,21 @@ class HSRequest : public Module { me = this; - this->AddCommand(HostServ, &commandhsrequest); - this->AddCommand(HostServ, &commandhsactive); - this->AddCommand(HostServ, &commandhsreject); - this->AddCommand(HostServ, &commandhswaiting); + if (!hostserv) + throw ModuleException("HostServ is not loaded!"); + + this->AddCommand(hostserv->Bot(), &commandhsrequest); + this->AddCommand(hostserv->Bot(), &commandhsactive); + this->AddCommand(hostserv->Bot(), &commandhsreject); + this->AddCommand(hostserv->Bot(), &commandhswaiting); this->SetAuthor("Anope"); this->SetType(SUPPORTED); - this->OnReload(false); - Implementation i[] = { I_OnPreCommand, I_OnDatabaseRead, I_OnDatabaseWrite, I_OnReload }; ModuleManager::Attach(i, this, 4); + + this->OnReload(); } ~HSRequest() @@ -339,7 +344,7 @@ class HSRequest : public Module EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) { BotInfo *service = source.owner; - if (service == HostServ) + if (service->nick == Config->s_HostServ) { if (command->name.equals_ci("LIST")) { @@ -348,7 +353,7 @@ class HSRequest : public Module if (!key.empty() && key.equals_ci("+req")) { std::vector<Anope::string> emptyParams; - Command *c = FindCommand(HostServ, "WAITING"); + Command *c = FindCommand(hostserv->Bot(), "WAITING"); if (!c) throw CoreException("No waiting command?"); c->Execute(source, emptyParams); @@ -356,7 +361,7 @@ class HSRequest : public Module } } } - else if (service == NickServ) + else if (service->nick == Config->s_NickServ) { if (command->name.equals_ci("DROP")) { @@ -402,7 +407,7 @@ class HSRequest : public Module } } - void OnReload(bool) + void OnReload() { ConfigReader config; HSRequestMemoUser = config.ReadFlag("hs_request", "memouser", "no", 0); @@ -422,7 +427,7 @@ void req_send_memos(CommandSource &source, const Anope::string &vIdent, const An else host = vHost; - if (HSRequestMemoOper == 1) + if (HSRequestMemoOper == 1 && memoserv) for (unsigned i = 0; i < Config->Opers.size(); ++i) { Oper *o = Config->Opers[i]; @@ -431,9 +436,9 @@ void req_send_memos(CommandSource &source, const Anope::string &vIdent, const An if (!na) continue; - char message[BUFSIZE]; - snprintf(message, sizeof(message), _("[auto memo] vHost \002%s\002 has been requested."), host.c_str()); - memo_send(source, na->nick, message, 2); + Anope::string message = Anope::printf(_("[auto memo] vHost \002%s\002 has been requested by %s."), host.c_str(), source.u->GetMask().c_str()); + + memoserv->Send(Config->s_HostServ, na->nick, message, true); } } diff --git a/modules/extra/m_alias.cpp b/modules/extra/m_alias.cpp index c5f52bef2..025a53df0 100644 --- a/modules/extra/m_alias.cpp +++ b/modules/extra/m_alias.cpp @@ -6,6 +6,7 @@ */ #include "module.h" +#include "chanserv.h" struct CommandAlias { @@ -26,10 +27,10 @@ class ModuleAlias : public Module Implementation i[] = { I_OnReload, I_OnPreCommandRun, I_OnBotFantasy }; ModuleManager::Attach(i, this, 3); - OnReload(false); + OnReload(); } - void OnReload(bool) + void OnReload() { ConfigReader config; @@ -102,10 +103,10 @@ class ModuleAlias : public Module BotInfo *target = findbot(alias.target_client); if (!target) - target = ChanServ; + target = chanserv->Bot(); Anope::string full_message = alias.target_command; - if (target == ChanServ || target == BotServ) + if (target == chanserv->Bot() || target->nick == Config->s_BotServ) { Command *target_c = FindCommand(target, alias.target_command); if (target_c && !target_c->HasFlag(CFLAG_STRIP_CHANNEL)) diff --git a/modules/extra/m_dnsbl.cpp b/modules/extra/m_dnsbl.cpp index 5c88e75b5..f2572e694 100644 --- a/modules/extra/m_dnsbl.cpp +++ b/modules/extra/m_dnsbl.cpp @@ -6,10 +6,11 @@ */ #include "module.h" +#include "operserv.h" struct FakeAkill : public Command { - FakeAkill() : Command("AKILL", 0, 0) { this->service = OperServ; } + FakeAkill() : Command("AKILL", 0, 0) { this->service = findbot(Config->s_OperServ); } CommandReturn Execute(CommandSource &, const std::vector<Anope::string> &) { return MOD_CONT; } } fake_akill; @@ -61,18 +62,18 @@ class DNSBLResolver : public DNSRequest reason = reason.replace_all_cs("%N", Config->NetworkName); XLine *x = NULL; - if (this->add_to_akill && SGLine && (x = SGLine->Add(NULL, NULL, Anope::string("*@") + user->host, Anope::CurTime + this->blacklist.bantime, reason))) + if (this->add_to_akill && SGLine && (x = SGLine->Add(Anope::string("*@") + user->host, Config->s_OperServ, Anope::CurTime + this->blacklist.bantime, reason))) { - Log(LOG_COMMAND, OperServ, &fake_akill) << "for " << user->GetMask() << " (Listed in " << this->blacklist.name << ")"; + Log(LOG_COMMAND, operserv->Bot(), &fake_akill) << "for " << user->GetMask() << " (Listed in " << this->blacklist.name << ")"; /* If AkillOnAdd is disabled send it anyway, noone wants bots around... */ if (!Config->AkillOnAdd) - ircdproto->SendAkill(*user, x); + ircdproto->SendAkill(user, x); } else { - Log(OperServ) << "DNSBL: " << user->GetMask() << " appears in " << this->blacklist.name; - XLine xline(Anope::string("*@") + user->host, OperServ ? OperServ->nick : "OperServ", Anope::CurTime + this->blacklist.bantime, reason); - ircdproto->SendAkill(*user, &xline); + Log(operserv->Bot()) << "DNSBL: " << user->GetMask() << " appears in " << this->blacklist.name; + XLine xline(Anope::string("*@") + user->host, Config->s_OperServ, Anope::CurTime + this->blacklist.bantime, reason); + ircdproto->SendAkill(user, &xline); } } }; @@ -90,13 +91,13 @@ class ModuleDNSBL : public Module this->SetAuthor("Anope"); this->SetType(SUPPORTED); - OnReload(false); - - Implementation i[] = { I_OnReload, I_OnPreUserConnect }; + Implementation i[] = { I_OnReload, I_OnUserConnect }; ModuleManager::Attach(i, this, 2); + + OnReload(); } - void OnReload(bool) + void OnReload() { ConfigReader config; @@ -127,17 +128,18 @@ class ModuleDNSBL : public Module } } - EventReturn OnPreUserConnect(User *u) + void OnUserConnect(dynamic_reference<User> &user, bool &exempt) { - if (!this->check_on_connect && !Me->IsSynced()) - return EVENT_CONTINUE; - if (!this->check_on_netburst && !u->server->IsSynced()) - return EVENT_CONTINUE; + if (exempt || !user || (!this->check_on_connect && !Me->IsSynced())) + return; + + if (!this->check_on_netburst && !user->server->IsSynced()) + return; /* At this time we only support IPv4 */ - if (u->ip.sa.sa_family != AF_INET) - return EVENT_CONTINUE; + if (user->ip.sa.sa_family != AF_INET) + return; - unsigned long ip = u->ip.sa4.sin_addr.s_addr; + unsigned long ip = user->ip.sa4.sin_addr.s_addr; unsigned long reverse_ip = ((ip & 0xFF) << 24) | ((ip & 0xFF00) << 8) | ((ip & 0xFF0000) >> 8) | ((ip & 0xFF000000) >> 24); sockaddrs user_ip; @@ -151,7 +153,7 @@ class ModuleDNSBL : public Module try { Anope::string dnsbl_host = user_ip.addr() + "." + b.name; - DNSBLResolver *res = new DNSBLResolver(this, u, b, dnsbl_host, this->add_to_akill); + DNSBLResolver *res = new DNSBLResolver(this, user, b, dnsbl_host, this->add_to_akill); res->Process(); } catch (const SocketException &ex) @@ -160,7 +162,7 @@ class ModuleDNSBL : public Module } } - return EVENT_CONTINUE; + return; } }; diff --git a/modules/extra/m_helpchan.cpp b/modules/extra/m_helpchan.cpp index 028e5e332..90a33ca79 100644 --- a/modules/extra/m_helpchan.cpp +++ b/modules/extra/m_helpchan.cpp @@ -6,6 +6,7 @@ */ #include "module.h" +#include "operserv.h" class HelpChannel : public Module { @@ -20,23 +21,23 @@ class HelpChannel : public Module Implementation i[] = { I_OnChannelModeSet, I_OnReload }; ModuleManager::Attach(i, this, 2); - OnReload(true); + OnReload(); } EventReturn OnChannelModeSet(Channel *c, ChannelModeName Name, const Anope::string ¶m) { - if (Name == CMODE_OP && c && c->ci && c->name.equals_ci(this->HelpChan)) + if (Name == CMODE_OP && operserv && c && c->ci && c->name.equals_ci(this->HelpChan)) { User *u = finduser(param); if (u && check_access(u, c->ci, CA_OPDEOPME)) - u->SetMode(OperServ, UMODE_HELPOP); + u->SetMode(operserv->Bot(), UMODE_HELPOP); } return EVENT_CONTINUE; } - void OnReload(bool) + void OnReload() { ConfigReader config; diff --git a/modules/extra/m_ldap.cpp b/modules/extra/m_ldap.cpp index c7f0914a0..157bc70ac 100644 --- a/modules/extra/m_ldap.cpp +++ b/modules/extra/m_ldap.cpp @@ -210,7 +210,7 @@ class ModuleLDAP : public Module, public Pipe Implementation i[] = { I_OnReload, I_OnModuleUnload }; ModuleManager::Attach(i, this, 2); - OnReload(true); + OnReload(); } ~ModuleLDAP() @@ -225,7 +225,7 @@ class ModuleLDAP : public Module, public Pipe LDAPServices.clear(); } - void OnReload(bool startup) + void OnReload() { ConfigReader config; int i, num; diff --git a/modules/extra/m_ldap_authentication.cpp b/modules/extra/m_ldap_authentication.cpp index fa60247e5..f2caac63d 100644 --- a/modules/extra/m_ldap_authentication.cpp +++ b/modules/extra/m_ldap_authentication.cpp @@ -1,4 +1,5 @@ #include "module.h" +#include "nickserv.h" #include "ldap.h" static Anope::string email_attribute; @@ -44,8 +45,8 @@ class IdentifyInterface : public LDAPInterface return; } - User *u = *ii->user; - Command *c = *ii->command; + User *u = ii->user; + Command *c = ii->command; u->Extend("m_ldap_authentication_authenticated"); @@ -56,7 +57,7 @@ class IdentifyInterface : public LDAPInterface if (Config->NSAddAccessOnReg) na->nc->AddAccess(create_mask(u)); - u->SendMessage(NickServ, _("Your account \002%s\002 has been successfully created."), na->nick.c_str()); + u->SendMessage(nickserv->Bot(), _("Your account \002%s\002 has been successfully created."), na->nick.c_str()); } enc_encrypt(ii->pass, na->nc->pass); @@ -83,8 +84,8 @@ class IdentifyInterface : public LDAPInterface return; } - User *u = *ii->user; - Command *c = *ii->command; + User *u = ii->user; + Command *c = ii->command; u->Extend("m_ldap_authentication_error"); @@ -128,7 +129,7 @@ class OnIdentifyInterface : public LDAPInterface if (!email.equals_ci(u->Account()->email)) { u->Account()->email = email; - u->SendMessage(NickServ, _("Your email has been updated to \002%s\002"), email.c_str()); + u->SendMessage(nickserv->Bot(), _("Your email has been updated to \002%s\002"), email.c_str()); Log() << "m_ldap_authentication: Updated email address for " << u->nick << " (" << u->Account()->display << ") to " << email; } } @@ -166,10 +167,10 @@ class NSIdentifyLDAP : public Module ModuleManager::Attach(i, this, 4); ModuleManager::SetPriority(this, PRIORITY_FIRST); - OnReload(false); + OnReload(); } - void OnReload(bool) + void OnReload() { ConfigReader config; @@ -182,7 +183,7 @@ class NSIdentifyLDAP : public Module EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) { - if (this->disable_register && command->service == NickServ && command->name == "REGISTER") + if (this->disable_register && nickserv && command->service == nickserv->Bot() && command->name == "REGISTER") { source.Reply(_(this->disable_reason.c_str())); return EVENT_STOP; diff --git a/modules/extra/m_ldap_oper.cpp b/modules/extra/m_ldap_oper.cpp index b8a1d5f51..8010031cb 100644 --- a/modules/extra/m_ldap_oper.cpp +++ b/modules/extra/m_ldap_oper.cpp @@ -93,10 +93,10 @@ class LDAPOper : public Module Implementation i[] = { I_OnReload, I_OnNickIdentify, I_OnDelCore }; ModuleManager::Attach(i, this, 3); - OnReload(false); + OnReload(); } - void OnReload(bool) + void OnReload() { ConfigReader config; diff --git a/modules/extra/m_mysql.cpp b/modules/extra/m_mysql.cpp index 9895d025d..a54426b37 100644 --- a/modules/extra/m_mysql.cpp +++ b/modules/extra/m_mysql.cpp @@ -158,7 +158,7 @@ class ModuleSQL : public Module, public Pipe DThread = new DispatcherThread(); threadEngine.Start(DThread); - OnReload(true); + OnReload(); } ~ModuleSQL() @@ -173,7 +173,7 @@ class ModuleSQL : public Module, public Pipe delete DThread; } - void OnReload(bool startup) + void OnReload() { ConfigReader config; int i, num; diff --git a/modules/extra/m_xmlrpc.cpp b/modules/extra/m_xmlrpc.cpp index db1242970..34288195a 100644 --- a/modules/extra/m_xmlrpc.cpp +++ b/modules/extra/m_xmlrpc.cpp @@ -218,12 +218,12 @@ class ModuleXMLRPC : public Module { me = this; - OnReload(false); - ModuleManager::RegisterService(&this->xmlrpcinterface); Implementation i[] = { I_OnReload }; ModuleManager::Attach(i, this, 1); + + OnReload(); } ~ModuleXMLRPC() @@ -250,7 +250,7 @@ class ModuleXMLRPC : public Module this->listen_sockets.clear(); } - void OnReload(bool) + void OnReload() { ConfigReader config; diff --git a/modules/extra/m_xmlrpc_main.cpp b/modules/extra/m_xmlrpc_main.cpp index 593aba6ef..6f4b4b05c 100644 --- a/modules/extra/m_xmlrpc_main.cpp +++ b/modules/extra/m_xmlrpc_main.cpp @@ -87,14 +87,15 @@ class MyXMLRPCEvent : public XMLRPCEvent else request->reply("online", "yes"); - mod_run_cmd(bi, *u, NULL, command); + mod_run_cmd(bi, u, NULL, command); if (created && u) { - XMLRPCUser *myu = debug_cast<XMLRPCUser *>(*u); + User *useru = u; + XMLRPCUser *myu = debug_cast<XMLRPCUser *>(useru); if (!myu->GetOut().empty()) request->reply("return", iface->Sanitize(myu->GetOut())); - delete *u; + delete u; } } } diff --git a/modules/extra/ns_maxemail.cpp b/modules/extra/ns_maxemail.cpp index 94b4ef12c..2a0141508 100644 --- a/modules/extra/ns_maxemail.cpp +++ b/modules/extra/ns_maxemail.cpp @@ -59,13 +59,13 @@ class NSMaxEmail : public Module this->SetAuthor("Anope"); this->SetType(SUPPORTED); - ModuleManager::Attach(I_OnReload, this); - ModuleManager::Attach(I_OnPreCommand, this); + Implementation i[] = { I_OnReload, I_OnPreCommand }; + ModuleManager::Attach(i, this, 2); - OnReload(false); + OnReload(); } - void OnReload(bool) + void OnReload() { ConfigReader config; this->NSEmailMax = config.ReadInteger("ns_maxemail", "maxemails", "0", 0, false); @@ -75,7 +75,7 @@ class NSMaxEmail : public Module EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) { BotInfo *service = source.owner; - if (service == NickServ) + if (service->nick == Config->s_NickServ) { if (command->name.equals_ci("REGISTER")) { diff --git a/modules/extra/ns_set_misc.cpp b/modules/extra/ns_set_misc.cpp index a1bf091c5..385fb9648 100644 --- a/modules/extra/ns_set_misc.cpp +++ b/modules/extra/ns_set_misc.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSSetMisc : public Command { @@ -80,8 +81,8 @@ class NSSetMisc : public Module if (Commands.empty()) return; - Command *set = FindCommand(NickServ, "SET"); - Command *saset = FindCommand(NickServ, "SASET"); + Command *set = FindCommand(nickserv->Bot(), "SET"); + Command *saset = FindCommand(nickserv->Bot(), "SASET"); if (!set && !saset) return; @@ -120,7 +121,7 @@ class NSSetMisc : public Module Implementation i[] = { I_OnReload, I_OnNickInfo, I_OnDatabaseWriteMetadata, I_OnDatabaseReadMetadata }; ModuleManager::Attach(i, this, 4); - OnReload(true); + OnReload(); } ~NSSetMisc() @@ -128,12 +129,12 @@ class NSSetMisc : public Module RemoveAll(); } - void OnReload(bool) + void OnReload() { RemoveAll(); - Command *set = FindCommand(NickServ, "SET"); - Command *saset = FindCommand(NickServ, "SASET"); + Command *set = FindCommand(nickserv->Bot(), "SET"); + Command *saset = FindCommand(nickserv->Bot(), "SASET"); if (!set && !saset) return; diff --git a/modules/extra/os_defcon.cpp b/modules/extra/os_defcon.cpp new file mode 100644 index 000000000..a2a536adf --- /dev/null +++ b/modules/extra/os_defcon.cpp @@ -0,0 +1,693 @@ +/* OperServ core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" +#include "operserv.h" +#include "global.h" +#include "os_session.h" + +enum DefconLevel +{ + DEFCON_NO_NEW_CHANNELS, + DEFCON_NO_NEW_NICKS, + DEFCON_NO_MLOCK_CHANGE, + DEFCON_FORCE_CHAN_MODES, + DEFCON_REDUCE_SESSION, + DEFCON_NO_NEW_CLIENTS, + DEFCON_OPER_ONLY, + DEFCON_SILENT_OPER_ONLY, + DEFCON_AKILL_NEW_CLIENTS, + DEFCON_NO_NEW_MEMOS +}; + +static Module *me = NULL; +bool DefConModesSet = false; + +struct DefconConfig +{ + std::vector<std::bitset<32> > DefCon; + Flags<ChannelModeName, CMODE_END * 2> DefConModesOn; + Flags<ChannelModeName, CMODE_END * 2> DefConModesOff; + std::map<ChannelModeName, Anope::string> DefConModesOnParams; + + int defaultlevel, sessionlimit; + Anope::string chanmodes, message, offmessage, akillreason; + std::vector<Anope::string> defcons; + time_t akillexpire, timeout; + bool globalondefcon; + + DefconConfig() + { + this->DefCon.resize(5); + } + + bool Check(DefconLevel level) + { + return this->Check(this->defaultlevel, level); + } + + bool Check(int dlevel, DefconLevel level) + { + return this->DefCon[dlevel].test(level); + } + + void Add(int dlevel, DefconLevel level) + { + this->DefCon[dlevel][level] = true; + } + + void Del(int dlevel, DefconLevel level) + { + this->DefCon[dlevel][level] = false; + } + + bool SetDefConParam(ChannelModeName Name, const Anope::string &buf) + { + return DefConModesOnParams.insert(std::make_pair(Name, buf)).second; + } + + void UnsetDefConParam(ChannelModeName Name) + { + DefConModesOnParams.erase(Name); + } + + bool GetDefConParam(ChannelModeName Name, Anope::string &buf) + { + std::map<ChannelModeName, Anope::string>::iterator it = DefConModesOnParams.find(Name); + + buf.clear(); + + if (it != DefConModesOnParams.end()) + { + buf = it->second; + return true; + } + + return false; + } +}; + +static DefconConfig DConfig; + +/**************************************************************************/ + +void defcon_sendlvls(CommandSource &source); +void runDefCon(); +static Anope::string defconReverseModes(const Anope::string &modes); + +class DefConTimeout : public CallBack +{ + int level; + + public: + DefConTimeout(Module *mod, int newlevel) : CallBack(mod, DConfig.timeout), level(newlevel) { } + + void Tick(time_t) + { + if (DConfig.defaultlevel != level) + { + DConfig.defaultlevel = level; + FOREACH_MOD(I_OnDefconLevel, OnDefconLevel(level)); + Log(operserv->Bot(), "operserv/defcon") << "Defcon level timeout, returning to level " << level; + ircdproto->SendGlobops(operserv->Bot(), GetString(NULL, _("\002%s\002 Changed the DEFCON level to \002%d\002")).c_str(), Config->s_OperServ.c_str(), level); + + if (DConfig.globalondefcon) + { + if (!DConfig.offmessage.empty()) + global->SendGlobal(global->Bot(), "", DConfig.offmessage); + else + global->SendGlobal(global->Bot(), "", Anope::printf(GetString(NULL, _("The Defcon Level is now at Level: \002%d\002")).c_str(), DConfig.defaultlevel)); + + if (!DConfig.message.empty()) + global->SendGlobal(global->Bot(), "", DConfig.message); + } + + runDefCon(); + } + } +}; +static DefConTimeout *timeout; + +class CommandOSDefcon : public Command +{ + void SendLevels(CommandSource &source) + { + if (DConfig.Check(DEFCON_NO_NEW_CHANNELS)) + source.Reply(_("* No new channel registrations")); + if (DConfig.Check(DEFCON_NO_NEW_NICKS)) + source.Reply(_("* No new nick registrations")); + if (DConfig.Check(DEFCON_NO_MLOCK_CHANGE)) + source.Reply(_("* No MLOCK changes")); + if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && !DConfig.chanmodes.empty()) + source.Reply(_("* Force Chan Modes (%s) to be set on all channels"), DConfig.chanmodes.c_str()); + if (DConfig.Check(DEFCON_REDUCE_SESSION)) + source.Reply(_("* Use the reduced session limit of %d"), DConfig.sessionlimit); + if (DConfig.Check(DEFCON_NO_NEW_CLIENTS)) + source.Reply(_("* Kill any NEW clients connecting")); + if (DConfig.Check(DEFCON_OPER_ONLY)) + source.Reply(_("* Ignore any non-opers with message")); + if (DConfig.Check(DEFCON_SILENT_OPER_ONLY)) + source.Reply(_("* Silently ignore non-opers")); + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + source.Reply(_("* AKILL any new clients connecting")); + if (DConfig.Check(DEFCON_NO_NEW_MEMOS)) + source.Reply(_("* No new memos sent")); + } + + public: + CommandOSDefcon() : Command("DEFCON", 1, 1, "operserv/defcon") + { + this->SetDesc(_("Manipulate the DefCon system")); + } + + CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + User *u = source.u; + const Anope::string &lvl = params[0]; + + if (lvl.empty()) + { + source.Reply(_("Services are now at DEFCON \002%d\002"), DConfig.defaultlevel); + this->SendLevels(source); + return MOD_CONT; + } + + int newLevel = 0; + try + { + newLevel = convertTo<int>(lvl); + } + catch (const ConvertException &) { } + + if (newLevel < 1 || newLevel > 5) + { + this->OnSyntaxError(source, ""); + return MOD_CONT; + } + + DConfig.defaultlevel = newLevel; + + FOREACH_MOD(I_OnDefconLevel, OnDefconLevel(newLevel)); + + if (timeout) + { + delete timeout; + timeout = NULL; + } + + if (DConfig.timeout) + timeout = new DefConTimeout(me, 5); + + source.Reply(_("Services are now at DEFCON \002%d\002"), DConfig.defaultlevel); + this->SendLevels(source); + Log(LOG_ADMIN, u, this) << "to change defcon level to " << newLevel; + ircdproto->SendGlobops(operserv->Bot(), _("\002%s\002 Changed the DEFCON level to \002%d\002"), u->nick.c_str(), newLevel); + /* Global notice the user what is happening. Also any Message that + the Admin would like to add. Set in config file. */ + if (DConfig.globalondefcon) + { + if (DConfig.defaultlevel == 5 && !DConfig.offmessage.empty()) + global->SendGlobal(global->Bot(), "", DConfig.offmessage); + else if (DConfig.defaultlevel != 5) + { + global->SendGlobal(global->Bot(), "", Anope::printf(_("The Defcon level is now at: \002%d\002"), DConfig.defaultlevel)); + if (!DConfig.message.empty()) + global->SendGlobal(global->Bot(), "", DConfig.message); + } + } + + /* Run any defcon functions, e.g. FORCE CHAN MODE */ + runDefCon(); + return MOD_CONT; + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + source.Reply(_("Syntax: \002DEFCON\002 [\0021\002|\0022\002|\0023\002|\0024\002|\0025\002]\n" + "The defcon system can be used to implement a pre-defined\n" + "set of restrictions to services useful during an attempted\n" + "attack on the network.")); + return true; + } + + void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) + { + SyntaxError(source, "DEFCON", _("DEFCON [\0021\002|\0022\002|\0023\002|\0024\002|\0025\002]")); + } +}; + +class OSDefcon : public Module +{ + service_reference<SessionService> session_service; + CommandOSDefcon commandosdefcon; + + void ParseModeString() + { + int add = -1; /* 1 if adding, 0 if deleting, -1 if neither */ + unsigned char mode; + ChannelMode *cm; + ChannelModeParam *cmp; + Anope::string modes, param; + + spacesepstream ss(DConfig.chanmodes); + + DConfig.DefConModesOn.ClearFlags(); + DConfig.DefConModesOff.ClearFlags(); + ss.GetToken(modes); + + /* Loop while there are modes to set */ + for (unsigned i = 0, end = modes.length(); i < end; ++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->Type == MODE_STATUS || cm->Type == MODE_LIST || !cm->CanSet(NULL)) + { + Log() << "DefConChanModes mode character '" << mode << "' cannot be locked"; + continue; + } + else if (add) + { + DConfig.DefConModesOn.SetFlag(cm->Name); + DConfig.DefConModesOff.UnsetFlag(cm->Name); + + if (cm->Type == MODE_PARAM) + { + cmp = debug_cast<ChannelModeParam *>(cm); + + if (!ss.GetToken(param)) + { + Log() << "DefConChanModes mode character '" << mode << "' has no parameter while one is expected"; + continue; + } + + if (!cmp->IsValid(param)) + continue; + + DConfig.SetDefConParam(cmp->Name, param); + } + } + else if (DConfig.DefConModesOn.HasFlag(cm->Name)) + { + DConfig.DefConModesOn.UnsetFlag(cm->Name); + + if (cm->Type == MODE_PARAM) + DConfig.UnsetDefConParam(cm->Name); + } + } + } + + /* We can't mlock +L if +l is not mlocked as well. */ + if ((cm = ModeManager::FindChannelModeByName(CMODE_REDIRECT)) && DConfig.DefConModesOn.HasFlag(cm->Name) && !DConfig.DefConModesOn.HasFlag(CMODE_LIMIT)) + { + DConfig.DefConModesOn.UnsetFlag(CMODE_REDIRECT); + + Log() << "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)) && DConfig.DefConModesOn.HasFlag(cm->Name) && !DConfig.DefConModesOn.HasFlag(CMODE_INVITE)) + { + DConfig.DefConModesOn.UnsetFlag(CMODE_NOKNOCK); + Log() << "DefConChanModes must lock mode +i as well to lock mode +K"; + } + } + + public: + OSDefcon(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), session_service("session") + { + if (!DConfig.defaultlevel) + throw ModuleException("Invalid configuration settings"); + + me = this; + + this->SetAuthor("Anope"); + this->SetType(CORE); + + Implementation i[] = { I_OnReload, I_OnChannelModeSet, I_OnChannelModeUnset, I_OnPreCommandRun, I_OnPreCommand, I_OnUserConnect, I_OnChannelModeAdd, I_OnChannelCreate }; + ModuleManager::Attach(i, this, 9); + + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosdefcon); + + this->OnReload(); + } + + void OnReload() + { + ConfigReader config; + DefconConfig dconfig; + + dconfig.defaultlevel = config.ReadInteger("defcon", "defaultlevel", 0, 0); + dconfig.defcons[4] = config.ReadValue("defcon", "level4", 0); + dconfig.defcons[3] = config.ReadValue("defcon", "level3", 0); + dconfig.defcons[2] = config.ReadValue("defcon", "level2", 0); + dconfig.defcons[1] = config.ReadValue("defcon", "level1", 0); + dconfig.sessionlimit = config.ReadInteger("defcon", "sessionlimit", 0, 0); + dconfig.akillexpire = dotime(config.ReadValue("defcon", "akillexpire", 0)); + dconfig.chanmodes = config.ReadValue("defcon", "chanmodes", 0); + dconfig.timeout = dotime(config.ReadValue("defcon", "timeout", 0)); + dconfig.globalondefcon = config.ReadFlag("defcon", "globalondefcon", 0); + dconfig.message = config.ReadValue("defcon", "message", 0); + dconfig.offmessage = config.ReadValue("defcon", "offmessage", 0); + + if (dconfig.defaultlevel < 1 || dconfig.defaultlevel > 5) + throw ConfigException("The value for <os_defcon:defaultlevel> must be between 1 and 5"); + else if (dconfig.akillexpire <= 0) + throw ConfigException("The value for <os_defcon:akillexpire> must be greater than zero!"); + + for (unsigned level = 1; level < 5; ++level) + { + spacesepstream operations(dconfig.defcons[level]); + Anope::string operation; + while (operations.GetToken(operation)) + { + if (operation.equals_ci("nonewchannels")) + dconfig.Add(level, DEFCON_NO_NEW_CHANNELS); + else if (operation.equals_ci("nonewnicks")) + dconfig.Add(level, DEFCON_NO_NEW_NICKS); + else if (operation.equals_ci("nomlockchanges")) + dconfig.Add(level, DEFCON_NO_MLOCK_CHANGE); + else if (operation.equals_ci("forcechanmodes")) + dconfig.Add(level, DEFCON_FORCE_CHAN_MODES); + else if (operation.equals_ci("reducedsessions")) + dconfig.Add(level, DEFCON_REDUCE_SESSION); + else if (operation.equals_ci("nonewclients")) + dconfig.Add(level, DEFCON_NO_NEW_CLIENTS); + else if (operation.equals_ci("operonly")) + dconfig.Add(level, DEFCON_OPER_ONLY); + else if (operation.equals_ci("silentoperonly")) + dconfig.Add(level, DEFCON_SILENT_OPER_ONLY); + else if (operation.equals_ci("akillnewclients")) + dconfig.Add(level, DEFCON_AKILL_NEW_CLIENTS); + else if (operation.equals_ci("nonewmemos")) + dconfig.Add(level, DEFCON_NO_NEW_MEMOS); + } + + if (dconfig.Check(level, DEFCON_REDUCE_SESSION) && dconfig.sessionlimit <= 0) + throw ConfigException("The value for <os_defcon:sessionlimit> must be greater than zero!"); + else if (dconfig.Check(level, DEFCON_AKILL_NEW_CLIENTS) && dconfig.akillreason.empty()) + throw ConfigException("The value for <os_defcon:akillreason> must not be empty!"); + else if (dconfig.Check(level, DEFCON_FORCE_CHAN_MODES) && dconfig.chanmodes.empty()) + throw ConfigException("The value for <os_defcon:chanmodes> must not be empty!"); + } + + DConfig = dconfig; + this->ParseModeString(); + } + + EventReturn OnUserConnect(User *u, bool &exempt) + { + if (!exempt && u->server->IsSynced() && DConfig.Check(DEFCON_AKILL_NEW_CLIENTS) && !u->server->IsULined()) + { + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + { + Log(operserv->Bot(), "operserv/defcon") << "DEFCON: adding akill for *@" << u->host; + XLine *x = SGLine->Add("*@" + u->host, Config->s_OperServ, Anope::CurTime + DConfig.akillexpire, DConfig.akillreason); + if (x) + x->By = Config->s_OperServ; + } + + if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + kill_user(Config->s_OperServ, u, DConfig.akillreason); + + return EVENT_STOP; + } + + return EVENT_CONTINUE; + } + + EventReturn OnChannelModeSet(Channel *c, ChannelModeName Name, const Anope::string ¶m) + { + ChannelMode *cm = ModeManager::FindChannelModeByName(Name); + + if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && cm && DConfig.DefConModesOff.HasFlag(Name)) + { + c->RemoveMode(operserv->Bot(), Name, param); + + return EVENT_STOP; + } + + return EVENT_CONTINUE; + } + + EventReturn OnChannelModeUnset(Channel *c, ChannelModeName Name, const Anope::string &) + { + ChannelMode *cm = ModeManager::FindChannelModeByName(Name); + + if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && cm && DConfig.DefConModesOn.HasFlag(Name)) + { + Anope::string param; + + if (DConfig.GetDefConParam(Name, param)) + c->SetMode(operserv->Bot(), Name, param); + else + c->SetMode(operserv->Bot(), Name); + + return EVENT_STOP; + + } + + return EVENT_CONTINUE; + } + + EventReturn OnPreCommandRun(User *&u, BotInfo *&bi, Anope::string &command, Anope::string &message, ChannelInfo *&ci) + { + if (!u->HasMode(UMODE_OPER) && (DConfig.Check(DEFCON_OPER_ONLY) || DConfig.Check(DEFCON_SILENT_OPER_ONLY))) + { + if (!DConfig.Check(DEFCON_SILENT_OPER_ONLY)) + u->SendMessage(bi, _("Services are in Defcon mode, Please try again later.")); + + return EVENT_STOP; + } + + return EVENT_CONTINUE; + } + + EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) + { + BotInfo *service = command->service; + if (service->nick == Config->s_NickServ) + { + if (command->name.equals_ci("REGISTER") || command->name.equals_ci("GROUP")) + { + if (DConfig.Check(DEFCON_NO_NEW_NICKS)) + { + source.Reply(_("Services are in Defcon mode, Please try again later.")); + return EVENT_STOP; + } + } + } + else if (service->nick == Config->s_ChanServ) + { + if (command->name.equals_ci("SET")) + { + if (!params.empty() && params[0].equals_ci("MLOCK") && DConfig.Check(DEFCON_NO_MLOCK_CHANGE)) + { + source.Reply(_("Services are in Defcon mode, Please try again later.")); + return EVENT_STOP; + } + } + else if (command->name.equals_ci("REGISTER")) + { + if (DConfig.Check(DEFCON_NO_NEW_CHANNELS)) + { + source.Reply(_("Services are in Defcon mode, Please try again later.")); + return EVENT_STOP; + } + } + } + else if (service->nick == Config->s_MemoServ) + { + if (command->name.equals_ci("SEND") || command->name.equals_ci("SENDALL")) + { + if (DConfig.Check(DEFCON_NO_NEW_MEMOS)) + { + source.Reply(_("Services are in Defcon mode, Please try again later.")); + return EVENT_STOP; + } + } + } + + return EVENT_CONTINUE; + } + + void OnUserConnect(dynamic_reference<User> &u, bool &exempt) + { + if (exempt || !u || !u->server->IsSynced() || u->server->IsULined()) + return; + + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + { + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + { + Log(operserv->Bot(), "operserv/defcon") << "DEFCON: adding akill for *@" << u->host; + XLine *x = SGLine->Add("*@" + u->host, Config->s_OperServ, Anope::CurTime + DConfig.akillexpire, DConfig.akillreason); + if (x) + x->By = Config->s_OperServ; + } + + if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + { + kill_user(Config->s_OperServ, u, DConfig.akillreason); + return; + } + } + + if (!DConfig.sessionlimit) + return; + + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + { + Log(operserv->Bot(), "operserv/defcon") << "DEFCON: adding akill for *@" << u->host; + XLine *x = SGLine->Add("*@" + u->host, Config->s_OperServ, Anope::CurTime + DConfig.akillexpire, !DConfig.akillreason.empty() ? DConfig.akillreason : "DEFCON AKILL"); + if (x) + x->By = Config->s_OperServ; + } + + if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + { + kill_user(Config->s_OperServ, u, DConfig.akillreason); + return; + } + + Session *session = session_service->FindSession(u->host); + Exception *exception = session_service->FindException(u); + + if (DConfig.Check(DEFCON_REDUCE_SESSION) && !exception) + { + if (session && session->count > DConfig.sessionlimit) + { + if (!Config->SessionLimitExceeded.empty()) + ircdproto->SendMessage(operserv->Bot(), u->nick, Config->SessionLimitExceeded.c_str(), u->host.c_str()); + if (!Config->SessionLimitDetailsLoc.empty()) + ircdproto->SendMessage(operserv->Bot(), u->nick, "%s", Config->SessionLimitDetailsLoc.c_str()); + + kill_user(Config->s_OperServ, u, "Defcon session limit exceeded"); + ++session->hits; + if (Config->MaxSessionKill && session->hits >= Config->MaxSessionKill) + { + SGLine->Add("*@" + u->host, Config->s_OperServ, Anope::CurTime + Config->SessionAutoKillExpiry, "Defcon session limit exceeded"); + ircdproto->SendGlobops(operserv->Bot(), "[DEFCON] Added a temporary AKILL for \2*@%s\2 due to excessive connections", u->host.c_str()); + } + } + } + } + + void OnChannelModeAdd(ChannelMode *cm) + { + if (DConfig.chanmodes.find(cm->ModeChar) != Anope::string::npos) + this->ParseModeString(); + } + + void OnChannelCreate(Channel *c) + { + if (DConfig.Check(DEFCON_FORCE_CHAN_MODES)) + c->SetModes(operserv->Bot(), false, "%s", DConfig.chanmodes.c_str()); + } +}; + +/** + * Send a message to the oper about which precautions are "active" for this level + **/ +void defcon_sendlvls(CommandSource &source) +{ + if (DConfig.Check(DEFCON_NO_NEW_CHANNELS)) + source.Reply(_("* No new channel registrations")); + if (DConfig.Check(DEFCON_NO_NEW_NICKS)) + source.Reply(_("* No new nick registrations")); + if (DConfig.Check(DEFCON_NO_MLOCK_CHANGE)) + source.Reply(_("* No MLOCK changes")); + if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && !DConfig.chanmodes.empty()) + source.Reply(_("* Force Chan Modes (%s) to be set on all channels"), DConfig.chanmodes.c_str()); + if (DConfig.Check(DEFCON_REDUCE_SESSION)) + source.Reply(_("* Use the reduced session limit of %d"), DConfig.sessionlimit); + if (DConfig.Check(DEFCON_NO_NEW_CLIENTS)) + source.Reply(_("* Kill any NEW clients connecting")); + if (DConfig.Check(DEFCON_OPER_ONLY)) + source.Reply(_("* Ignore any non-opers with message")); + if (DConfig.Check(DEFCON_SILENT_OPER_ONLY)) + source.Reply(_("* Silently ignore non-opers")); + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + source.Reply(_("* AKILL any new clients connecting")); + if (DConfig.Check(DEFCON_NO_NEW_MEMOS)) + source.Reply(_("* No new memos sent")); +} + +void runDefCon() +{ + if (DConfig.Check(DEFCON_FORCE_CHAN_MODES)) + { + if (!DConfig.chanmodes.empty() && !DefConModesSet) + { + if (DConfig.chanmodes[0] == '+' || DConfig.chanmodes[0] == '-') + { + Log(operserv->Bot(), "operserv/defcon") << "DEFCON: setting " << DConfig.chanmodes << " on all channels"; + DefConModesSet = true; + MassChannelModes(operserv->Bot(), DConfig.chanmodes); + } + } + } + else + { + if (!DConfig.chanmodes.empty() && DefConModesSet) + { + if (DConfig.chanmodes[0] == '+' || DConfig.chanmodes[0] == '-') + { + DefConModesSet = false; + Anope::string newmodes = defconReverseModes(DConfig.chanmodes); + if (!newmodes.empty()) + { + Log(operserv->Bot(), "operserv/defcon") << "DEFCON: setting " << newmodes << " on all channels"; + MassChannelModes(operserv->Bot(), newmodes); + } + } + } + } +} + +static Anope::string defconReverseModes(const Anope::string &modes) +{ + if (modes.empty()) + return ""; + Anope::string newmodes; + for (unsigned i = 0, end = modes.length(); i < end; ++i) + { + if (modes[i] == '+') + newmodes += '-'; + else if (modes[i] == '-') + newmodes += '+'; + else + newmodes += modes[i]; + } + return newmodes; +} + +MODULE_INIT(OSDefcon) |