diff --git a/doc/conf/modules.full.conf b/doc/conf/modules.full.conf index 97d4e1ffd..c777da77b 100644 --- a/doc/conf/modules.full.conf +++ b/doc/conf/modules.full.conf @@ -164,10 +164,11 @@ loadmodule "chanmodes/secureonly"; /* +z */ /*** User modes ***/ -loadmodule "usermodes/bot"; /* +B */ -loadmodule "usermodes/noctcp"; /* +T */ -loadmodule "usermodes/censor"; /* +G */ -loadmodule "usermodes/showwhois"; /* +W */ +loadmodule "usermodes/bot"; /* +B (mark yourself as a bot) */ +loadmodule "usermodes/noctcp"; /* +T (block CTCP's) */ +loadmodule "usermodes/censor"; /* +G (censor bad words) */ +loadmodule "usermodes/showwhois"; /* +W (show if someone does /WHOIS) */ +loadmodule "usermodes/nokick"; /* +q (unkickable oper) */ /*** Extended Bans ***/ diff --git a/include/h.h b/include/h.h index a80ed621a..9a029b20b 100644 --- a/include/h.h +++ b/include/h.h @@ -408,7 +408,6 @@ extern MODVAR long UMODE_SERVICES; /* 0x4000 services */ extern MODVAR long UMODE_HIDE; /* 0x8000 Hide from Nukes */ extern MODVAR long UMODE_NETADMIN; /* 0x10000 Network Admin */ extern MODVAR long UMODE_COADMIN; /* 0x80000 Co Admin */ -extern MODVAR long UMODE_KIX; /* 0x200000 usermode +q */ extern MODVAR long UMODE_SECURE; /* 0x800000 User is a secure connect */ extern MODVAR long UMODE_VICTIM; /* 0x8000000 Intentional Victim */ extern MODVAR long UMODE_DEAF; /* 0x10000000 Deaf */ diff --git a/include/struct.h b/include/struct.h index b6de86cd4..30595e861 100644 --- a/include/struct.h +++ b/include/struct.h @@ -360,7 +360,6 @@ typedef OperPermission (*OperClassEntryEvalCallback)(OperClassACLEntryVar* varia #define IsClientF(x) ((x)->user->snomask & SNO_CLIENT) #define IsFloodF(x) ((x)->user->snomask & SNO_FLOOD) #define IsEyes(x) ((x)->user->snomask & SNO_EYES) -#define IsKix(x) ((x)->umodes & UMODE_KIX) #define IsAdmin(x) ((x)->umodes & UMODE_ADMIN) #define IsNetAdmin(x) ((x)->umodes & UMODE_NETADMIN) @@ -537,17 +536,15 @@ typedef OperPermission (*OperClassEntryEvalCallback)(OperClassACLEntryVar* varia #define OFLAG_TKL 0x10000000 /* can use G:lines and shuns */ #define OFLAG_GZL 0x20000000 /* can use global Z:lines */ #define OFLAG_OVERRIDE 0x40000000 /* can use oper-override */ -#define OFLAG_UMODEQ 0x80000000 /* can set +q */ #define OFLAG_LOCAL (OFLAG_REHASH|OFLAG_GLOBOP|OFLAG_WALLOP|OFLAG_LOCOP|OFLAG_LROUTE|OFLAG_LKILL|OFLAG_KLINE|OFLAG_UNKLINE|OFLAG_LNOTICE) #define OFLAG_GLOBAL (OFLAG_LOCAL|OFLAG_GROUTE|OFLAG_GKILL|OFLAG_GNOTICE) #define OFLAG_ISGLOBAL (OFLAG_GROUTE|OFLAG_GKILL|OFLAG_GNOTICE|OFLAG_TKL|OFLAG_GZL|OFLAG_OVERRIDE) -#define OFLAG_NADMIN (OFLAG_NETADMIN | OFLAG_SADMIN | OFLAG_ADMIN | OFLAG_GLOBAL | OFLAG_UMODEQ | OFLAG_DCCDENY) +#define OFLAG_NADMIN (OFLAG_NETADMIN | OFLAG_SADMIN | OFLAG_ADMIN | OFLAG_GLOBAL | OFLAG_DCCDENY) #define OFLAG_ADMIN_ (OFLAG_ADMIN | OFLAG_GLOBAL | OFLAG_DCCDENY) #define OFLAG_COADMIN_ (OFLAG_COADMIN | OFLAG_GLOBAL | OFLAG_DCCDENY) -#define OFLAG_SADMIN_ (OFLAG_SADMIN | OFLAG_GLOBAL | OFLAG_UMODEQ | OFLAG_DCCDENY) +#define OFLAG_SADMIN_ (OFLAG_SADMIN | OFLAG_GLOBAL | OFLAG_DCCDENY) #define OPCanOverride(x) ((x)->oflag & OFLAG_OVERRIDE) -#define OPCanUmodeq(x) ((x)->oflag & OFLAG_UMODEQ) #define OPCanDCCDeny(x) ((x)->oflag & OFLAG_DCCDENY) #define OPCanTKL(x) ((x)->oflag & OFLAG_TKL) #define OPCanGZL(x) ((x)->oflag & OFLAG_GZL) diff --git a/src/modules/chanmodes/nokick.c b/src/modules/chanmodes/nokick.c index 45886342b..ae8c0f8fb 100644 --- a/src/modules/chanmodes/nokick.c +++ b/src/modules/chanmodes/nokick.c @@ -50,11 +50,10 @@ ModuleHeader MOD_HEADER(nokick) }; Cmode_t EXTCMODE_NOKICK; -static char errMsg[2048]; #define IsNoKick(chptr) (chptr->mode.extmode & EXTCMODE_NOKICK) -DLLFUNC char * nokick_check (aClient* sptr, aClient* who, aChannel *chptr, char* comment, long sptr_flags, long who_flags); +int nokick_check (aClient* sptr, aClient* who, aChannel *chptr, char* comment, long sptr_flags, long who_flags, char **reject_reason); DLLFUNC int MOD_TEST(nokick)(ModuleInfo *modinfo) { @@ -71,7 +70,7 @@ DLLFUNC int MOD_INIT(nokick)(ModuleInfo *modinfo) req.is_ok = extcmode_default_requirechop; CmodeAdd(modinfo->handle, req, &EXTCMODE_NOKICK); - HookAddPCharEx(modinfo->handle, HOOKTYPE_CAN_KICK, nokick_check); + HookAddEx(modinfo->handle, HOOKTYPE_CAN_KICK, nokick_check); MARK_AS_OFFICIAL_MODULE(modinfo); @@ -88,18 +87,19 @@ DLLFUNC int MOD_UNLOAD(nokick)(int module_unload) return MOD_SUCCESS; } -DLLFUNC char * nokick_check (aClient* sptr, aClient* who, aChannel *chptr, char* comment, long sptr_flags, long who_flags) +int nokick_check (aClient* sptr, aClient* who, aChannel *chptr, char* comment, long sptr_flags, long who_flags, char **reject_reason) { + static char errmsg[256]; if (MyClient(sptr) && IsNoKick(chptr)) { - /* As a warning, this is not thread safe... */ - ircsnprintf(errMsg,sizeof(errMsg),err_str(ERR_CANNOTDOCOMMAND), + ircsnprintf(errmsg, sizeof(errmsg), err_str(ERR_CANNOTDOCOMMAND), me.name, sptr->name, "KICK", "channel is +Q"); - return errMsg; + *reject_reason = errmsg; + return EX_DENY; /* Deny, but let opers override if necessary. */ } - return 0; + return EX_ALLOW; } diff --git a/src/modules/m_kick.c b/src/modules/m_kick.c index 79f1aa4fc..eb47c42f0 100644 --- a/src/modules/m_kick.c +++ b/src/modules/m_kick.c @@ -94,6 +94,7 @@ CMD_FUNC(m_kick) Membership *lp; Hook *h; int i = 0; + int ret, strict_ret; if (parc < 3 || *parv[1] == '\0') { @@ -147,35 +148,31 @@ CMD_FUNC(m_kick) * a remote kick should always be allowed (pass through). -- Syzop */ - /* applies to everyone (well except remote/ulines :p) */ - if (IsKix(who) && !IsULine(sptr) && MyClient(sptr)) - { - if (!IsNetAdmin(sptr)) - { - char errbuf[NICKLEN+10]; - ircsnprintf(errbuf, sizeof(errbuf), "%s is +q", who->name); - sendto_one(sptr, err_str(ERR_CANNOTDOCOMMAND), - me.name, sptr->name, "KICK", - errbuf); - sendnotice(who, - "*** q: %s tried to kick you from channel %s (%s)", - parv[0], - chptr->chname, comment); - goto deny; - } - } - /* Store "who" access flags */ who_flags = get_access(who, chptr); badkick = NULL; + ret = 0; + strict_ret = EX_ALLOW; for (h = Hooks[HOOKTYPE_CAN_KICK]; h; h = h->next) { - badkick = (*(h->func.pcharfunc))(sptr, who, chptr, comment, sptr_flags, who_flags); - if (badkick) + ret = (*(h->func.intfunc))(sptr, who, chptr, comment, sptr_flags, who_flags, &badkick); + + if (ret == EX_DENY) + strict_ret = ret; + else if (ret == EX_ALWAYS_DENY) break; } - if (badkick) + if (ret == EX_ALWAYS_DENY) + { + if (MyClient(sptr) && badkick) + sendto_one(sptr, "%s", badkick); /* send error, if any */ + + if (MyClient(sptr)) + continue; /* reject the kick (note: we never block remote kicks) */ + } + + if (ret == EX_DENY) { /* If set it means 'not allowed to kick'.. now check if (s)he can override that.. */ if (op_can_override(sptr)) @@ -190,12 +187,10 @@ CMD_FUNC(m_kick) goto attack; /* all other checks don't matter anymore (and could cause double msgs) */ } else { /* Not an oper overriding */ - if (MyClient(sptr)) - { - /* Send the error message prepared by the can_kick hook and deny the kick */ - sendto_one(sptr, "%s", badkick); - continue; - } + if (MyClient(sptr) && badkick) + sendto_one(sptr, "%s", badkick); /* send error, if any */ + + continue; /* reject the kick */ } } diff --git a/src/modules/m_mode.c b/src/modules/m_mode.c index 80a4a5c26..df819902c 100644 --- a/src/modules/m_mode.c +++ b/src/modules/m_mode.c @@ -1758,8 +1758,6 @@ DLLFUNC CMD_FUNC(_m_umode) */ if (MyClient(sptr)) { - if ((sptr->umodes & UMODE_KIX) && (!OPCanUmodeq(sptr) || !IsAnOper(sptr))) - sptr->umodes &= ~UMODE_KIX; if ((sptr->umodes & UMODE_SECURE) && !IsSecure(sptr)) sptr->umodes &= ~UMODE_SECURE; if (!(sptr->umodes & UMODE_SECURE) && IsSecure(sptr)) diff --git a/src/modules/m_svsnoop.c b/src/modules/m_svsnoop.c index fa1c3510a..8efce9325 100644 --- a/src/modules/m_svsnoop.c +++ b/src/modules/m_svsnoop.c @@ -103,7 +103,7 @@ long oldumodes; oldumodes = acptr->umodes; acptr->umodes &= ~(UMODE_OPER | UMODE_LOCOP | UMODE_SERVICES | UMODE_SADMIN | UMODE_ADMIN | - UMODE_NETADMIN | UMODE_KIX | + UMODE_NETADMIN | UMODE_DEAF | UMODE_HIDEOPER | UMODE_FAILOP | UMODE_COADMIN | UMODE_VICTIM); acptr->oflag = 0; diff --git a/src/modules/m_svso.c b/src/modules/m_svso.c index d5ee69f2d..293e5ff5a 100644 --- a/src/modules/m_svso.c +++ b/src/modules/m_svso.c @@ -76,7 +76,6 @@ static int oper_access[] = { OFLAG_TKL, 't', OFLAG_GZL, 'Z', OFLAG_OVERRIDE, 'v', - OFLAG_UMODEQ, 'q', OFLAG_DCCDENY, 'd', OFLAG_ADDLINE, 'X', OFLAG_TSCTL, 'T', @@ -169,7 +168,7 @@ int m_svso(aClient *cptr, aClient *sptr, int parc, char *parv[]) acptr->umodes &= ~(UMODE_NETADMIN); acptr->umodes &= - ~(UMODE_KIX | UMODE_DEAF | UMODE_HIDEOPER | UMODE_VICTIM); + ~(UMODE_DEAF | UMODE_HIDEOPER | UMODE_VICTIM); acptr->oflag = 0; remove_oper_snomasks(acptr); RunHook2(HOOKTYPE_LOCAL_OPER, acptr, 0); diff --git a/src/modules/usermodes/Makefile.in b/src/modules/usermodes/Makefile.in index 5a5d1eedb..99994d361 100644 --- a/src/modules/usermodes/Makefile.in +++ b/src/modules/usermodes/Makefile.in @@ -30,7 +30,7 @@ INCLUDES = ../../include/auth.h ../../include/badwords.h ../../include/channel.h ../../include/version.h ../../include/whowas.h R_MODULES=\ - noctcp.so censor.so bot.so showwhois.so + noctcp.so censor.so bot.so showwhois.so nokick.so MODULES=$(R_MODULES) MODULEFLAGS=@MODULEFLAGS@ @@ -67,3 +67,7 @@ bot.so: bot.c $(INCLUDES) showwhois.so: showwhois.c $(INCLUDES) $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \ -o showwhois.so showwhois.c + +nokick.so: nokick.c $(INCLUDES) + $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \ + -o nokick.so nokick.c diff --git a/src/modules/usermodes/nokick.c b/src/modules/usermodes/nokick.c new file mode 100644 index 000000000..5ffa262e3 --- /dev/null +++ b/src/modules/usermodes/nokick.c @@ -0,0 +1,87 @@ +/* + * Prevents you from being kicked (User mode +q) + * (C) Copyright 2000-.. Bram Matthys (Syzop) 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 "unrealircd.h" + +#define IsNokick(cptr) (cptr->umodes & UMODE_NOKICK) + +/* Module header */ +ModuleHeader MOD_HEADER(nokick) + = { + "usermodes/nokick", + "$Id$", + "User Mode +q", + "3.2-b8-1", + NULL + }; + +/* Global variables */ +long UMODE_NOKICK = 0L; + +/* Forward declarations */ +int nokick_can_kick(aClient *sptr, aClient *target, aChannel *chptr, + char *comment, long sptr_flags, long target_flags, char **reject_reason); + +DLLFUNC int MOD_TEST(nokick)(ModuleInfo *modinfo) +{ + return MOD_SUCCESS; +} + +DLLFUNC int MOD_INIT(nokick)(ModuleInfo *modinfo) +{ + UmodeAdd(modinfo->handle, 'q', UMODE_GLOBAL, umode_allow_opers, &UMODE_NOKICK); // TODO: limit more!! + + HookAddEx(modinfo->handle, HOOKTYPE_CAN_KICK, nokick_can_kick); + + MARK_AS_OFFICIAL_MODULE(modinfo); + return MOD_SUCCESS; +} + +DLLFUNC int MOD_LOAD(nokick)(int module_load) +{ + return MOD_SUCCESS; +} + +DLLFUNC int MOD_UNLOAD(nokick)(int module_unload) +{ + return MOD_SUCCESS; +} + +int nokick_can_kick(aClient *sptr, aClient *target, aChannel *chptr, char *comment, + long sptr_flags, long target_flags, char **reject_reason) +{ + static char errmsg[NICKLEN+32]; + + if (IsNokick(target) && !IsULine(sptr) && MyClient(sptr) && !IsNetAdmin(sptr)) + { + ircsnprintf(errmsg, sizeof(errmsg), err_str(ERR_CANNOTDOCOMMAND), + me.name, sptr->name, "KICK", + "user is unkickable (user mode +q)"); + + *reject_reason = errmsg; + + sendnotice(target, + "*** umode q: %s tried to kick you from channel %s (%s)", + sptr->name, chptr->chname, comment); + + return EX_ALWAYS_DENY; + } + + return EX_ALLOW; +} diff --git a/src/s_conf.c b/src/s_conf.c index 66981fb1c..9289fb8d5 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -186,7 +186,6 @@ static int _OldOperFlags[] = { OFLAG_TKL, 't', OFLAG_GZL, 'Z', OFLAG_OVERRIDE, 'v', - OFLAG_UMODEQ, 'q', OFLAG_DCCDENY, 'd', OFLAG_ADDLINE, 'X', OFLAG_TSCTL, 'T', @@ -212,7 +211,6 @@ static OperFlag _OperFlags[] = { { OFLAG_OVERRIDE, "can_override" }, { OFLAG_REHASH, "can_rehash" }, { OFLAG_RESTART, "can_restart" }, - { OFLAG_UMODEQ, "can_setq" }, { OFLAG_TSCTL, "can_tsctl" }, { OFLAG_UNKLINE, "can_unkline" }, { OFLAG_WALLOP, "can_wallops" }, diff --git a/src/s_svs.c b/src/s_svs.c index d69e8015c..b5476dcf2 100644 --- a/src/s_svs.c +++ b/src/s_svs.c @@ -74,7 +74,6 @@ MODVAR int oper_access[] = { OFLAG_TKL, 't', OFLAG_GZL, 'Z', OFLAG_OVERRIDE, 'v', - OFLAG_UMODEQ, 'q', OFLAG_DCCDENY, 'd', OFLAG_ADDLINE, 'X', OFLAG_TSCTL, 'T', diff --git a/src/umodes.c b/src/umodes.c index 6d06980c0..38903ee41 100644 --- a/src/umodes.c +++ b/src/umodes.c @@ -65,7 +65,6 @@ long UMODE_SERVICES = 0L; /* services */ long UMODE_HIDE = 0L; /* Hide from Nukes */ long UMODE_NETADMIN = 0L; /* Network Admin */ long UMODE_COADMIN = 0L; /* Co Admin */ -long UMODE_KIX = 0L; /* usermode +q */ long UMODE_SECURE = 0L; /* User is a secure connect */ long UMODE_VICTIM = 0L; /* Intentional Victim */ long UMODE_DEAF = 0L; /* Deaf */ @@ -137,7 +136,6 @@ void umode_init(void) UmodeAdd(NULL, 'x', UMODE_GLOBAL, NULL, &UMODE_HIDE); UmodeAdd(NULL, 'N', UMODE_GLOBAL, umode_allow_opers, &UMODE_NETADMIN); UmodeAdd(NULL, 'C', UMODE_GLOBAL, umode_allow_opers, &UMODE_COADMIN); - UmodeAdd(NULL, 'q', UMODE_GLOBAL, umode_allow_opers, &UMODE_KIX); UmodeAdd(NULL, 'z', UMODE_GLOBAL, NULL, &UMODE_SECURE); UmodeAdd(NULL, 'v', UMODE_GLOBAL, umode_allow_opers, &UMODE_VICTIM); UmodeAdd(NULL, 'd', UMODE_GLOBAL, NULL, &UMODE_DEAF);