Committer  : entrope
CVSROOT    : /cvsroot/undernet-ircu
Module     : ircu2.10
Commit time: 2004-05-17 23:13:54 UTC

Modified files:
     ircd/s_debug.c ircd/m_oper.c ircd/ircd_parser.y ircd/ircd_lexer.l
     ircd/ircd_features.c ircd/client.c include/ircd_features.h
     include/client.h include/class.h doc/example.conf ChangeLog

Log message:

Replace privilege-controlling Feature settings with
privilege-controlling Class and Operator settings,
giving server admins more flexibility to delegate
privileges.

---------------------- diff included ----------------------
Index: ircu2.10/ChangeLog
diff -u ircu2.10/ChangeLog:1.420 ircu2.10/ChangeLog:1.421
--- ircu2.10/ChangeLog:1.420    Sun May 16 11:16:55 2004
+++ ircu2.10/ChangeLog  Mon May 17 16:13:44 2004
@@ -1,3 +1,22 @@
+2004-05-17  Michael Poole <[EMAIL PROTECTED]>
+
+       * include/ircd_features.h, ircd/ircd_features.c, ircd/s_debug.c:
+       Rip out feature settings related to oper privileges.
+
+       * include/client.h: Comment a few unexplained privileges.
+
+       * ircd/ircd_lexer.l: Rename privilege keywords to match their
+       names in code and /PRIVS output.  Add support for two "new"
+       privileges (FORCE_OPMODE, FORCE_LOCAL_OPMODE).
+
+       * include/class.h, ircd/client.c, ircd/ircd_parser.y,
+       ircd/m_oper.c: Replace the removed feature settings with
+       per-connection class operator privileges.
+
+       * doc/example.conf: Document the change.
+
+       * ircd/ircd_parser.y (portblock): Fix slight memory leak.
+
 2004-05-16  Michael Poole <[EMAIL PROTECTED]>
 
        * doc/example.conf: Make this show the new NICKLEN default.
Index: ircu2.10/doc/example.conf
diff -u ircu2.10/doc/example.conf:1.28 ircu2.10/doc/example.conf:1.29
--- ircu2.10/doc/example.conf:1.28      Sun May 16 11:16:56 2004
+++ ircu2.10/doc/example.conf   Mon May 17 16:13:44 2004
@@ -161,7 +161,57 @@
  sendq = 160000;
  maxlinks = 400;
 };
+Class {
+ name = "Opers";
+ pingfreq = 1 minutes 30 seconds;
+ sendq = 160000;
+ maxlinks = 10;
+
+ # For connection classes intended for operator use, you can specify
+ # privileges used when the Operator block (see below) names this
+ # class.  The local (aka globally_opered) privilege MUST be defined
+ # by either the Class or Operator block.  The following privileges
+ # exist:
+ #
+ # local (or propagate, with the opposite sense)
+ # whox  (can use x flag with /WHO)
+ # display (oper status visible to lusers)
+ # chan_limit (can join local channels when in
+ #                              MAXCHANNELSPERUSER channels)
+ # mode_lchan (can /MODE &channel without chanops)
+ # deop_lchan (cannot be deopped or kicked on local channels)
+ # walk_lchan (can forcibly /JOIN &channel OVERRIDE)
+ # show_invis (see +i users in /WHO x)
+ # show_all_invis (see +i users in /WHO x)
+ # unlimit_query (show more results from /WHO)
+ # local_kill (can kill clients on this server)
+ # rehash (can use /REHASH)
+ # die (can use /DIE)
+ # local_jupe_server (not used)
+ # set (can use /SET)
+ # local_gline (can set a G-line for this server only)
+ # local_badchan (can set a Gchan for this server only)
+ # see_chan (can see users in +s channels in /WHO)
+ # wide_gline (can use ! to force a wide G-line)
+ # see_opers (can see opers without DISPLAY privilege)
+ # force_local_opmode (can use OPMODE/CLEARMODE on quarantined local channels)
+ # kill (can kill clients on other servers)
+ # gline (can issue G-lines to other servers)
+ # jupe_server (not used)
+ # opmode (can use /OPMODE)
+ # badchan (can issue Gchans to other servers)
+ # force_opmode (can use OPMODE/CLEARMODE on quarantined global channels)
+ #
+ # For global opers (with propagate = yes or local = no), the default
+ # is to grant all of the above privileges.  For local opers, the
+ # default is to grant ONLY the following privileges:
+ #  chan_limit, mode_lchan, show_invis, show_all_invis, local_kill,
+ #  rehash, local_gline, local_jupe, local_opmode, whox, display,
+ #  force_local_opmode
+ # Any privileges listed in a Class block override the defaults.
 
+ local = no;
+};
 # [Client]
 #
 # To allow clients to connect, they need authorization. This can be
@@ -567,47 +617,14 @@
 # them from using Uworld as well.
 #
 # Operator {
-#  local = yes;
 #  host = "host/IP mask";
 #  name = "opername";
 #  password = "encryptedpass";
 #  class = "classname";
