diff --git a/include/modules.h b/include/modules.h index 6c2c4fbd9..008d9de31 100644 --- a/include/modules.h +++ b/include/modules.h @@ -725,6 +725,8 @@ ModDataInfo *findmoddata_byname(char *name, ModDataType type); #define HOOKTYPE_PRE_KNOCK 72 #define HOOKTYPE_PRE_INVITE 73 #define HOOKTYPE_CAN_CHANGE_MODE 74 +#define HOOKTYPE_OPER_INVITE_BAN 75 +#define HOOKTYPE_VIEW_TOPIC_OUTSIDE_CHANNEl 76 /* Hook return values */ #define HOOK_CONTINUE 0 diff --git a/include/struct.h b/include/struct.h index f3a8797d4..7c3d6c14b 100644 --- a/include/struct.h +++ b/include/struct.h @@ -1629,7 +1629,6 @@ struct liststruct { #define MODE_RGSTR 0x8000 #define MODE_RGSTRONLY 0x10000 #define MODE_NOCOLOR 0x40000 -#define MODE_OPERONLY 0x80000 #define MODE_ADMONLY 0x100000 #define MODE_NOKICKS 0x200000 #define MODE_STRIP 0x400000 diff --git a/modules.conf b/modules.conf index cf95132ae..9f1014779 100644 --- a/modules.conf +++ b/modules.conf @@ -122,6 +122,7 @@ loadmodule "modules/chanmodes/censor"; /* +G */ loadmodule "modules/chanmodes/delayjoin"; /* +D */ loadmodule "modules/chanmodes/noknock"; /* +K */ loadmodule "modules/chanmodes/noinvite"; /* +V */ +loadmodule "modules/chanmodes/operonly"; /* +O */ /*** User modes ***/ loadmodule "modules/usermodes/noctcp"; /* +T */ diff --git a/src/channel.c b/src/channel.c index d722cad29..7071ef1ec 100644 --- a/src/channel.c +++ b/src/channel.c @@ -88,7 +88,6 @@ aCtab cFlagTab[] = { {MODE_RGSTRONLY, 'R', 0, 0}, {MODE_CHANPROT, 'a', 0, 1}, {MODE_CHANOWNER, 'q', 0, 1}, - {MODE_OPERONLY, 'O', 0, 0}, {MODE_ADMONLY, 'A', 0, 0}, {MODE_NOKICKS, 'Q', 0, 0}, {MODE_BAN, 'b', 1, 1}, diff --git a/src/modules/chanmodes/Makefile.in b/src/modules/chanmodes/Makefile.in index b4ec08e79..314aad304 100644 --- a/src/modules/chanmodes/Makefile.in +++ b/src/modules/chanmodes/Makefile.in @@ -31,7 +31,7 @@ INCLUDES = ../../include/auth.h ../../include/channel.h \ R_MODULES= \ nocolor.so stripcolor.so issecure.so permanent.so jointhrottle.so floodprot.so \ - noctcp.so link.so censor.so delayjoin.so noknock.so noinvite.so + noctcp.so link.so censor.so delayjoin.so noknock.so noinvite.so operonly.so MODULES=$(R_MODULES) MODULEFLAGS=@MODULEFLAGS@ @@ -99,4 +99,8 @@ noknock.so: noknock.c $(INCLUDES) noinvite.so: noinvite.c $(INCLUDES) $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \ - -o noinvite.so noinvite.c \ No newline at end of file + -o noinvite.so noinvite.c + +operonly.so: operonly.c $(INCLUDES) + $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \ + -o operonly.so operonly.c \ No newline at end of file diff --git a/src/modules/chanmodes/operonly.c b/src/modules/chanmodes/operonly.c new file mode 100644 index 000000000..479d05d66 --- /dev/null +++ b/src/modules/chanmodes/operonly.c @@ -0,0 +1,133 @@ +/* + * Disallow knocks UnrealIRCd Module (Channel Mode +K) + * (C) Copyright 2014 Travis McArthur (Heero) and the UnrealIRCd team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "config.h" +#include "struct.h" +#include "common.h" +#include "sys.h" +#include "numeric.h" +#include "msg.h" +#include "proto.h" +#include "channel.h" +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include +#endif +#include +#include "h.h" +#ifdef _WIN32 +#include "version.h" +#endif + +DLLFUNC CMD_FUNC(operonly); + +ModuleHeader MOD_HEADER(operonly) + = { + "chanmodes/operonly", + "$Id$", + "Channel Mode +V", + "3.2-b8-1", + NULL + }; + +Cmode_t EXTCMODE_OPERONLY; + +#define IsOperOnly(chptr) (chptr->mode.extmode & EXTCMODE_OPERONLY) + +DLLFUNC int operonly_check (aClient *cptr, aChannel *chptr, char *key, char *parv[]); +DLLFUNC int operonly_topic_allow (aClient *sptr, aChannel *chptr); +DLLFUNC int operonly_mode_allow (aChannel *chptr, aClient *cptr, long mode, char *params); +DLLFUNC int operonly_check_ban(aClient *cptr, aChannel *chptr); + +DLLFUNC int MOD_TEST(operonly)(ModuleInfo *modinfo) +{ + return MOD_SUCCESS; +} + +DLLFUNC int MOD_INIT(operonly)(ModuleInfo *modinfo) +{ +CmodeInfo req; + + memset(&req, 0, sizeof(req)); + req.paracount = 0; + req.flag = 'O'; + req.is_ok = extcmode_default_requirechop; + CmodeAdd(modinfo->handle, req, &EXTCMODE_OPERONLY); + + HookAddEx(modinfo->handle, HOOKTYPE_CAN_CHANGE_MODE, operonly_mode_allow); + HookAddEx(modinfo->handle, HOOKTYPE_CAN_JOIN, operonly_check); + HookAddEx(modinfo->handle, HOOKTYPE_OPER_INVITE_BAN, operonly_check_ban); + HookAddEx(modinfo->handle, HOOKTYPE_VIEW_TOPIC_OUTSIDE_CHANNEl, operonly_topic_allow); + + + MARK_AS_OFFICIAL_MODULE(modinfo); + return MOD_SUCCESS; +} + +DLLFUNC int MOD_LOAD(noctcp)(int module_load) +{ + return MOD_SUCCESS; +} + +DLLFUNC int MOD_UNLOAD(noctcp)(int module_unload) +{ + return MOD_SUCCESS; +} + +DLLFUNC int operonly_check (aClient *cptr, aChannel *chptr, char *key, char *parv[]) +{ + if ((chptr->mode.extmode & EXTCMODE_OPERONLY) && !IsAnOper(cptr)) + return ERR_OPERONLY; + return 0; +} + + +DLLFUNC int operonly_mode_allow (aChannel *chptr, aClient *cptr, long mode, char *params) +{ + + if ((mode & EXTCMODE_OPERONLY) && !IsAnOper(cptr)) + { + sendto_one(cptr, err_str(ERR_NOPRIVILEGES), me.name, cptr->name); + return HOOK_DENY; + } + + return HOOK_CONTINUE; +} + +DLLFUNC int operonly_check_ban(aClient *cptr, aChannel *chptr) +{ + if ((chptr->mode.extmode & EXTCMODE_OPERONLY) && + IsAnOper(cptr) && !IsSkoAdmin(cptr) && !IsCoAdmin(cptr)) + return HOOK_DENY; + + return HOOK_CONTINUE; +} + +DLLFUNC int operonly_topic_allow (aClient *sptr, aChannel *chptr) +{ + if (chptr->mode.extmode & EXTCMODE_OPERONLY && !IsAnOper(sptr)) + return HOOK_DENY; + + return HOOK_CONTINUE; +} + diff --git a/src/modules/m_join.c b/src/modules/m_join.c index 48b4257a7..0faf75060 100644 --- a/src/modules/m_join.c +++ b/src/modules/m_join.c @@ -103,9 +103,9 @@ DLLFUNC int _can_join(aClient *cptr, aClient *sptr, aChannel *chptr, char *key, Link *lp; Ban *banned; Hook *h; -int i; +int i,j; - for (h = Hooks[HOOKTYPE_CAN_JOIN]; h; h = h->next) + for (h = Hooks[HOOKTYPE_CAN_JOIN]; h; h = h->next) { i = (*(h->func.intfunc))(sptr,chptr,key,parv); if (i != 0) @@ -128,16 +128,20 @@ int i; return (ERR_SECUREONLYCHAN); } - if ((chptr->mode.mode & MODE_OPERONLY) && !IsAnOper(sptr)) - return (ERR_OPERONLY); - if ((chptr->mode.mode & MODE_ADMONLY) && !IsSkoAdmin(sptr)) return (ERR_ADMONLY); - /* Admin, Coadmin, Netadmin, and SAdmin can still walk +b in +O */ + + for (h = Hooks[HOOKTYPE_OPER_INVITE_BAN]; h; h = h->next) + { + j = (*(h->func.intfunc))(sptr,chptr); + if (j != 0) + break; + } + + /* See if we can evade this ban */ banned = is_banned(sptr, chptr, BANCHK_JOIN); - if (banned && (chptr->mode.mode & MODE_OPERONLY) && - IsAnOper(sptr) && !IsSkoAdmin(sptr) && !IsCoAdmin(sptr)) + if (banned && j == HOOK_DENY) return (ERR_BANNEDFROMCHAN); /* Only NetAdmin/SAdmin can walk +b in +A */ diff --git a/src/modules/m_mode.c b/src/modules/m_mode.c index 8f811e848..1765aadc0 100644 --- a/src/modules/m_mode.c +++ b/src/modules/m_mode.c @@ -829,13 +829,6 @@ int do_mode_char(aChannel *chptr, long modetype, char modechar, char *param, } switch (modetype) { - case MODE_OPERONLY: - if (MyClient(cptr) && !IsAnOper(cptr)) - { - sendto_one(cptr, err_str(ERR_NOPRIVILEGES), me.name, cptr->name); - break; - } - goto setthephuckingmode; case MODE_ADMONLY: if (!IsSkoAdmin(cptr) && !IsServer(cptr) && !IsULine(cptr)) diff --git a/src/modules/m_topic.c b/src/modules/m_topic.c index b05ed951a..f29f44548 100644 --- a/src/modules/m_topic.c +++ b/src/modules/m_topic.c @@ -103,6 +103,8 @@ char *topic = NULL, *name, *tnick = NULL; TS ttime = 0; int topiClen = 0; int nicKlen = 0; +int i = 0; +Hook *h; int ismember; /* cache: IsMember() */ long flags = 0; /* cache: membership flags */ @@ -156,12 +158,20 @@ long flags = 0; /* cache: membership flags */ if (!topic) /* only asking for topic */ { - if ((chptr->mode.mode & MODE_OPERONLY && !IsAnOper(sptr) && !ismember) || - (chptr->mode.mode & MODE_ADMONLY && !IsAdmin(sptr) && !ismember) || - (is_banned(sptr,chptr,BANCHK_JOIN) && !IsAnOper(sptr) && !ismember)) { + for (h = Hooks[HOOKTYPE_VIEW_TOPIC_OUTSIDE_CHANNEl]; h; h = h->next) + { + i = (*(h->func.intfunc))(sptr,chptr); + if (i != HOOK_CONTINUE) + break; + } + + /* If you're not a member, and you can't view outside channel, deny */ + if ((!ismember && i == HOOK_DENY) || (is_banned(sptr,chptr,BANCHK_JOIN) && !IsAnOper(sptr))) + { sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0], name); return 0; } + if (!chptr->topic) sendto_one(sptr, rpl_str(RPL_NOTOPIC), me.name, parv[0], chptr->chname);