From 8cb381cc8efd931e9f3f1c8f77efbe8b284a3ef5 Mon Sep 17 00:00:00 2001 From: Bram Matthys Date: Sat, 20 Jun 2015 21:09:17 +0200 Subject: [PATCH] Move user mode +S to usermodes/servicebot. TODO: hide channels in /WHOIS and some more testing. Tomorrow.. ;) --- doc/conf/modules.full.conf | 1 + include/h.h | 2 +- include/modules.h | 2 + include/struct.h | 2 - src/modules/m_kick.c | 3 +- src/modules/m_kill.c | 21 +++-- src/modules/m_mode.c | 58 ++++++++---- src/modules/m_svsnoop.c | 2 +- src/modules/m_svso.c | 10 +-- src/modules/m_whois.c | 8 +- src/modules/usermodes/Makefile.in | 6 +- src/modules/usermodes/servicebot.c | 136 +++++++++++++++++++++++++++++ src/umodes.c | 9 +- 13 files changed, 217 insertions(+), 43 deletions(-) create mode 100644 src/modules/usermodes/servicebot.c diff --git a/doc/conf/modules.full.conf b/doc/conf/modules.full.conf index c777da77b..22cd8c1c7 100644 --- a/doc/conf/modules.full.conf +++ b/doc/conf/modules.full.conf @@ -165,6 +165,7 @@ loadmodule "chanmodes/secureonly"; /* +z */ /*** User modes ***/ loadmodule "usermodes/bot"; /* +B (mark yourself as a bot) */ +loadmodule "usermodes/servicebot"; /* +S (service bot) */ loadmodule "usermodes/noctcp"; /* +T (block CTCP's) */ loadmodule "usermodes/censor"; /* +G (censor bad words) */ loadmodule "usermodes/showwhois"; /* +W (show if someone does /WHOIS) */ diff --git a/include/h.h b/include/h.h index 9a029b20b..9bf4ac3cc 100644 --- a/include/h.h +++ b/include/h.h @@ -332,6 +332,7 @@ extern long umode_get(char, int, int (*)(aClient *, int)); #define umode_gget(x) umode_get(x, 1, 0); extern int umode_allow_all(aClient *sptr, int what); extern int umode_allow_opers(aClient *sptr, int what); +extern int umode_allow_none(aClient *sptr, int what); extern int umode_delete(char ch, long val); extern void send_umode(aClient *, aClient *, long, long, char *); extern void send_umode_out(aClient *, aClient *, long); @@ -404,7 +405,6 @@ extern MODVAR long UMODE_ADMIN; /* 0x0080 Admin */ extern MODVAR long UMODE_SERVNOTICE;/* 0x0100 server notices such as kill */ extern MODVAR long UMODE_LOCOP; /* 0x0200 Local operator -- SRB */ extern MODVAR long UMODE_RGSTRONLY; /* 0x0400 Only reg nick message */ -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 */ diff --git a/include/modules.h b/include/modules.h index 1ecf8ede8..078c4470c 100644 --- a/include/modules.h +++ b/include/modules.h @@ -746,6 +746,8 @@ extern char *moddata_client_get(aClient *acptr, char *varname); #define HOOKTYPE_WHOIS 81 #define HOOKTYPE_CHECK_INIT 82 #define HOOKTYPE_WHO_STATUS 83 +#define HOOKTYPE_MODE_DEOP 84 +#define HOOKTYPE_PRE_KILL 85 /* Hook return values */ #define HOOK_CONTINUE 0 diff --git a/include/struct.h b/include/struct.h index 30595e861..ac8964f32 100644 --- a/include/struct.h +++ b/include/struct.h @@ -369,7 +369,6 @@ typedef OperPermission (*OperClassEntryEvalCallback)(OperClassACLEntryVar* varia #define IsOper(x) ((x)->umodes & UMODE_OPER) #define IsLocOp(x) ((x)->umodes & UMODE_LOCOP) #define IsInvisible(x) ((x)->umodes & UMODE_INVISIBLE) -#define IsServices(x) ((x)->umodes & UMODE_SERVICES) #define IsAnOper(x) ((x)->umodes & (UMODE_OPER|UMODE_LOCOP)) #define IsARegNick(x) ((x)->umodes & (UMODE_REGNICK)) #define IsRegNick(x) ((x)->umodes & UMODE_REGNICK) @@ -449,7 +448,6 @@ typedef OperPermission (*OperClassEntryEvalCallback)(OperClassACLEntryVar* varia #define ClearFailops(x) ((x)->umodes &= ~UMODE_FAILOP) #define ClearOper(x) ((x)->umodes &= ~UMODE_OPER) #define ClearInvisible(x) ((x)->umodes &= ~UMODE_INVISIBLE) -#define ClearServices(x) ((x)->umodes &= ~UMODE_SERVICES) #define ClearWallops(x) ((x)->umodes &= ~UMODE_WALLOP) #define ClearDNS(x) ((x)->flags &= ~FLAGS_DOINGDNS) #define ClearAuth(x) ((x)->flags &= ~FLAGS_AUTH) diff --git a/src/modules/m_kick.c b/src/modules/m_kick.c index eb47c42f0..f4a778739 100644 --- a/src/modules/m_kick.c +++ b/src/modules/m_kick.c @@ -162,6 +162,7 @@ CMD_FUNC(m_kick) else if (ret == EX_ALWAYS_DENY) break; } + ret = strict_ret; /* most strict one wins */ if (ret == EX_ALWAYS_DENY) { @@ -219,7 +220,7 @@ CMD_FUNC(m_kick) } /* victim is +a or +q, we are not +q */ - if ((who_flags & (CHFL_CHANOWNER|CHFL_CHANPROT) || IsServices(who)) + if ((who_flags & (CHFL_CHANOWNER|CHFL_CHANPROT)) && !(sptr_flags & CHFL_CHANOWNER)) { if (sptr == who) goto attack; /* kicking self == ok */ diff --git a/src/modules/m_kill.c b/src/modules/m_kill.c index fd4b38cc6..b9ec01d87 100644 --- a/src/modules/m_kill.c +++ b/src/modules/m_kill.c @@ -91,9 +91,8 @@ DLLFUNC int m_kill(aClient *cptr, aClient *sptr, int parc, char *parv[]) char *oinpath = get_client_name(cptr, FALSE); char *user, *path, *killer, *nick, *p, *s; int chasing = 0, kcount = 0; - - - + Hook *h; + if (parc < 2 || *parv[1] == '\0') { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), @@ -178,12 +177,20 @@ DLLFUNC int m_kill(aClient *cptr, aClient *sptr, int parc, char *parv[]) continue; } - if (IsServices(acptr) && !(IsNetAdmin(sptr) || IsULine(sptr))) + if (MyClient(sptr)) { - sendto_one(sptr, err_str(ERR_KILLDENY), me.name, - parv[0], parv[1]); - return 0; + int ret = EX_ALLOW; + for (h = Hooks[HOOKTYPE_PRE_KILL]; h; h = h->next) + { + /* note: parameters are: sptr, victim, reason. reason can be NULL !! */ + ret = (*(h->func.intfunc))(sptr, acptr, path); + if (ret != EX_ALLOW) + break; + } + if ((ret == EX_DENY) || (ret == EX_ALWAYS_DENY)) + continue; /* reject kill for this particular user */ } + /* From here on, the kill is probably going to be successful. */ kcount++; diff --git a/src/modules/m_mode.c b/src/modules/m_mode.c index df819902c..1d24e44d0 100644 --- a/src/modules/m_mode.c +++ b/src/modules/m_mode.c @@ -782,6 +782,7 @@ int do_mode_char(aChannel *chptr, long modetype, char modechar, char *param, char *xp; int notsecure; chasing = 0; + Hook *h; if ((my_access & CHFL_HALFOP) && !is_xchanop(my_access) && !IsULine(cptr) && !op_can_override(cptr) && !samode_in_progress) @@ -913,16 +914,48 @@ int do_mode_char(aChannel *chptr, long modetype, char modechar, char *param, if (IsServer(cptr) || IsULine(cptr)) goto breaktherules; - /* Services are special! */ - if (IsServices(member->cptr) && MyClient(cptr) && !IsNetAdmin(cptr) && (what == MODE_DEL)) + if (what == MODE_DEL) { - char errbuf[NICKLEN+50]; - ircsnprintf(errbuf, sizeof(errbuf), "%s is a network service", member->cptr->name); - sendto_one(cptr, err_str(ERR_CANNOTCHANGECHANMODE), me.name, cptr->name, - modechar, errbuf); - break; - } + int ret = 0; + int strict_ret = EX_ALLOW; + char *badmode = NULL; + + for (h = Hooks[HOOKTYPE_MODE_DEOP]; h; h = h->next) + { + ret = (*(h->func.intfunc))(cptr, member->cptr, chptr, what, modechar, my_access, &badmode); + if (ret == EX_DENY) + strict_ret = ret; + else if (ret == EX_ALWAYS_DENY) + break; + } + ret = strict_ret; /* most strict one wins */ + + if (ret == EX_ALWAYS_DENY) + { + if (MyClient(cptr) && badmode) + sendto_one(cptr, "%s", badmode); /* send error message, if any */ + + if (MyClient(cptr)) + break; /* stop processing this mode */ + } + /* This probably should work but is completely untested (the operoverride stuff, I mean): */ + if (ret == EX_DENY) + { + if (!op_can_override(cptr)) + { + if (MyClient(cptr) && badmode) + sendto_one(cptr, "%s", badmode); /* send error message, if any */ + + if (MyClient(cptr)) + break; /* stop processing this mode */ + } else { + if (IsAnOper(cptr)) + opermode = 1; + } + } + } + /* This check not only prevents unprivileged users from doing a -q on chanowners, * it also protects against -o/-h/-v on them. */ @@ -1764,14 +1797,7 @@ DLLFUNC CMD_FUNC(_m_umode) sptr->umodes |= UMODE_SECURE; } } - /* - * For Services Protection... - */ - if (!IsServer(cptr) && !IsULine(sptr)) - { - if (IsServices(sptr)) - ClearServices(sptr); - } + if ((setflags & UMODE_HIDE) && !IsHidden(sptr)) sptr->umodes &= ~UMODE_SETHOST; diff --git a/src/modules/m_svsnoop.c b/src/modules/m_svsnoop.c index 8efce9325..1f9e4d0be 100644 --- a/src/modules/m_svsnoop.c +++ b/src/modules/m_svsnoop.c @@ -102,7 +102,7 @@ long oldumodes; oldumodes = acptr->umodes; acptr->umodes &= ~(UMODE_OPER | UMODE_LOCOP | - UMODE_SERVICES | UMODE_SADMIN | UMODE_ADMIN | + UMODE_SADMIN | UMODE_ADMIN | UMODE_NETADMIN | UMODE_DEAF | UMODE_HIDEOPER | UMODE_FAILOP | UMODE_COADMIN | UMODE_VICTIM); diff --git a/src/modules/m_svso.c b/src/modules/m_svso.c index 293e5ff5a..92b60781a 100644 --- a/src/modules/m_svso.c +++ b/src/modules/m_svso.c @@ -162,13 +162,9 @@ int m_svso(aClient *cptr, aClient *sptr, int parc, char *parv[]) if (!list_empty(&acptr->special_node)) list_del(&acptr->special_node); - acptr->umodes &= - ~(UMODE_OPER | UMODE_LOCOP | UMODE_SERVICES | - UMODE_SADMIN | UMODE_ADMIN | UMODE_COADMIN); - acptr->umodes &= - ~(UMODE_NETADMIN); - acptr->umodes &= - ~(UMODE_DEAF | UMODE_HIDEOPER | UMODE_VICTIM); + acptr->umodes &= ~(UMODE_OPER | UMODE_LOCOP | UMODE_SADMIN | UMODE_ADMIN | UMODE_COADMIN); + acptr->umodes &= ~(UMODE_NETADMIN); + acptr->umodes &= ~(UMODE_DEAF | UMODE_HIDEOPER | UMODE_VICTIM); acptr->oflag = 0; remove_oper_snomasks(acptr); RunHook2(HOOKTYPE_LOCAL_OPER, acptr, 0); diff --git a/src/modules/m_whois.c b/src/modules/m_whois.c index 5066e2d85..afbb9dc3e 100644 --- a/src/modules/m_whois.c +++ b/src/modules/m_whois.c @@ -192,8 +192,8 @@ DLLFUNC int m_whois(aClient *cptr, aClient *sptr, int parc, char *parv[]) showchannel = 1; if ((acptr->umodes & UMODE_HIDEWHOIS) && !IsMember(sptr, chptr) && !IsAnOper(sptr) && !OperClass_evaluateACLPath("override:whois:",sptr,NULL,chptr,NULL)) showchannel = 0; - if (IsServices(acptr) && !IsNetAdmin(sptr) && !IsSAdmin(sptr) && !OperClass_evaluateACLPath("override:whois",sptr,NULL,chptr,NULL)) - showchannel = 0; +/* if (IsServices(acptr) && !IsNetAdmin(sptr) && !IsSAdmin(sptr) && !OperClass_evaluateACLPath("override:whois",sptr,NULL,chptr,NULL)) + showchannel = 0; TODO TODO OOOOOOOOOOOOOOOOOOOOOOOOOOOOO TODODODODODOO !!!! */ if (acptr == sptr) showchannel = 1; @@ -273,7 +273,7 @@ DLLFUNC int m_whois(aClient *cptr, aClient *sptr, int parc, char *parv[]) sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0], name, user->away); - if ((IsAnOper(acptr) || IsServices(acptr)) && !hideoper) + if (IsAnOper(acptr) && !hideoper) { buf[0] = '\0'; if (IsNetAdmin(acptr)) @@ -284,8 +284,6 @@ DLLFUNC int m_whois(aClient *cptr, aClient *sptr, int parc, char *parv[]) strlcat(buf, "a Server Administrator", sizeof buf); else if (IsCoAdmin(acptr)) strlcat(buf, "a Co Administrator", sizeof buf); - else if (IsServices(acptr)) - strlcat(buf, "a Network Service", sizeof buf); else if (IsOper(acptr)) strlcat(buf, "an IRC Operator", sizeof buf); diff --git a/src/modules/usermodes/Makefile.in b/src/modules/usermodes/Makefile.in index 99994d361..cf1a6fad8 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 nokick.so + noctcp.so censor.so bot.so showwhois.so nokick.so servicebot.so MODULES=$(R_MODULES) MODULEFLAGS=@MODULEFLAGS@ @@ -71,3 +71,7 @@ showwhois.so: showwhois.c $(INCLUDES) nokick.so: nokick.c $(INCLUDES) $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \ -o nokick.so nokick.c + +servicebot.so: servicebot.c $(INCLUDES) + $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \ + -o servicebot.so servicebot.c diff --git a/src/modules/usermodes/servicebot.c b/src/modules/usermodes/servicebot.c new file mode 100644 index 000000000..6e4918304 --- /dev/null +++ b/src/modules/usermodes/servicebot.c @@ -0,0 +1,136 @@ +/* + * 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 IsServiceBot(cptr) (cptr->umodes & UMODE_SERVICEBOT) + +#define WHOIS_SERVICE_STRING ":%s 313 %s %s :is a Network Service" + +/* Module header */ +ModuleHeader MOD_HEADER(servicebot) + = { + "usermodes/servicebot", + "$Id$", + "User Mode +q", + "3.2-b8-1", + NULL + }; + +/* Global variables */ +long UMODE_SERVICEBOT = 0L; + +/* Forward declarations */ +int servicebot_can_kick(aClient *sptr, aClient *target, aChannel *chptr, + char *comment, long sptr_flags, long target_flags, char **reject_reason); +int servicebot_mode_deop(aClient *sptr, aClient *target, aChannel *chptr, + u_int what, char modechar, long my_access, char **reject_reason); +int servicebot_pre_kill(aClient *sptr, aClient *target, char *reason); +int servicebot_whois(aClient *sptr, aClient *acptr); + +DLLFUNC int MOD_TEST(servicebot)(ModuleInfo *modinfo) +{ + return MOD_SUCCESS; +} + +DLLFUNC int MOD_INIT(servicebot)(ModuleInfo *modinfo) +{ + UmodeAdd(modinfo->handle, 'S', UMODE_GLOBAL, umode_allow_none, &UMODE_SERVICEBOT); + + HookAddEx(modinfo->handle, HOOKTYPE_CAN_KICK, servicebot_can_kick); + HookAddEx(modinfo->handle, HOOKTYPE_MODE_DEOP, servicebot_mode_deop); + HookAddEx(modinfo->handle, HOOKTYPE_PRE_KILL, servicebot_pre_kill); + HookAddEx(modinfo->handle, HOOKTYPE_WHOIS, servicebot_whois); + + MARK_AS_OFFICIAL_MODULE(modinfo); + return MOD_SUCCESS; +} + +DLLFUNC int MOD_LOAD(servicebot)(int module_load) +{ + return MOD_SUCCESS; +} + +DLLFUNC int MOD_UNLOAD(servicebot)(int module_unload) +{ + return MOD_SUCCESS; +} + +int servicebot_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 (MyClient(sptr) && !IsULine(sptr) && IsServiceBot(target)) + { + char errmsg2[NICKLEN+32]; + snprintf(errmsg2, sizeof(errmsg2), "%s is a Service Bot", target->name); + + snprintf(errmsg, sizeof(errmsg), err_str(ERR_CANNOTDOCOMMAND), + me.name, sptr->name, "KICK", errmsg2); + + *reject_reason = errmsg; + + return EX_DENY; + } + + return EX_ALLOW; +} + +int servicebot_mode_deop(aClient *sptr, aClient *target, aChannel *chptr, + u_int what, char modechar, long my_access, char **reject_reason) +{ + static char errmsg[NICKLEN+32]; + + if (IsServiceBot(target) && MyClient(sptr) && !IsNetAdmin(sptr) && (what == MODE_DEL)) + { + char errmsg2[NICKLEN+32]; + snprintf(errmsg2, sizeof(errmsg2), "%s is a Service Bot", target->name); + + snprintf(errmsg, sizeof(errmsg), err_str(ERR_CANNOTCHANGECHANMODE), + me.name, sptr->name, modechar, errmsg2); + + *reject_reason = errmsg; + + return EX_DENY; + } + + return EX_ALLOW; +} + +int servicebot_pre_kill(aClient *sptr, aClient *target, char *reason) +{ + if (IsServiceBot(target) && !(IsNetAdmin(sptr) || IsULine(sptr))) + { + sendto_one(sptr, err_str(ERR_KILLDENY), me.name, + sptr->name, target->name); + return EX_ALWAYS_DENY; + } + return EX_ALLOW; +} + +int servicebot_whois(aClient *sptr, aClient *acptr) +{ + int hideoper = (IsHideOper(acptr) && (sptr != acptr) && !IsAnOper(sptr)) ? 1 : 0; + + if (IsServiceBot(acptr) && !hideoper) + sendto_one(sptr, WHOIS_SERVICE_STRING, me.name, sptr->name, acptr->name); + + return 0; +} diff --git a/src/umodes.c b/src/umodes.c index 38903ee41..ad517b7b9 100644 --- a/src/umodes.c +++ b/src/umodes.c @@ -61,7 +61,6 @@ long UMODE_ADMIN = 0L; /* Admin */ long UMODE_SERVNOTICE = 0L; /* server notices such as kill */ long UMODE_LOCOP = 0L; /* Local operator -- SRB */ long UMODE_RGSTRONLY = 0L; /* Only reg nick message */ -long UMODE_SERVICES = 0L; /* services */ long UMODE_HIDE = 0L; /* Hide from Nukes */ long UMODE_NETADMIN = 0L; /* Network Admin */ long UMODE_COADMIN = 0L; /* Co Admin */ @@ -132,7 +131,6 @@ void umode_init(void) UmodeAdd(NULL, 's', UMODE_LOCAL, NULL, &UMODE_SERVNOTICE); UmodeAdd(NULL, 'O', UMODE_LOCAL, umode_allow_opers, &UMODE_LOCOP); UmodeAdd(NULL, 'R', UMODE_GLOBAL, NULL, &UMODE_RGSTRONLY); - UmodeAdd(NULL, 'S', UMODE_GLOBAL, umode_allow_opers, &UMODE_SERVICES); 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); @@ -377,6 +375,13 @@ int umode_allow_all(aClient *sptr, int what) return 1; } +int umode_allow_none(aClient *sptr, int what) +{ + if (MyClient(sptr)) + return 0; + return 1; +} + int umode_allow_opers(aClient *sptr, int what) { if (MyClient(sptr))