-#
-#  # You can also specify per-operator privileges, many of which can
-#  # be globally disabled by settings in the "features" block (as
-#  # indicated).
-#  extended_who_information = yes;
-#  oper_status_display = yes;
-#  globally_opered = no;              # inverted alias for local
-#  bypass_local_channel_limits = yes; # unless OPER_NO_CHAN_LIMIT = FALSE
-#  set_local_channel_modes = yes;     # unless OPER_MODE_LCHAN = FALSE
-#  protected_local_channel = yes;     # unless NO_OPER_DEOP_LCHAN = FALSE
-#  bypass_join_local_channels = yes;  # unless OPER_WALK_THROUGH_LMODES = FALSE
-#  see_invisible_users = yes;         # unless SHOW_INVISIBLE_USERS = FALSE
-#  list_all_invisible_users = yes;    # unless SHOW_ALL_INVISIBLE_USERS = FALSE
-#  unlimited_who_queries = yes;       # unless UNLIMIT_OPER_QUERY = FALSE
-#
-#  # The following privileges have two settings in the "features" block;
-#  # one to globally disable for local operators, one to globally disable
-#  # the privilege for global operators.
-#  local_kill = yes;                  # unless {OPER,LOCOP}_KILL = FALSE
-#  rehash = yes;                      # unless {OPER,LOCOP}_REHASH = FALSE
-#  die = yes;                         # unless {OPER,LOCOP}_DIE = FALSE
-#  local_gline = yes;                 # unless {OPER,LOCOP}_LGLINE = FALSE
-#  local_jupe_server = yes;           # unless {OPER,LOCOP}_LJUPE = FALSE
-#  change_settings = yes;             # unless {OPER,LOCOP}_SET = FALSE
-#  local_gline_channels = yes;        # unless {OPER,LOCOP}_LBADCHAN = FALSE
-#  see_private_channels = yes;        # unless {OPER,LOCOP}_SEE_IN_SECRET_CHANNELS = 
FALSE
-#  wide_glines = yes;                 # unless {OPER,LOCOP}_WIDE_GLINE = FALSE
-#
-#  # The following privileges default to yes for global operators and
-#  # to no for local operators.
-#  see_other_opers = yes;             # unless local
-#  global_kill = yes;                 # unless local or LOCAL_KILL_ONLY = TRUE
-#  gline = yes;                       # unless local or OPER_GLINE = FALSE
-#  jupe_server = yes;                 # unless local or OPER_JUPE = FALSE
-#  hack_channel_modes = yes;          # unless local or OPER_OPMODE = FALSE
-#  gline_channels = yes;              # unless local or OPER_BADCHAN = FALSE
+#  # You can also set any operator privilege; see the Class block
+#  # documentation for details.  A privilege defined for a single
+#  # Operator will override the privilege settings for the Class
+#  # and the default setting.
 # };
 #
 # The encrypted password is optional.  If you wish to encrypt your
@@ -625,11 +642,10 @@
  class = "Local";
 };
 Operator {
- local = yes;
  host = "[EMAIL PROTECTED]";
  password = "notencryptedpass";
  name = "Niels";
- class = "Local";
+ class = "Opers";
 };
 
 # Note that the <connection class> is optional, but leaving it away
@@ -789,43 +805,7 @@
 # "IPCHECK_CLONE_PERIOD" = "40";
 # "IPCHECK_CLONE_DELAY" = "600";
 # "CRYPT_OPER_PASSWORD" = "TRUE";
-# "OPER_NO_CHAN_LIMIT" = "TRUE";
-# "OPER_MODE_LCHAN" = "TRUE";
-# "OPER_WALK_THROUGH_LMODES" = "FALSE";
-# "NO_OPER_DEOP_LCHAN" = "FALSE";
-# "SHOW_INVISIBLE_USERS" = "TRUE";
-# "SHOW_ALL_INVISIBLE_USERS" = "TRUE";
-# "UNLIMIT_OPER_QUERY" = "FALSE";
-# "LOCAL_KILL_ONLY" = "FALSE";
 # "CONFIG_OPERCMDS" = "FALSE";
-# "OPER_KILL" = "TRUE";
-# "OPER_REHASH" = "TRUE";
-# "OPER_RESTART" = "TRUE";
-# "OPER_DIE" = "TRUE";
-# "OPER_GLINE" = "TRUE";
-# "OPER_LGLINE" = "TRUE";
-# "OPER_JUPE" = "TRUE";
-# "OPER_LJUPE" = "TRUE";
-# "OPER_OPMODE" = "TRUE";
-# "OPER_LOPMODE" = "TRUE";
-# "OPER_BADCHAN" = "FALSE";
-# "OPER_LBADCHAN" = "FALSE";
-# "OPER_SET" = "FALSE";
-# "OPERS_SEE_IN_SECRET_CHANNELS" = "TRUE";
-# "OPER_WIDE_GLINE" = "TRUE";
-# "OPER_LIST_CHAN" = "TRUE";
-# "LOCOP_KILL" = "TRUE";
-# "LOCOP_REHASH" = "TRUE";
-# "LOCOP_RESTART" = "FALSE";
-# "LOCOP_DIE" = "FALSE";
-# "LOCOP_LGLINE" = "TRUE";
-# "LOCOP_LJUPE" = "TRUE";
-# "LOCOP_LOPMODE" = "TRUE";
-# "LOCOP_LBADCHAN" = "FALSE";
-# "LOCOP_SET" = "FALSE";
-# "LOCOP_SEE_IN_SECRET_CHANNELS" = "FALSE";
-# "LOCOP_WIDE_GLINE" = "FALSE";
-# "LOCOP_LIST_CHAN" = "FALSE";
 # "OPLEVELS" = "TRUE";
 # "LOCAL_CHANNELS" = "TRUE";
 };
Index: ircu2.10/include/class.h
diff -u ircu2.10/include/class.h:1.15 ircu2.10/include/class.h:1.16
--- ircu2.10/include/class.h:1.15       Mon May 10 19:51:08 2004
+++ ircu2.10/include/class.h    Mon May 17 16:13:44 2004
@@ -17,7 +17,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: class.h,v 1.15 2004/05/11 02:51:08 entrope Exp $
+ * $Id: class.h,v 1.16 2004/05/17 23:13:44 entrope Exp $
  */
 #ifndef INCLUDED_class_h
 #define INCLUDED_class_h
@@ -26,7 +26,8 @@
 #define INCLUDED_sys_types_h
 #endif
 
-struct Client;
+#include "client.h"
+
 struct ConfItem;
 struct StatDesc;
 
@@ -37,6 +38,8 @@
   struct ConnectionClass* next;
   char                    *cc_name;
   char                    *default_umode;
+  struct Privs            privs;
+  struct Privs            privs_dirty;
   unsigned int            max_sendq;
   short                   ping_freq;
   short                   conn_freq;
