From bd12e3a4e6501496f6eeb7aeb5245162020d6e6c Mon Sep 17 00:00:00 2001 From: danieldg Date: Sat, 14 Mar 2009 20:48:43 +0000 Subject: Extban rework: allow exceptions to override bans on join Move all bans that prevent a user from joining the channel to OnCheckBan, then stack their return results to allow an exception to override a ban. This does not make join exceptions override any other exception like mute. git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11222 e03df62e-2008-0410-955e-edbf42e46eb7 --- src/channels.cpp | 99 ++++++++++++++++++-------------------- src/modules/m_allowinvite.cpp | 2 +- src/modules/m_banexception.cpp | 3 +- src/modules/m_blockcaps.cpp | 2 +- src/modules/m_blockcolor.cpp | 2 +- src/modules/m_channelban.cpp | 20 ++------ src/modules/m_gecosban.cpp | 18 ++----- src/modules/m_muteban.cpp | 4 +- src/modules/m_noctcp.cpp | 2 +- src/modules/m_nokicks.cpp | 2 +- src/modules/m_nonicks.cpp | 2 +- src/modules/m_nonotice.cpp | 2 +- src/modules/m_nopartmsg.cpp | 2 +- src/modules/m_operchans.cpp | 28 +++-------- src/modules/m_operinvex.cpp | 18 ++----- src/modules/m_serverban.cpp | 18 ++----- src/modules/m_services_account.cpp | 22 ++++----- src/modules/m_stripcolor.cpp | 2 +- 18 files changed, 92 insertions(+), 156 deletions(-) (limited to 'src') diff --git a/src/channels.cpp b/src/channels.cpp index b8195ee9f..4435b3324 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -489,78 +489,73 @@ Channel* Channel::ForceChan(InspIRCd* Instance, Channel* Ptr, User* user, const bool Channel::IsBanned(User* user) { - char mask[MAXBUF]; - int MOD_RESULT = 0; - FOREACH_RESULT(I_OnCheckBan,OnCheckBan(user, this)); + int result = 0; + FOREACH_RESULT_MAP(I_OnCheckBan, OnCheckBan(user, this), + result = banmatch_reduce(result, MOD_RESULT); + ); - if (MOD_RESULT == -1) - return true; - else if (MOD_RESULT == 0) + if (result) + return (result < 0); + + char mask[MAXBUF]; + snprintf(mask, MAXBUF, "%s!%s@%s", user->nick.c_str(), user->ident.c_str(), user->GetIPString()); + for (BanList::iterator i = this->bans.begin(); i != this->bans.end(); i++) { - snprintf(mask, MAXBUF, "%s!%s@%s", user->nick.c_str(), user->ident.c_str(), user->GetIPString()); - for (BanList::iterator i = this->bans.begin(); i != this->bans.end(); i++) + if ((InspIRCd::Match(user->GetFullHost(),i->data, NULL)) || // host + (InspIRCd::Match(user->GetFullRealHost(),i->data, NULL)) || // uncloaked host + (InspIRCd::MatchCIDR(mask, i->data, NULL))) // ip { - if ((InspIRCd::Match(user->GetFullHost(),i->data, NULL)) || // host - (InspIRCd::Match(user->GetFullRealHost(),i->data, NULL)) || // uncloaked host - (InspIRCd::MatchCIDR(mask, i->data, NULL))) // ip - { - return true; - } + return true; } } return false; } -bool Channel::IsExtBanned(const std::string &str, char type) +int Channel::GetExtBanStatus(const std::string &str, char type) { - int MOD_RESULT = 0; - FOREACH_RESULT(I_OnCheckStringExtBan, OnCheckStringExtBan(str, this, type)); + int result = 0; + FOREACH_RESULT_MAP(I_OnCheckStringExtBan, OnCheckStringExtBan(str, this, type), + result = banmatch_reduce(result, MOD_RESULT); + ); + + if (result) + return result; - if (MOD_RESULT == -1) - return true; - else if (MOD_RESULT == 0) + // nobody decided for us, check the ban list + for (BanList::iterator i = this->bans.begin(); i != this->bans.end(); i++) { - for (BanList::iterator i = this->bans.begin(); i != this->bans.end(); i++) - { - if (i->data[0] != type || i->data[1] != ':') - continue; + if (i->data[0] != type || i->data[1] != ':') + continue; - // Iterate past char and : to get to the mask without doing a data copy(!) - std::string maskptr = i->data.substr(2); - ServerInstance->Logs->Log("EXTBANS", DEBUG, "Checking %s against %s, type is %c", str.c_str(), maskptr.c_str(), type); + std::string maskptr = i->data.substr(2); + ServerInstance->Logs->Log("EXTBANS", DEBUG, "Checking %s against %s, type is %c", str.c_str(), maskptr.c_str(), type); - if (InspIRCd::Match(str, maskptr, NULL)) - return true; - } + if (InspIRCd::Match(str, maskptr, NULL)) + return -1; } - return false; + return 0; } -bool Channel::IsExtBanned(User *user, char type) +int Channel::GetExtBanStatus(User *user, char type) { - int MOD_RESULT = 0; - FOREACH_RESULT(I_OnCheckExtBan, OnCheckExtBan(user, this, type)); + int result = 0; + FOREACH_RESULT_MAP(I_OnCheckExtBan, OnCheckExtBan(user, this, type), + result = banmatch_reduce(result, MOD_RESULT); + ); - if (MOD_RESULT == -1) - return true; - else if (MOD_RESULT == 0) - { - char mask[MAXBUF]; - snprintf(mask, MAXBUF, "%s!%s@%s", user->nick.c_str(), user->ident.c_str(), user->GetIPString()); + if (result) + return result; - // XXX: we should probably hook cloaked hosts in here somehow too.. - if (this->IsExtBanned(mask, type)) - return true; - - if (this->IsExtBanned(user->GetFullHost(), type)) - return true; - - if (this->IsExtBanned(user->GetFullRealHost(), type)) - return true; - } - - return false; + char mask[MAXBUF]; + int rv = 0; + snprintf(mask, MAXBUF, "%s!%s@%s", user->nick.c_str(), user->ident.c_str(), user->GetIPString()); + + // XXX: we should probably hook cloaked hosts in here somehow too.. + rv = banmatch_reduce(rv, this->GetExtBanStatus(mask, type)); + rv = banmatch_reduce(rv, this->GetExtBanStatus(user->GetFullHost(), type)); + rv = banmatch_reduce(rv, this->GetExtBanStatus(user->GetFullRealHost(), type)); + return rv; } /* Channel::PartUser diff --git a/src/modules/m_allowinvite.cpp b/src/modules/m_allowinvite.cpp index a675a0cc8..cbab0bd2f 100644 --- a/src/modules/m_allowinvite.cpp +++ b/src/modules/m_allowinvite.cpp @@ -44,7 +44,7 @@ class ModuleAllowInvite : public Module { if (IS_LOCAL(user)) { - if (channel->IsModeSet('A') && !channel->IsExtBanned(user, 'A')) + if (channel->IsModeSet('A') && channel->GetExtBanStatus(user, 'A') < 0) { // Explicitly allow /invite return -1; diff --git a/src/modules/m_banexception.cpp b/src/modules/m_banexception.cpp index 42fce61f9..5a8c2b785 100644 --- a/src/modules/m_banexception.cpp +++ b/src/modules/m_banexception.cpp @@ -104,7 +104,8 @@ public: std::string maskptr = it->mask.substr(2); if (InspIRCd::Match(str, maskptr)) - return 1; // matches + // They match an entry on the list, so let them in. + return 1; } } diff --git a/src/modules/m_blockcaps.cpp b/src/modules/m_blockcaps.cpp index 497221ee2..6b6030bd8 100644 --- a/src/modules/m_blockcaps.cpp +++ b/src/modules/m_blockcaps.cpp @@ -69,7 +69,7 @@ public: return 0; } - if (c->IsModeSet('B') || c->IsExtBanned(user, 'B')) + if (c->IsModeSet('B') || c->GetExtBanStatus(user, 'B') < 0) { int caps = 0; const char* actstr = "\1ACTION "; diff --git a/src/modules/m_blockcolor.cpp b/src/modules/m_blockcolor.cpp index 8338745ba..65ef0e825 100644 --- a/src/modules/m_blockcolor.cpp +++ b/src/modules/m_blockcolor.cpp @@ -54,7 +54,7 @@ class ModuleBlockColour : public Module return 0; } - if(c->IsModeSet('c') || c->IsExtBanned(user, 'c')) + if(c->IsModeSet('c') || c->GetExtBanStatus(user, 'c') < 0) { for (std::string::iterator i = text.begin(); i != text.end(); i++) { diff --git a/src/modules/m_channelban.cpp b/src/modules/m_channelban.cpp index def17bdb5..8caae0a96 100644 --- a/src/modules/m_channelban.cpp +++ b/src/modules/m_channelban.cpp @@ -21,7 +21,7 @@ class ModuleBadChannelExtban : public Module public: ModuleBadChannelExtban(InspIRCd* Me) : Module(Me) { - Implementation eventlist[] = { I_OnUserPreJoin, I_On005Numeric }; + Implementation eventlist[] = { I_OnCheckBan, I_On005Numeric }; ServerInstance->Modules->Attach(eventlist, this, 2); } @@ -34,25 +34,15 @@ class ModuleBadChannelExtban : public Module return Version("$Id$", VF_COMMON|VF_VENDOR,API_VERSION); } - virtual int OnUserPreJoin(User *user, Channel *c, const char *cname, std::string &privs, const std::string &key) + virtual int OnCheckBan(User *user, Channel *c) { - if (!IS_LOCAL(user)) - return 0; - - if (!c) - return 0; - - + int rv = 0; for (UCListIter i = user->chans.begin(); i != user->chans.end(); i++) { - if (c->IsExtBanned(i->first->name, 'j')) - { - user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s %s :Cannot join channel (You're banned)", user->nick.c_str(), c->name.c_str()); - return 1; - } + rv = banmatch_reduce(rv, c->GetExtBanStatus(i->first->name, 'j')); } - return 0; + return rv; } virtual void On005Numeric(std::string &output) diff --git a/src/modules/m_gecosban.cpp b/src/modules/m_gecosban.cpp index 5147a2eb9..934501f41 100644 --- a/src/modules/m_gecosban.cpp +++ b/src/modules/m_gecosban.cpp @@ -21,7 +21,7 @@ class ModuleGecosBan : public Module public: ModuleGecosBan(InspIRCd* Me) : Module(Me) { - Implementation eventlist[] = { I_OnUserPreJoin, I_On005Numeric }; + Implementation eventlist[] = { I_OnCheckBan, I_On005Numeric }; ServerInstance->Modules->Attach(eventlist, this, 2); } @@ -34,21 +34,9 @@ class ModuleGecosBan : public Module return Version("$Id$", VF_COMMON|VF_VENDOR, API_VERSION); } - virtual int OnUserPreJoin(User *user, Channel *c, const char *cname, std::string &privs, const std::string &key) + virtual int OnCheckBan(User *user, Channel *c) { - if (!IS_LOCAL(user)) - return 0; - - if (!c) - return 0; - - if (c->IsExtBanned(user->fullname, 'r')) - { - user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s %s :Cannot join channel (You're banned)", user->nick.c_str(), c->name.c_str()); - return 1; - } - - return 0; + return c->GetExtBanStatus(user->fullname, 'r'); } virtual void On005Numeric(std::string &output) diff --git a/src/modules/m_muteban.cpp b/src/modules/m_muteban.cpp index de31fb275..11c87976b 100644 --- a/src/modules/m_muteban.cpp +++ b/src/modules/m_muteban.cpp @@ -41,7 +41,7 @@ class ModuleQuietBan : public Module if (target_type == TYPE_CHANNEL) { - if (((Channel *)dest)->IsExtBanned(user, 'm')) + if (((Channel *)dest)->GetExtBanStatus(user, 'm') < 0) { user->WriteServ("NOTICE "+std::string(user->nick)+" :*** Cannot send to " + ((Channel *)dest)->name + ", as you are muted"); return 1; @@ -58,7 +58,7 @@ class ModuleQuietBan : public Module if (target_type == TYPE_CHANNEL) { - if (((Channel *)dest)->IsExtBanned(user, 'm')) + if (((Channel *)dest)->GetExtBanStatus(user, 'm') < 0) { user->WriteServ("NOTICE "+std::string(user->nick)+" :*** Cannot send to " + ((Channel *)dest)->name + ", as you are muted"); return 1; diff --git a/src/modules/m_noctcp.cpp b/src/modules/m_noctcp.cpp index d431a7369..5f734ec15 100644 --- a/src/modules/m_noctcp.cpp +++ b/src/modules/m_noctcp.cpp @@ -88,7 +88,7 @@ class ModuleNoCTCP : public Module return 0; } - if (c->IsModeSet('C') || c->IsExtBanned(user, 'C')) + if (c->IsModeSet('C') || c->GetExtBanStatus(user, 'C') < 0) { if ((text.length()) && (text[0] == '\1')) { diff --git a/src/modules/m_nokicks.cpp b/src/modules/m_nokicks.cpp index 5db14299b..229366e1c 100644 --- a/src/modules/m_nokicks.cpp +++ b/src/modules/m_nokicks.cpp @@ -45,7 +45,7 @@ class ModuleNoKicks : public Module { if (access_type == AC_KICK) { - if (channel->IsModeSet('Q') || channel->IsExtBanned(source, 'Q')) + if (channel->IsModeSet('Q') || channel->GetExtBanStatus(source, 'Q') < 0) { if ((ServerInstance->ULine(source->nick.c_str())) || (ServerInstance->ULine(source->server)) || (!*source->server)) { diff --git a/src/modules/m_nonicks.cpp b/src/modules/m_nonicks.cpp index 14957759c..50b4503dd 100644 --- a/src/modules/m_nonicks.cpp +++ b/src/modules/m_nonicks.cpp @@ -92,7 +92,7 @@ class ModuleNoNickChange : public Module if (CHANOPS_EXEMPT(ServerInstance, 'N') && curr->GetStatus(user) == STATUS_OP) continue; - if (curr->IsModeSet('N') || curr->IsExtBanned(user, 'N')) + if (curr->IsModeSet('N') || curr->GetExtBanStatus(user, 'N') < 0) { user->WriteNumeric(ERR_CANTCHANGENICK, "%s :Can't change nickname while on %s (+N is set)", user->nick.c_str(), curr->name.c_str()); return 1; diff --git a/src/modules/m_nonotice.cpp b/src/modules/m_nonotice.cpp index 9c02408cf..79a1ea796 100644 --- a/src/modules/m_nonotice.cpp +++ b/src/modules/m_nonotice.cpp @@ -48,7 +48,7 @@ class ModuleNoNotice : public Module if ((target_type == TYPE_CHANNEL) && (IS_LOCAL(user))) { Channel* c = (Channel*)dest; - if (c->IsModeSet('T') || c->IsExtBanned(user, 'T')) + if (c->IsModeSet('T') || c->GetExtBanStatus(user, 'T') < 0) { if (ServerInstance->ULine(user->server)) { diff --git a/src/modules/m_nopartmsg.cpp b/src/modules/m_nopartmsg.cpp index afa44900d..1b1316ae5 100644 --- a/src/modules/m_nopartmsg.cpp +++ b/src/modules/m_nopartmsg.cpp @@ -40,7 +40,7 @@ class ModulePartMsgBan : public Module if (!IS_LOCAL(user)) return; - if (channel->IsExtBanned(user, 'p')) + if (channel->GetExtBanStatus(user, 'p') < 0) partmessage = ""; return; diff --git a/src/modules/m_operchans.cpp b/src/modules/m_operchans.cpp index b8f7f2415..2205ed03d 100644 --- a/src/modules/m_operchans.cpp +++ b/src/modules/m_operchans.cpp @@ -56,32 +56,18 @@ class ModuleOperChans : public Module oc = new OperChans(ServerInstance); if (!ServerInstance->Modes->AddMode(oc)) throw ModuleException("Could not add new modes!"); - Implementation eventlist[] = { I_OnUserPreJoin }; + Implementation eventlist[] = { I_OnCheckBan }; ServerInstance->Modules->Attach(eventlist, this, 1); } - virtual int OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven) + virtual int OnCheckBan(User* user, Channel* chan) { - if (!IS_OPER(user)) - { - if (chan) - { - if (chan->IsModeSet('O')) - { - user->WriteNumeric(ERR_CANTJOINOPERSONLY, "%s %s :Only IRC operators may join the channel %s (+O is set)",user->nick.c_str(), chan->name.c_str(), chan->name.c_str()); - return 1; - } - } - } - else - { - if (chan && chan->IsExtBanned(user->oper, 'O')) - { - user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s %s :Cannot join channel (You're banned)", user->nick.c_str(), chan->name.c_str()); - return 1; - } - } + if (IS_OPER(user)) + return chan->GetExtBanStatus(user->oper, 'O'); + + if (chan->IsModeSet('O')) + return -1; return 0; } diff --git a/src/modules/m_operinvex.cpp b/src/modules/m_operinvex.cpp index 19b12d34c..1952d4296 100644 --- a/src/modules/m_operinvex.cpp +++ b/src/modules/m_operinvex.cpp @@ -24,7 +24,7 @@ class ModuleOperInvex : public Module public: ModuleOperInvex(InspIRCd* Me) : Module(Me) { - Implementation eventlist[] = { I_OnUserPreJoin, I_On005Numeric, I_OnCheckInvite }; + Implementation eventlist[] = { I_OnCheckBan, I_On005Numeric, I_OnCheckInvite }; ServerInstance->Modules->Attach(eventlist, this, 3); } @@ -55,21 +55,11 @@ class ModuleOperInvex : public Module return 0; } - virtual int OnUserPreJoin(User *user, Channel *c, const char *cname, std::string &privs, const std::string &key) + virtual int OnCheckBan(User *user, Channel *c) { - if (!IS_LOCAL(user) || !IS_OPER(user)) - return 0; - - if (!c) + if (!IS_OPER(user)) return 0; - - if (c->IsExtBanned(user->oper, 'O')) - { - user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s %s :Cannot join channel (You're banned)", user->nick.c_str(), c->name.c_str()); - return 1; - } - - return 0; + return c->GetExtBanStatus(user->oper, 'O'); } virtual void On005Numeric(std::string &output) diff --git a/src/modules/m_serverban.cpp b/src/modules/m_serverban.cpp index ca3b51e50..8c5db021b 100644 --- a/src/modules/m_serverban.cpp +++ b/src/modules/m_serverban.cpp @@ -21,7 +21,7 @@ class ModuleServerBan : public Module public: ModuleServerBan(InspIRCd* Me) : Module(Me) { - Implementation eventlist[] = { I_OnUserPreJoin, I_On005Numeric }; + Implementation eventlist[] = { I_OnCheckBan, I_On005Numeric }; ServerInstance->Modules->Attach(eventlist, this, 2); } @@ -34,21 +34,9 @@ class ModuleServerBan : public Module return Version("$Id$",VF_COMMON|VF_VENDOR,API_VERSION); } - virtual int OnUserPreJoin(User *user, Channel *c, const char *cname, std::string &privs, const std::string &key) + virtual int OnCheckBan(User *user, Channel *c) { - if (!IS_LOCAL(user)) - return 0; - - if (!c) - return 0; - - if (c->IsExtBanned(user->server, 's')) - { - user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s %s :Cannot join channel (You're banned)", user->nick.c_str(), c->name.c_str()); - return 1; - } - - return 0; + return c->GetExtBanStatus(user->server, 's'); } virtual void On005Numeric(std::string &output) diff --git a/src/modules/m_services_account.cpp b/src/modules/m_services_account.cpp index a763e8e68..59e7ec2e4 100644 --- a/src/modules/m_services_account.cpp +++ b/src/modules/m_services_account.cpp @@ -116,7 +116,7 @@ class ModuleServicesAccount : public Module if (!ServerInstance->Modes->AddMode(m1) || !ServerInstance->Modes->AddMode(m2) || !ServerInstance->Modes->AddMode(m3) || !ServerInstance->Modes->AddMode(m4) || !ServerInstance->Modes->AddMode(m5)) throw ModuleException("Some other module has claimed our modes!"); - Implementation eventlist[] = { I_OnWhois, I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserPreJoin, + Implementation eventlist[] = { I_OnWhois, I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserPreJoin, I_OnCheckBan, I_OnSyncUserMetaData, I_OnUserQuit, I_OnCleanup, I_OnDecodeMetaData, I_On005Numeric, I_OnUserPostNick }; ServerInstance->Modules->Attach(eventlist, this, 10); @@ -186,7 +186,7 @@ class ModuleServicesAccount : public Module if (account) { - if (c->IsExtBanned(*account, 'M')) + if (c->GetExtBanStatus(*account, 'M') < 0) { // may not speak (text is deliberately vague, so they don't know which restriction to evade) user->WriteNumeric(477, ""+std::string(user->nick)+" "+std::string(c->name)+" :You may not speak in this channel"); @@ -208,6 +208,14 @@ class ModuleServicesAccount : public Module return 0; } + virtual int OnCheckBan(User* user, Channel* chan) + { + std::string* account; + if (!user->GetExt("accountname", account)) + return 0; + return chan->GetExtBanStatus(*account, 'R'); + } + virtual int OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list) { return OnUserPreMessage(user, dest, target_type, text, status, exempt_list); @@ -239,16 +247,6 @@ class ModuleServicesAccount : public Module return 1; } } - - if (account) - { - if (chan->IsExtBanned(*account, 'R')) - { - // may not join - user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s %s :Cannot join channel (You're banned)", user->nick.c_str(), chan->name.c_str()); - return 1; - } - } } return 0; } diff --git a/src/modules/m_stripcolor.cpp b/src/modules/m_stripcolor.cpp index 8e2b0e8d9..605068d46 100644 --- a/src/modules/m_stripcolor.cpp +++ b/src/modules/m_stripcolor.cpp @@ -125,7 +125,7 @@ class ModuleStripColor : public Module return 0; } - active = t->IsModeSet('S') || t->IsExtBanned(user, 'S'); + active = t->IsModeSet('S') || t->GetExtBanStatus(user, 'S') < 0; } if (active) -- cgit v1.2.3