Author: David M <captjay@superlink.net>
authorBleep <twhelvey1@home.com>
Mon, 29 Nov 1999 00:26:42 +0000 (00:26 +0000)
committerBleep <twhelvey1@home.com>
Mon, 29 Nov 1999 00:26:42 +0000 (00:26 +0000)
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
ChangeLog
config/config-sh.in
include/channel.h
include/numeric.h
ircd/channel.c
ircd/s_debug.c
ircd/s_err.c

index 5682e379d77097e06f658ef7fb249bef1c9925e1..f8629dc3dbfef315eb455500e5d2e138a1fbc351 100644 (file)
--- a/.patches
+++ b/.patches
@@ -1 +1 @@
-ircu2.10.07+
+ircu2.10.07+.03
index 209dba1566e8d6746e7d20eb4bda461c0f7a444d..f5e51aab088e957fc064f693292d890b1d389431 100644 (file)
--- 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
index 0fe05994a573fbdc5f1d7ba61821e3eed2432d67..82f75de6e27b2b9e653131d19d6defb0e3e90ae4 100644 (file)
@@ -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
index 53feffe3901905635c830cd4f6eba813200500c7..167e9cf2346c00b2fc360b536dea22e7d0a8b396 100644 (file)
 #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
index ae886e71737192a729f065137cbe6990b95e70d8..06b3337ad12f792f0f995ad99e7ec9b9721f2ad6 100644 (file)
 
 #define ERR_NOOPERHOST      491
 
+#define ERR_ISOPERLCHAN      498        /* Undernet extension */
+
 #define ERR_UMODEUNKNOWNFLAG 501
 #define ERR_USERSDONTMATCH   502
 
index 133d1ee12bb9d369b3d1f3ca21458323f8ce84da..27b6e95f555371020c4da447e80d32bf302ccfb7 100644 (file)
@@ -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))
   {
index b6fa0f6ea05691458354cf8a17ed9c11988cf86c..5ba170503a9182e5c8ab2fb90f962c342d637627 100644 (file)
@@ -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
index 8b2b589f771bf42b377203b287d2df64ab84d359..96894158677f5d564345e1596ef9edfd6359e7fc 100644 (file)
@@ -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 */