Index: ircu2.10/include/client.h
diff -u ircu2.10/include/client.h:1.30 ircu2.10/include/client.h:1.31
--- ircu2.10/include/client.h:1.30      Mon May 10 19:51:08 2004
+++ ircu2.10/include/client.h   Mon May 17 16:13:44 2004
@@ -18,7 +18,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *
- * $Id: client.h,v 1.30 2004/05/11 02:51:08 entrope Exp $
+ * $Id: client.h,v 1.31 2004/05/17 23:13:44 entrope Exp $
  */
 #ifndef INCLUDED_client_h
 #define INCLUDED_client_h
@@ -113,8 +113,8 @@
     PRIV_SEE_OPERS, /* display hidden opers */
     PRIV_WIDE_GLINE, /* oper can set wider G-lines */
     PRIV_LIST_CHAN, /* oper can list secret channels */
-    PRIV_FORCE_OPMODE,
-    PRIV_FORCE_LOCAL_OPMODE,
+    PRIV_FORCE_OPMODE, /* can hack modes on quarantined channels */
+    PRIV_FORCE_LOCAL_OPMODE, /* can hack modes on quarantined local channels */
     PRIV_LAST_PRIV /* must be the same as the last priv */
   };
 
Index: ircu2.10/include/ircd_features.h
diff -u ircu2.10/include/ircd_features.h:1.24 ircu2.10/include/ircd_features.h:1.25
--- ircu2.10/include/ircd_features.h:1.24       Sat May 15 07:44:57 2004
+++ ircu2.10/include/ircd_features.h    Mon May 17 16:13:44 2004
@@ -18,7 +18,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: ircd_features.h,v 1.24 2004/05/15 14:44:57 entrope Exp $
+ * $Id: ircd_features.h,v 1.25 2004/05/17 23:13:44 entrope Exp $
  */
 
 struct Client;
@@ -90,52 +90,9 @@
 
   /* features that affect all operators */
   FEAT_CRYPT_OPER_PASSWORD,
-  FEAT_OPER_NO_CHAN_LIMIT,
-  FEAT_OPER_MODE_LCHAN,
-  FEAT_OPER_WALK_THROUGH_LMODES,
-  FEAT_NO_OPER_DEOP_LCHAN,
-  FEAT_SHOW_INVISIBLE_USERS,
-  FEAT_SHOW_ALL_INVISIBLE_USERS,
-  FEAT_UNLIMIT_OPER_QUERY,
-  FEAT_LOCAL_KILL_ONLY,
   FEAT_CONFIG_OPERCMDS,
   FEAT_LIST_CHAN,
 
-  /* features that affect global opers on this server */
-  FEAT_OPER_KILL,
-  FEAT_OPER_REHASH,
-  FEAT_OPER_RESTART,
-  FEAT_OPER_DIE,
-  FEAT_OPER_GLINE,
-  FEAT_OPER_LGLINE,
-  FEAT_OPER_JUPE,
-  FEAT_OPER_LJUPE,
-  FEAT_OPER_OPMODE,
-  FEAT_OPER_LOPMODE,
-  FEAT_OPER_FORCE_OPMODE,
-  FEAT_OPER_FORCE_LOPMODE,
-  FEAT_OPER_BADCHAN,
-  FEAT_OPER_LBADCHAN,
-  FEAT_OPER_SET,
-  FEAT_OPERS_SEE_IN_SECRET_CHANNELS,
-  FEAT_OPER_WIDE_GLINE,
-  FEAT_OPER_LIST_CHAN,
-
-  /* features that affect local opers on this server */
-  FEAT_LOCOP_KILL,
-  FEAT_LOCOP_REHASH,
-  FEAT_LOCOP_RESTART,
-  FEAT_LOCOP_DIE,
-  FEAT_LOCOP_LGLINE,
-  FEAT_LOCOP_LJUPE,
-  FEAT_LOCOP_LOPMODE,
-  FEAT_LOCOP_FORCE_LOPMODE,
-  FEAT_LOCOP_LBADCHAN,
-  FEAT_LOCOP_SET,
-  FEAT_LOCOP_SEE_IN_SECRET_CHANNELS,
-  FEAT_LOCOP_WIDE_GLINE,
-  FEAT_LOCOP_LIST_CHAN,
-
   /* HEAD_IN_SAND Features */
   FEAT_HIS_SNOTICES,
   FEAT_HIS_SNOTICES_OPER_ONLY,
Index: ircu2.10/ircd/client.c
diff -u ircu2.10/ircd/client.c:1.23 ircu2.10/ircd/client.c:1.24
--- ircu2.10/ircd/client.c:1.23 Mon May 10 19:51:07 2004
+++ ircu2.10/ircd/client.c      Mon May 17 16:13:44 2004
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: client.c,v 1.23 2004/05/11 02:51:07 entrope Exp $
+ * $Id: client.c,v 1.24 2004/05/17 23:13:44 entrope Exp $
  */
 #include "config.h"
 
@@ -120,75 +120,9 @@
   }
 }
 
