From 95eeb973be84e391b553e5fc9bdebdc36a78598d Mon Sep 17 00:00:00 2001 From: Bleep Date: Mon, 29 Nov 1999 00:26:42 +0000 Subject: [PATCH] Author: David M Log message: - added configuration option to allow opers to set modes on local channels even if they are not oped. - added configuration option to allow opers to walk through modes on local channels, since they are required to be on a channel to be able to set modes on it. - added configuration option to prevent opers from being deoped from local channels. - added configuration option to allow opers to bypass the maximum number of channels per user. Detailed behavior changes: If the admin so choses, opers can now use /mode on local channels even if they are not oped. In that case, a server notice is generated (SNO_HACK4), and to clients, it appears that the local server set the mode. The server notice is not propagated to other servers. If activated in the configuration, opers can join local channels under any circumstances. Doing so does not generate a server notice. Note that the oper can still not talk in the channel if he is banned. Preventing opers from being deoped on local channels results in the user attempting the deop to receive a new numeric reply (498) stating he cannot kick or deop an oper on a local channel. An oper can deop himself, though. Provided again to fill the service gaps on local channels, allowing admins who want it to implement "services" for their local channels. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@10 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- .patches | 2 +- ChangeLog | 5 ++- config/config-sh.in | 4 ++ include/channel.h | 4 ++ include/numeric.h | 2 + ircd/channel.c | 94 +++++++++++++++++++++++++++++++++++++++++---- ircd/s_debug.c | 12 ++++++ ircd/s_err.c | 2 +- 8 files changed, 115 insertions(+), 10 deletions(-) diff --git a/.patches b/.patches index 5682e37..f8629dc 100644 --- a/.patches +++ b/.patches @@ -1 +1 @@ -ircu2.10.07+ +ircu2.10.07+.03 diff --git a/ChangeLog b/ChangeLog index 209dba1..f5e51aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,15 @@ # # ChangeLog for Undernet ircu Servers # -# $Id: ChangeLog,v 1.3 1999-11-28 01:36:25 danny Exp $ +# $Id: ChangeLog,v 1.4 1999-11-29 00:26:41 bleep Exp $ # # Please insert new entries on the top of the list, a one or two line comment # is sufficient. Please include your name on the entries we know who to blame. # Please keep lines < 80 chars. #------------------------------------------------------------------------------- +* config-sh.in, channel.h, numeric.h, channel.c, s_debug.c, s_err.c: + add lchanmode patch by CaptJay, add symbols to incredibly long + feature string. Bump patchlevel to .03 --Bleep * list.h list.c s_conf.h s_conf.c opercmds.c: badchan patch 2 seperate settings, allow global, and allow local. currently allow_local is 'unapproved' for use on undernet. --WildThang diff --git a/config/config-sh.in b/config/config-sh.in index 0fe0599..82f75de 100644 --- a/config/config-sh.in +++ b/config/config-sh.in @@ -347,6 +347,10 @@ comment 'Oper commands' bool 'Allow local opers to use the RESTART command' LOCOP_RESTART bool 'Allow local opers to use the DIE command' LOCOP_DIE bool 'Allow local opers to add local G-lines' LOCOP_LGLINE y + bool 'Allow local/global opers to be on any number of channels' OPER_NO_CHAN_LIMIT y + bool 'Allow local/global opers to set modes on local channels' OPER_MODE_LCHAN y + bool 'Allow local/global opers to walk through local channels modes' OPER_WALK_THROUGH_LMODES n + bool 'Prevent local/global opers from being kicked or deoped on local channels' NO_OPER_DEOP_LCHAN n endmenu mainmenu_option next_comment diff --git a/include/channel.h b/include/channel.h index 53feffe..167e9cf 100644 --- a/include/channel.h +++ b/include/channel.h @@ -99,6 +99,10 @@ #define IsChannelName(name) (*(name) == '#' || \ IsModelessChannel(name) || IsLocalChannel(name)) +/* Check if a sptr is an oper, and chptr is a local channel. */ + +#define IsOperOnLocalChannel(sptr,chname) ((IsOper(sptr)) && (IsLocalChannel(chname))) + /* used in SetMode() in channel.c and m_umode() in s_msg.c */ #define MODE_NULL 0 diff --git a/include/numeric.h b/include/numeric.h index ae886e7..06b3337 100644 --- a/include/numeric.h +++ b/include/numeric.h @@ -114,6 +114,8 @@ #define ERR_NOOPERHOST 491 +#define ERR_ISOPERLCHAN 498 /* Undernet extension */ + #define ERR_UMODEUNKNOWNFLAG 501 #define ERR_USERSDONTMATCH 502 diff --git a/ircd/channel.c b/ircd/channel.c index 133d1ee..27b6e95 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -99,6 +99,12 @@ static char nparabuf[MODEBUFLEN]; */ #define MAGIC_REMOTE_JOIN_TS 1270080000 +/* + * Use a global variable to remember if an oper set a mode on a local channel. Ugly, + * but the only way to do it without changing set_mode intensively. + */ +int LocalChanOperMode = 0; + /* * return the length (>=0) of a chain of links. */ @@ -821,6 +827,8 @@ int m_mode(aClient *cptr, aClient *sptr, int parc, char *parv[]) return 0; } + LocalChanOperMode = 0; + if (!(sendts = set_mode(cptr, sptr, chptr, parc - 2, parv + 2, modebuf, parabuf, nparabuf, &badop))) { @@ -835,8 +843,20 @@ int m_mode(aClient *cptr, aClient *sptr, int parc, char *parv[]) if (strlen(modebuf) > (size_t)1 || sendts > 0) { if (badop != 2 && strlen(modebuf) > (size_t)1) + { +#ifdef OPER_MODE_LCHAN + if (LocalChanOperMode) { + sendto_channel_butserv(chptr, &me, ":%s MODE %s %s %s", + me.name, chptr->chname, modebuf, parabuf); + sendto_op_mask(SNO_HACK4, + "OPER MODE: %s MODE %s %s %s", + me.name,chptr->chname,modebuf,parabuf); + } + else +#endif sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s %s", parv[0], chptr->chname, modebuf, parabuf); + } if (IsLocalChannel(chptr->chname)) return 0; /* We send a creationtime of 0, to mark it as a hack --Run */ @@ -1039,6 +1059,11 @@ static int set_mode(aClient *cptr, aClient *sptr, aChannel *chptr, int parc, if (!(IsServer(cptr) || (tmp = IsMember(sptr, chptr)))) return 0; +#ifdef OPER_MODE_LCHAN + if (IsOperOnLocalChannel(sptr, chptr->chname) && !(tmp->flags & CHFL_CHANOP)) + LocalChanOperMode = 1; +#endif + newmode = mode->mode; while (curr && *curr) @@ -1103,6 +1128,19 @@ static int set_mode(aClient *cptr, aClient *sptr, aChannel *chptr, int parc, cptr->name, parv[0], chptr->chname); break; } +#ifdef NO_OPER_DEOP_LCHAN + /* + * if the user is an oper on a local channel, prevent him + * from being deoped. that oper can deop himself though. + */ + if (whatt == MODE_DEL && IsOperOnLocalChannel(who, chptr->chname) && + (who != sptr) && MyUser(cptr) && *curr == 'o') + { + sendto_one(cptr, err_str(ERR_ISOPERLCHAN), me.name, + cptr->name, parv[0], chptr->chname); + break; + } +#endif if (whatt == MODE_ADD) { lp = &chops[opcnt++]; @@ -1331,8 +1369,17 @@ static int set_mode(aClient *cptr, aClient *sptr, aChannel *chptr, int parc, } } /* end of while loop for MODE processing */ - /* Now reject non chan ops */ + /* + * Now reject non chan ops. Accept modes from opers on local channels + * even if they are deopped + */ +#ifdef OPER_MODE_LCHAN + if (!IsServer(cptr) && + (!tmp || !((tmp->flags & CHFL_CHANOP) || + IsOperOnLocalChannel(sptr, chptr->chname)))) +#else if (!IsServer(cptr) && (!tmp || !(tmp->flags & CHFL_CHANOP))) +#endif { *badop = 0; return (opcnt || newmode != mode->mode || limitset || keychange) ? 0 : -1; @@ -1345,7 +1392,13 @@ static int set_mode(aClient *cptr, aClient *sptr, aChannel *chptr, int parc, (aconf = find_conf_host(cptr->confs, sptr->name, CONF_UWORLD))) *badop = 4; +#ifdef OPER_MODE_LCHAN + bounce = (*badop == 1 || *badop == 2 || + (is_deopped(sptr, chptr) && + !IsOperOnLocalChannel(sptr, chptr->chname))) ? 1 : 0; +#else bounce = (*badop == 1 || *badop == 2 || is_deopped(sptr, chptr)) ? 1 : 0; +#endif whatt = 0; for (ip = flags; *ip; ip += 2) @@ -1935,8 +1988,14 @@ static int can_join(aClient *sptr, aChannel *chptr, char *key) { Reg1 Link *lp; - /* Now a banned user CAN join if invited -- Nemesi */ - /* Now a user CAN escape channel limit if invited -- bfriendly */ +#ifdef OPER_WALK_THROUGH_LMODES + if (IsOperOnLocalChannel(sptr, chptr->chname)) + return 0; +#endif + /* + * Now a banned user CAN join if invited -- Nemesi + * Now a user CAN escape channel limit if invited -- bfriendly + */ if ((chptr->mode.mode & MODE_INVITEONLY) || (is_banned(sptr, chptr, NULL) || (chptr->mode.limit && chptr->users >= chptr->mode.limit))) { @@ -1947,9 +2006,11 @@ static int can_join(aClient *sptr, aChannel *chptr, char *key) { if (chptr->mode.limit && chptr->users >= chptr->mode.limit) return (ERR_CHANNELISFULL); - /* This can return an "Invite only" msg instead of the "You are banned" - if _both_ conditions are true, but who can say what is more - appropriate ? checking again IsBanned would be _SO_ cpu-xpensive ! */ + /* + * This can return an "Invite only" msg instead of the "You are banned" + * if _both_ conditions are true, but who can say what is more + * appropriate ? checking again IsBanned would be _SO_ cpu-xpensive ! + */ return ((chptr->mode.mode & MODE_INVITEONLY) ? ERR_INVITEONLYCHAN : ERR_BANNEDFROMCHAN); } @@ -2302,7 +2363,14 @@ int m_join(aClient *cptr, aClient *sptr, int parc, char *parv[]) sendcreate = 1; } - if (sptr->user->joined >= MAXCHANNELSPERUSER) +#ifdef OPER_NO_CHAN_LIMIT + /* + * Opers are allowed to join any number of channels + */ + if (sptr->user->joined >= MAXCHANNELSPERUSER && !IsOper(sptr)) +#else + if (sptr->user->joined >= MAXCHANNELSPERUSER) +#endif { chptr = get_channel(sptr, name, !CREATE); sendto_one(sptr, err_str(ERR_TOOMANYCHANNELS), @@ -3592,6 +3660,18 @@ int m_kick(aClient *cptr, aClient *sptr, int parc, char *parv[]) parv[0], who->name, chptr->chname); return 0; } +#ifdef NO_OPER_DEOP_LCHAN + /* + * Prevent kicking opers from local channels -DM- + */ + if (IsOperOnLocalChannel(who, chptr->chname)) + { + sendto_one(sptr, err_str(ERR_ISOPERLCHAN), me.name, + parv[0], who->name, chptr->chname); + return 0; + } +#endif + if (((lp = find_user_link(chptr->members, who)) && !(lp->flags & CHFL_ZOMBIE)) || IsServer(sptr)) { diff --git a/ircd/s_debug.c b/ircd/s_debug.c index b6fa0f6..5ba1705 100644 --- a/ircd/s_debug.c +++ b/ircd/s_debug.c @@ -101,6 +101,12 @@ char serveropts[] = { #ifdef OPER_REHASH 'E', #endif +#ifdef OPER_NO_CHAN_LIMIT + 'F', +#endif +#ifdef OPER_MODE_LCHAN + 'f', +#endif #ifdef HUB 'H', #endif @@ -121,12 +127,18 @@ char serveropts[] = { #ifdef LEAST_IDLE 'L', #endif +#ifdef OPER_WALK_THROUGH_LMODES + 'l', +#endif #ifdef IDLE_FROM_MSG 'M', #endif #ifdef USEONE 'O', #endif +#ifdef NO_OPER_DEOP_LCHAN + 'o', +#endif #ifdef CRYPT_OPER_PASSWORD 'p', #endif diff --git a/ircd/s_err.c b/ircd/s_err.c index 8b2b589..9689415 100644 --- a/ircd/s_err.c +++ b/ircd/s_err.c @@ -258,7 +258,7 @@ static Numeric numeric_errors[] = { /* 497 */ {0, (char *)NULL}, /* 498 */ - {0, (char *)NULL}, + {ERR_ISOPERLCHAN, "%s %s :Cannot kick or deop an IRC Operator on a local channel"}, /* 499 */ {0, (char *)NULL}, /* 500 */ -- 2.20.1