-enum FeatureFlag {
-  FEATFLAG_NULL,
-  FEATFLAG_DISABLES_PRIV,
-  FEATFLAG_ENABLES_PRIV,
-  FEATFLAG_GLOBAL_OPERS,
-  FEATFLAG_LOCAL_OPERS,
-  FEATFLAG_ALL_OPERS
-};
-
-static struct
-{
-  enum Priv priv;
-  enum Feature feat;
-  enum FeatureFlag flag;
-} feattab[] =
-  {
-    { PRIV_WHOX, FEAT_LAST_F, FEATFLAG_ALL_OPERS },
-    { PRIV_DISPLAY, FEAT_LAST_F, FEATFLAG_ALL_OPERS },
-    { PRIV_CHAN_LIMIT, FEAT_OPER_NO_CHAN_LIMIT, FEATFLAG_ALL_OPERS },
-    { PRIV_MODE_LCHAN, FEAT_OPER_MODE_LCHAN, FEATFLAG_ALL_OPERS },
-    { PRIV_LOCAL_OPMODE, FEAT_OPER_MODE_LCHAN, FEATFLAG_ALL_OPERS },
-    { PRIV_WALK_LCHAN, FEAT_OPER_WALK_THROUGH_LMODES, FEATFLAG_ALL_OPERS },
-    { PRIV_DEOP_LCHAN, FEAT_NO_OPER_DEOP_LCHAN, FEATFLAG_ALL_OPERS },
-    { PRIV_SHOW_INVIS, FEAT_SHOW_INVISIBLE_USERS, FEATFLAG_ALL_OPERS },
-    { PRIV_SHOW_ALL_INVIS, FEAT_SHOW_ALL_INVISIBLE_USERS, FEATFLAG_ALL_OPERS },
-    { PRIV_UNLIMIT_QUERY, FEAT_UNLIMIT_OPER_QUERY, FEATFLAG_ALL_OPERS },
-    
-    { PRIV_KILL, FEAT_LOCAL_KILL_ONLY, FEATFLAG_DISABLES_PRIV },
-    { PRIV_GLINE, FEAT_CONFIG_OPERCMDS, FEATFLAG_ENABLES_PRIV },
-    { PRIV_JUPE, FEAT_CONFIG_OPERCMDS, FEATFLAG_ENABLES_PRIV },
-    { PRIV_OPMODE, FEAT_CONFIG_OPERCMDS, FEATFLAG_ENABLES_PRIV },
-    { PRIV_BADCHAN, FEAT_CONFIG_OPERCMDS, FEATFLAG_ENABLES_PRIV },
-    
-    { PRIV_PROPAGATE, FEAT_LAST_F, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_SEE_OPERS, FEAT_LAST_F, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_KILL, FEAT_OPER_KILL, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_LOCAL_KILL, FEAT_OPER_KILL, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_REHASH, FEAT_OPER_REHASH, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_RESTART, FEAT_OPER_RESTART, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_DIE, FEAT_OPER_DIE, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_GLINE, FEAT_OPER_GLINE, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_LOCAL_GLINE, FEAT_OPER_LGLINE, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_JUPE, FEAT_OPER_JUPE, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_LOCAL_JUPE, FEAT_OPER_LJUPE, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_OPMODE, FEAT_OPER_OPMODE, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_LOCAL_OPMODE, FEAT_OPER_LOPMODE, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_FORCE_OPMODE, FEAT_OPER_FORCE_OPMODE, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_FORCE_LOCAL_OPMODE, FEAT_OPER_FORCE_LOPMODE, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_BADCHAN, FEAT_OPER_BADCHAN, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_LOCAL_BADCHAN, FEAT_OPER_LBADCHAN, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_SET, FEAT_OPER_SET, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_SEE_CHAN, FEAT_OPERS_SEE_IN_SECRET_CHANNELS, FEATFLAG_GLOBAL_OPERS },
-    { PRIV_WIDE_GLINE, FEAT_OPER_WIDE_GLINE, FEATFLAG_GLOBAL_OPERS },
-    
-    { PRIV_LOCAL_KILL, FEAT_LOCOP_KILL, FEATFLAG_LOCAL_OPERS },
-    { PRIV_REHASH, FEAT_LOCOP_REHASH, FEATFLAG_LOCAL_OPERS },
-    { PRIV_RESTART, FEAT_LOCOP_RESTART, FEATFLAG_LOCAL_OPERS },
-    { PRIV_DIE, FEAT_LOCOP_DIE, FEATFLAG_LOCAL_OPERS },
-    { PRIV_LOCAL_GLINE, FEAT_LOCOP_LGLINE, FEATFLAG_LOCAL_OPERS },
-    { PRIV_LOCAL_JUPE, FEAT_LOCOP_LJUPE, FEATFLAG_LOCAL_OPERS },
-    { PRIV_LOCAL_OPMODE, FEAT_LOCOP_LOPMODE, FEATFLAG_LOCAL_OPERS },
-    { PRIV_FORCE_LOCAL_OPMODE, FEAT_LOCOP_FORCE_LOPMODE, FEATFLAG_LOCAL_OPERS },
-    { PRIV_LOCAL_BADCHAN, FEAT_LOCOP_LBADCHAN, FEATFLAG_LOCAL_OPERS },
-    { PRIV_SET, FEAT_LOCOP_SET, FEATFLAG_LOCAL_OPERS },
-    { PRIV_SEE_CHAN, FEAT_LOCOP_SEE_IN_SECRET_CHANNELS, FEATFLAG_LOCAL_OPERS },
-    { PRIV_WIDE_GLINE, FEAT_LOCOP_WIDE_GLINE, FEATFLAG_LOCAL_OPERS },
-    
-    { PRIV_LAST_PRIV, FEAT_LAST_F, FEATFLAG_NULL }
-  };
+static struct Privs privs_global;
+static struct Privs privs_local;
+static int privs_defaults_set;
 
 /* client_set_privs(struct Client* client)
  *
@@ -197,8 +131,27 @@
 void
 client_set_privs(struct Client *client, struct ConfItem *oper)
 {
-  int i;
+  struct Privs *source, *defaults;
+  enum Priv priv;
 
+  if (!privs_defaults_set)
+  {
+    memset(&privs_global, -1, sizeof(privs_global));
+    memset(&privs_local, 0, sizeof(privs_local));
+    PrivSet(&privs_local, PRIV_CHAN_LIMIT);
+    PrivSet(&privs_local, PRIV_MODE_LCHAN);
+    PrivSet(&privs_local, PRIV_SHOW_INVIS);
+    PrivSet(&privs_local, PRIV_SHOW_ALL_INVIS);
+    PrivSet(&privs_local, PRIV_LOCAL_KILL);
+    PrivSet(&privs_local, PRIV_REHASH);
+    PrivSet(&privs_local, PRIV_LOCAL_GLINE);
+    PrivSet(&privs_local, PRIV_LOCAL_JUPE);
+    PrivSet(&privs_local, PRIV_LOCAL_OPMODE);
+    PrivSet(&privs_local, PRIV_WHOX);
+    PrivSet(&privs_local, PRIV_DISPLAY);
+    PrivSet(&privs_local, PRIV_FORCE_LOCAL_OPMODE);
+    privs_defaults_set = 1;
+  }
   memset(&(cli_privs(client)), 0, sizeof(struct Privs));
 
   if (!IsAnOper(client))
@@ -212,49 +165,41 @@
   else if (oper == NULL)
     return;
 
-  /* Copy across privs from the config. */
-  cli_privs(client) = oper->privs;
+  /* Clear out client's privileges. */
+  memset(&cli_privs(client), 0, sizeof(struct Privs));
+
+  /* Decide whether to use global or local oper defaults. */
+  if (PrivHas(&oper->privs_dirty, PRIV_PROPAGATE))
+    defaults = PrivHas(&oper->privs, PRIV_PROPAGATE) ? &privs_global : &privs_local;
+  else if (PrivHas(&oper->conn_class->privs_dirty, PRIV_PROPAGATE))
+    defaults = PrivHas(&oper->conn_class->privs, PRIV_PROPAGATE) ? &privs_global : 
&privs_local;
+  else
+      assert(0 && "Oper has no propagation and neither does connection class");
 
-  /* Now go through the features and set the non-dirty flags to their feature
-   * determined defaults...
+  /* For each feature, figure out whether it comes from the operator
+   * conf, the connection class conf, or the defaults, then apply it.
    */
-  for (i = 0; feattab[i].priv != PRIV_LAST_PRIV; i++)
+  for (priv = 0; priv < PRIV_LAST_PRIV; ++priv)
   {
-    if (PrivHas(&oper->privs_dirty, feattab[i].priv))
-      continue;
-    if (feattab[i].feat != FEAT_LAST_F && !feature_bool(feattab[i].feat))
-      continue;
-    switch (feattab[i].flag)
-    {
-    case FEATFLAG_ENABLES_PRIV:
-      if (!feature_bool(feattab[i].feat))
-        continue;
-      PrivSet(&cli_privs(client), feattab[i].priv);
-      continue;
-    case FEATFLAG_DISABLES_PRIV:
-      PrivClr(&cli_privs(client), feattab[i].priv);
-      continue;
-    case FEATFLAG_ALL_OPERS:
-      if (IsAnOper(client))
-        PrivSet(&cli_privs(client), feattab[i].priv);
-      continue;
-    case FEATFLAG_GLOBAL_OPERS:
-      if (IsOper(client))
-        PrivSet(&cli_privs(client), feattab[i].priv);
-      continue;
-    case FEATFLAG_LOCAL_OPERS:
-      if (IsLocOp(client))
-        PrivSet(&cli_privs(client), feattab[i].priv);
-      continue;
-    default:
-      continue;  /* ?? */
-    }
+    /* Figure out most applicable definition for the privilege. */
+    if (PrivHas(&oper->privs_dirty, priv))
+      source = &oper->privs;
+    else if (PrivHas(&oper->conn_class->privs_dirty, priv))
+      source = &oper->conn_class->privs;
+    else
+      source = defaults;
+
+    /* Set it if necessary (privileges were already cleared). */
+    if (PrivHas(source, priv))
+      PrivSet(&cli_privs(client), priv);
   }
 
   /* This should be handled in the config, but lets be sure... */
   if (PrivHas(&cli_privs(client), PRIV_PROPAGATE))
+  {
     /* force propagating opers to display */
     PrivSet(&cli_privs(client), PRIV_DISPLAY);
+  }
   else
   {
     /* if they don't propagate oper status, prevent desyncs */
Index: ircu2.10/ircd/ircd_features.c
diff -u ircu2.10/ircd/ircd_features.c:1.31 ircu2.10/ircd/ircd_features.c:1.32
--- ircu2.10/ircd/ircd_features.c:1.31  Sun May 16 11:16:56 2004
+++ ircu2.10/ircd/ircd_features.c       Mon May 17 16:13:44 2004
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: ircd_features.c,v 1.31 2004/05/16 18:16:56 entrope Exp $
+ * $Id: ircd_features.c,v 1.32 2004/05/17 23:13:44 entrope Exp $
  */
 #include "config.h"
 
@@ -296,52 +296,9 @@
 
   /* features that affect all operators */
   F_B(CRYPT_OPER_PASSWORD, FEAT_MYOPER | FEAT_READ, 1, 0),
-  F_B(OPER_NO_CHAN_LIMIT, 0, 1, 0),
-  F_B(OPER_MODE_LCHAN, 0, 1, 0),
-  F_B(OPER_WALK_THROUGH_LMODES, 0, 0, 0),
-  F_B(NO_OPER_DEOP_LCHAN, 0, 0, 0),
-  F_B(SHOW_INVISIBLE_USERS, 0, 1, 0),
-  F_B(SHOW_ALL_INVISIBLE_USERS, 0, 1, 0),
-  F_B(UNLIMIT_OPER_QUERY, 0, 0, 0),
-  F_B(LOCAL_KILL_ONLY, 0, 0, 0),
   F_B(CONFIG_OPERCMDS, 0, 0, 0),
   F_B(LIST_CHAN, 0, 1, 0),
 
-  /* features that affect global opers on this server */
-  F_B(OPER_KILL, 0, 1, 0),
-  F_B(OPER_REHASH, 0, 1, 0),
-  F_B(OPER_RESTART, 0, 1, 0),
-  F_B(OPER_DIE, 0, 1, 0),
-  F_B(OPER_GLINE, 0, 1, 0),
-  F_B(OPER_LGLINE, 0, 1, 0),
-  F_B(OPER_JUPE, 0, 1, 0),
-  F_B(OPER_LJUPE, 0, 1, 0),
-  F_B(OPER_OPMODE, 0, 1, 0),
-  F_B(OPER_LOPMODE, 0, 1, 0),
-  F_B(OPER_FORCE_OPMODE, 0, 1, 0),
-  F_B(OPER_FORCE_LOPMODE, 0, 1, 0),
-  F_B(OPER_BADCHAN, 0, 0, 0),
-  F_B(OPER_LBADCHAN, 0, 0, 0),
-  F_B(OPER_SET, 0, 0, 0),
-  F_B(OPERS_SEE_IN_SECRET_CHANNELS, 0, 1, 0),
-  F_B(OPER_WIDE_GLINE, 0, 1, 0),
-  F_B(OPER_LIST_CHAN, 0, 1, 0),
-
-  /* features that affect local opers on this server */
-  F_B(LOCOP_KILL, 0, 1, 0),
-  F_B(LOCOP_REHASH, 0, 1, 0),
-  F_B(LOCOP_RESTART, 0, 0, 0),
-  F_B(LOCOP_DIE, 0, 0, 0),
-  F_B(LOCOP_LGLINE, 0, 1, 0),
-  F_B(LOCOP_LJUPE, 0, 1, 0),
-  F_B(LOCOP_LOPMODE, 0, 1, 0),
-  F_B(LOCOP_FORCE_LOPMODE, 0, 1, 0),
-  F_B(LOCOP_LBADCHAN, 0, 0, 0),
-  F_B(LOCOP_SET, 0, 0, 0),
-  F_B(LOCOP_SEE_IN_SECRET_CHANNELS, 0, 0, 0),
-  F_B(LOCOP_WIDE_GLINE, 0, 0, 0),
-  F_B(LOCOP_LIST_CHAN, 0, 0, 0),
-
   /* HEAD_IN_SAND Features */
   F_B(HIS_SNOTICES, 0, 1, 0),
   F_B(HIS_SNOTICES_OPER_ONLY, 0, 1, 0),
Index: ircu2.10/ircd/ircd_lexer.l
diff -u ircu2.10/ircd/ircd_lexer.l:1.5 ircu2.10/ircd/ircd_lexer.l:1.6
--- ircu2.10/ircd/ircd_lexer.l:1.5      Mon May 10 19:51:07 2004
+++ ircu2.10/ircd/ircd_lexer.l  Mon May 17 16:13:44 2004
@@ -17,7 +17,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  *  USA.
- * $Id: ircd_lexer.l,v 1.5 2004/05/11 02:51:07 entrope Exp $
+ * $Id: ircd_lexer.l,v 1.6 2004/05/17 23:13:44 entrope Exp $
  */
 
 %{
@@ -123,32 +123,32 @@
 quarantine return QUARANTINE;
 features return FEATURES;
 channel return CHANNEL;
-bypass_local_channel_limits return TPRIV_CHAN_LIMIT;
-set_local_channel_modes return TPRIV_MODE_LCHAN;
-protected_local_channel return TPRIV_DEOP_LCHAN;
-bypass_join_local_channels return TPRIV_WALK_LCHAN;
-global_kill return TPRIV_KILL;
+chan_limit return TPRIV_CHAN_LIMIT;
+mode_lchan return TPRIV_MODE_LCHAN;
+deop_lchan return TPRIV_DEOP_LCHAN;
+walk_lchan return TPRIV_WALK_LCHAN;
 local_kill return TPRIV_LOCAL_KILL;
 rehash return TPRIV_REHASH;
 restart return TPRIV_RESTART;
 die return TPRIV_DIE;
 gline return TPRIV_GLINE;
 local_gline return TPRIV_LOCAL_GLINE;
-jupe_server return TPRIV_JUPE;
-local_jupe_server return TPRIV_LOCAL_JUPE;
-hack_channel_modes return TPRIV_OPMODE;
-change_settings return TPRIV_SET;
-extended_who_information return TPRIV_WHOX;
-gline_channels return TPRIV_BADCHAN;
-local_gline_channels return TPRIV_LOCAL_BADCHAN;
-see_private_channels return TPRIV_SEE_CHAN;
-see_invisible_users return TPRIV_SHOW_INVIS;
-list_all_invisible_users return TPRIV_SHOW_ALL_INVIS;
-globally_opered return TPRIV_PROPAGATE;
-unlimited_who_queries return TPRIV_UNLIMIT_QUERY;
-oper_status_display return TPRIV_DISPLAY;
-see_other_opers return TPRIV_SEE_OPERS;
-wide_glines return TPRIV_WIDE_GLINE;
+local_jupe return TPRIV_LOCAL_JUPE;
+opmode return TPRIV_OPMODE;
+set return TPRIV_SET;
+whox return TPRIV_WHOX;
+badchan return TPRIV_BADCHAN;
+local_badchan return TPRIV_LOCAL_BADCHAN;
+see_chan return TPRIV_SEE_CHAN;
+show_invis return TPRIV_SHOW_INVIS;
+show_all_invis return TPRIV_SHOW_ALL_INVIS;
+propagate return TPRIV_PROPAGATE;
+unlimit_query return TPRIV_UNLIMIT_QUERY;
+display return TPRIV_DISPLAY;
+see_opers return TPRIV_SEE_OPERS;
+wide_gline return TPRIV_WIDE_GLINE;
+force_opmode return TPRIV_FORCE_OPMODE;
+force_local_opmode return TPRIV_FORCE_LOCAL_OPMODE;
 pseudo return PSEUDO;
 prepend return PREPEND;
 usermode return USERMODE;
Index: ircu2.10/ircd/ircd_parser.y
diff -u ircu2.10/ircd/ircd_parser.y:1.14 ircu2.10/ircd/ircd_parser.y:1.15
--- ircu2.10/ircd/ircd_parser.y:1.14    Sun May 16 06:56:04 2004
+++ ircu2.10/ircd/ircd_parser.y Mon May 17 16:13:43 2004
@@ -17,7 +17,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  *  USA.
- * $Id: ircd_parser.y,v 1.14 2004/05/16 13:56:04 entrope Exp $
+ * $Id: ircd_parser.y,v 1.15 2004/05/17 23:13:43 entrope Exp $
  */
 %{
 
@@ -79,6 +79,8 @@
   struct ServerConf *sconf;
   struct qline *qconf = NULL;
   struct s_map *smap;
+  struct Privs privs;
+  struct Privs privs_dirty;
 
 static void parse_error(char *pattern,...) {
   static char error_buffer[1024];
@@ -157,12 +159,12 @@
 %token USERMODE
 /* and now a lot of priviledges... */
 %token TPRIV_CHAN_LIMIT TPRIV_MODE_LCHAN TPRIV_DEOP_LCHAN TPRIV_WALK_LCHAN
-%token TPRIV_KILL TPRIV_LOCAL_KILL TPRIV_REHASH TPRIV_RESTART TPRIV_DIE
-%token TPRIV_GLINE TPRIV_LOCAL_GLINE TPRIV_JUPE TPRIV_LOCAL_JUPE
+%token TPRIV_LOCAL_KILL TPRIV_REHASH TPRIV_RESTART TPRIV_DIE
+%token TPRIV_GLINE TPRIV_LOCAL_GLINE TPRIV_LOCAL_JUPE TPRIV_LOCAL_BADCHAN
 %token TPRIV_LOCAL_OPMODE TPRIV_OPMODE TPRIV_SET TPRIV_WHOX TPRIV_BADCHAN
-%token TPRIV_LOCAL_BADCHAN
 %token TPRIV_SEE_CHAN TPRIV_SHOW_INVIS TPRIV_SHOW_ALL_INVIS TPRIV_PROPAGATE
 %token TPRIV_UNLIMIT_QUERY TPRIV_DISPLAY TPRIV_SEE_OPERS TPRIV_WIDE_GLINE
+%token TPRIV_FORCE_OPMODE TPRIV_FORCE_LOCAL_OPMODE
 /* and some types... */
 %type <num> sizespec
 %type <num> timespec timefactor factoredtimes factoredtime
@@ -330,12 +332,18 @@
   maxlinks = 0;
   sendq = 0;
   pass = NULL;
+  memset(&privs, 0, sizeof(privs));
+  memset(&privs_dirty, 0, sizeof(privs_dirty));
 } '{' classitems '}'
 {
   if (name != NULL)
   {
-   add_class(name, tping, tconn, maxlinks, sendq);
-   find_class(name)->default_umode = pass;
+    struct ConnectionClass *c_class;
+    add_class(name, tping, tconn, maxlinks, sendq);
+    c_class = find_class(name);
+    c_class->default_umode = pass;
+    memcpy(&c_class->privs, &privs, sizeof(c_class->privs));
+    memcpy(&c_class->privs_dirty, &privs_dirty, sizeof(c_class->privs_dirty));
   }
   else {
    parse_error("Missing name in class block");
@@ -344,7 +352,7 @@
 } ';';
 classitems: classitem classitems | classitem;
 classitem: classname | classpingfreq | classconnfreq | classmaxlinks |
-           classsendq | classusermode | error;
+           classsendq | classusermode | priv | error;
 classname: NAME '=' QSTRING ';'
 {
   MyFree(name);
@@ -502,11 +510,19 @@
 {
   aconf = (struct ConfItem*) MyMalloc(sizeof(*aconf));
   memset(aconf, 0, sizeof(*aconf));
+  memset(&privs, 0, sizeof(privs));
+  memset(&privs_dirty, 0, sizeof(privs_dirty));
   aconf->status = CONF_OPERATOR;
 } '{' operitems '}' ';'
 {
-  if (aconf->name != NULL && aconf->passwd != NULL && aconf->host != NULL)
+  if (aconf->name != NULL && aconf->passwd != NULL && aconf->host != NULL
+      && aconf->conn_class != NULL)
   {
+    memcpy(&aconf->privs, &privs, sizeof(aconf->privs));
+    memcpy(&aconf->privs_dirty, &privs_dirty, sizeof(aconf->privs_dirty));
+    if (!PrivHas(&privs_dirty, PRIV_PROPAGATE)
+        && !PrivHas(&aconf->conn_class->privs_dirty, PRIV_PROPAGATE))
+      parse_error("Operator block for %s and class %s have no LOCAL setting", 
aconf->name, aconf->conn_class->cc_name);
     aconf->next = GlobalConfList;
     GlobalConfList = aconf;
   }
@@ -521,7 +537,7 @@
   }
 };
 operitems: operitem | operitems operitem;
-operitem: opername | operpass | operhost | operclass | operpriv | error;
+operitem: opername | operpass | operhost | operclass | priv | error;
 
 opername: NAME '=' QSTRING ';'
 {
@@ -554,13 +570,13 @@
  aconf->conn_class = find_class(yylval.text);
 };
 
-operpriv: privtype '=' yesorno ';'
+priv: privtype '=' yesorno ';'
 {
-  PrivSet(&aconf->privs_dirty, $1);
+  PrivSet(&privs_dirty, $1);
   if (($3 == 1) ^ invert)
-    PrivSet(&aconf->privs, $1);
+    PrivSet(&privs, $1);
   else
-    PrivClr(&aconf->privs, $1);
+    PrivClr(&privs, $1);
   invert = 0;
 };
 
@@ -568,14 +584,14 @@
           TPRIV_MODE_LCHAN { $$ = PRIV_MODE_LCHAN; } |
           TPRIV_DEOP_LCHAN { $$ = PRIV_DEOP_LCHAN; } |
           TPRIV_WALK_LCHAN { $$ = PRIV_WALK_LCHAN; } |
-          TPRIV_KILL { $$ = PRIV_KILL; } |
+          KILL { $$ = PRIV_KILL; } |
           TPRIV_LOCAL_KILL { $$ = PRIV_LOCAL_KILL; } |
           TPRIV_REHASH { $$ = PRIV_REHASH; } |
           TPRIV_RESTART { $$ = PRIV_RESTART; } |
           TPRIV_DIE { $$ = PRIV_DIE; } |
           TPRIV_GLINE { $$ = PRIV_GLINE; } |
           TPRIV_LOCAL_GLINE { $$ = PRIV_LOCAL_GLINE; } |
-          TPRIV_JUPE { $$ = PRIV_JUPE; } |
+          JUPE { $$ = PRIV_JUPE; } |
           TPRIV_LOCAL_JUPE { $$ = PRIV_LOCAL_JUPE; } |
           TPRIV_LOCAL_OPMODE { $$ = PRIV_LOCAL_OPMODE; } |
           TPRIV_OPMODE { $$ = PRIV_OPMODE; }|
@@ -591,7 +607,9 @@
           TPRIV_DISPLAY { $$ = PRIV_DISPLAY; } |
           TPRIV_SEE_OPERS { $$ = PRIV_SEE_OPERS; } |
           TPRIV_WIDE_GLINE { $$ = PRIV_WIDE_GLINE; } |
-          LOCAL { $$ = PRIV_PROPAGATE; invert = 1; };
+          LOCAL { $$ = PRIV_PROPAGATE; invert = 1; } |
+          TPRIV_FORCE_OPMODE { $$ = PRIV_FORCE_OPMODE; } |
+          TPRIV_FORCE_LOCAL_OPMODE { $$ = PRIV_FORCE_LOCAL_OPMODE; };
 
 yesorno: YES { $$ = 1; } | NO { $$ = 0; };
 
@@ -609,14 +627,14 @@
   if (port > 0 && port <= 0xFFFF)
   {
     add_listener(port, host, pass, tconn, tping);
-    host = pass = NULL;
   }
   else
   {
-    MyFree(host);
-    MyFree(pass);
     parse_error("Bad port block");
   }
+  MyFree(host);
+  MyFree(pass);
+  host = pass = NULL;
 };
 portitems: portitem portitems | portitem;
 portitem: portnumber | portvhost | portmask | portserver | porthidden | error;
Index: ircu2.10/ircd/m_oper.c
diff -u ircu2.10/ircd/m_oper.c:1.17 ircu2.10/ircd/m_oper.c:1.18
--- ircu2.10/ircd/m_oper.c:1.17 Sun May 16 06:56:04 2004
+++ ircu2.10/ircd/m_oper.c      Mon May 17 16:13:43 2004
@@ -20,7 +20,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: m_oper.c,v 1.17 2004/05/16 13:56:04 entrope Exp $
+ * $Id: m_oper.c,v 1.18 2004/05/17 23:13:43 entrope Exp $
  */
 
 /*
@@ -163,14 +163,10 @@
                           cli_sockhost(sptr));
       return 0;
     }
-    if (!PrivHas(&aconf->privs, PRIV_PROPAGATE)) {
-      ClearOper(sptr);
-      SetLocOp(sptr);
-    }
-    else {
-      /*
-       * prevent someone from being both oper and local oper
-       */
+    SetLocOp(sptr);
+    client_set_privs(sptr, aconf);
+    if (HasPriv(sptr, PRIV_PROPAGATE))
+    {
       ClearLocOp(sptr);
       SetOper(sptr);
       ++UserStats.opers;
@@ -182,7 +178,6 @@
     SetFlag(sptr, FLAG_DEBUG);
     
     set_snomask(sptr, SNO_OPERDEFAULT, SNO_ADD);
-    client_set_privs(sptr, aconf);
     cli_max_sendq(sptr) = 0; /* Get the sendq from the oper's class */
     send_umode_out(cptr, sptr, &old_mode, HasPriv(sptr, PRIV_PROPAGATE));
     send_reply(sptr, RPL_YOUREOPER);
Index: ircu2.10/ircd/s_debug.c
diff -u ircu2.10/ircd/s_debug.c:1.27 ircu2.10/ircd/s_debug.c:1.28
--- ircu2.10/ircd/s_debug.c:1.27        Tue Jan  7 19:17:19 2003
+++ ircu2.10/ircd/s_debug.c     Mon May 17 16:13:43 2004
@@ -17,7 +17,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: s_debug.c,v 1.27 2003/01/08 03:17:19 klmitch Exp $
+ * $Id: s_debug.c,v 1.28 2004/05/17 23:13:43 entrope Exp $
  *
  */
 #include "config.h"
@@ -93,54 +93,18 @@
   AddC('D');
 #endif
 
-  if (feature_bool(FEAT_LOCOP_REHASH))
-    AddC('e');
-
-  if (feature_bool(FEAT_OPER_REHASH))
-    AddC('E');
-
-  if (feature_bool(FEAT_OPER_NO_CHAN_LIMIT))
-    AddC('F');
-
-  if (feature_bool(FEAT_OPER_MODE_LCHAN))
-    AddC('f');
-
   if (feature_bool(FEAT_HUB))
     AddC('H');
 
-  if (feature_bool(FEAT_SHOW_ALL_INVISIBLE_USERS))
-    AddC('I');
-  else if (feature_bool(FEAT_SHOW_INVISIBLE_USERS))
-    AddC('i');
-
-  if (feature_bool(FEAT_OPER_KILL)) {
-    if (feature_bool(FEAT_LOCAL_KILL_ONLY))
-      AddC('k');
-    else
-      AddC('K');
-  }
-
-  if (feature_bool(FEAT_OPER_WALK_THROUGH_LMODES))
-    AddC('l');
-
   if (feature_bool(FEAT_IDLE_FROM_MSG))
     AddC('M');
 
-  if (feature_bool(FEAT_NO_OPER_DEOP_LCHAN))
-    AddC('o');
-
   if (feature_bool(FEAT_CRYPT_OPER_PASSWORD))
     AddC('p');
 
   if (feature_bool(FEAT_RELIABLE_CLOCK))
     AddC('R');
 
-  if (feature_bool(FEAT_LOCOP_RESTART))
-    AddC('s');
-
-  if (feature_bool(FEAT_OPER_RESTART))
-    AddC('S');
-
 #if defined(USE_POLL) && defined(HAVE_POLL_H)
   AddC('U');
 #endif
----------------------- End of diff -----------------------

Reply via email to