Replace privilege-controlling Feature settings with
authorMichael Poole <mdpoole@troilus.org>
Mon, 17 May 2004 23:13:44 +0000 (23:13 +0000)
committerMichael Poole <mdpoole@troilus.org>
Mon, 17 May 2004 23:13:44 +0000 (23:13 +0000)
privilege-controlling Class and Operator settings,
giving server admins more flexibility to delegate
privileges.

git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@1071 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

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

index 0f3286fa0c658d30be4287c72b08d3fdc232474e..584a95fc97df931114509591deb11097e4d69aa3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2004-05-17  Michael Poole <mdpoole@troilus.org>
+
+       * 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 <mdpoole@troilus.org>
 
        * doc/example.conf: Make this show the new NICKLEN default.
index 327f270e0ab7efaa6728c093aa65f905a03d4ea9..c55148c51524ad34b026820550095e16be097911 100644 (file)
@@ -161,7 +161,57 @@ Class {
  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 @@ CRULE
 # 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 @@ Operator {
  class = "Local";
 };
 Operator {
- local = yes;
  host = "*@*.uu.net";
  password = "notencryptedpass";
  name = "Niels";
- class = "Local";
+ class = "Opers";
 };
 
 # Note that the <connection class> is optional, but leaving it away
@@ -789,43 +805,7 @@ features
 # "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 374c21b5886431c781320b63c313b7b1af6add95..e5d0b54bdf2396015f7a6b9df67988fb7c736da6 100644 (file)
@@ -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 {
   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 f6500bc481b6f80619bb80fe9691224e23ffeb30..cb6779693c511aecf0b974eca5828a3f5bb486a8 100644 (file)
@@ -113,8 +113,8 @@ enum Priv
     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 533e3802e75019cbcc636f9fe258d8f00f8a5311..b1e0cc585d941cbb2167aeeff69fda04a6c09d4e 100644 (file)
@@ -90,52 +90,9 @@ enum Feature {
 
   /* 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 0b4e4f93daed6282a1bc688e7e69a4e9116f728d..8bfdfe8a01a686413e6d80316c90a91847d599e5 100644 (file)
@@ -120,75 +120,9 @@ void client_add_sendq(struct Connection* con, struct Connection** con_p)
   }
 }
 
-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 @@ static struct
 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 @@ client_set_privs(struct Client *client, struct ConfItem *oper)
   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 eab84ceb7580317030b2bea796c13035c2dec811..9fe5195719023bf7a7454f6d0104700dd94abdf9 100644 (file)
@@ -296,52 +296,9 @@ static struct FeatureDesc {
 
   /* 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 71569a2ae6305f5723ed6b4c4c94250b3e84ba6a..91f022fbb96ddb0df9a4d94f1237e32a8051758b 100644 (file)
@@ -123,32 +123,32 @@ kill return KILL;
 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 8233077d64eb6fc7a584d85fb3e24166daf99493..cb22a29e50381f7704ff5dc96243b57647051185 100644 (file)
@@ -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 @@ static void parse_error(char *pattern,...) {
 %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 @@ classblock: CLASS {
   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 @@ classblock: CLASS {
 } ';';
 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 @@ operblock: OPER
 {
   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 @@ operblock: OPER
   }
 };
 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 @@ operclass: CLASS '=' QSTRING ';'
  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 @@ privtype: TPRIV_CHAN_LIMIT { $$ = PRIV_CHAN_LIMIT; } |
           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 @@ privtype: TPRIV_CHAN_LIMIT { $$ = PRIV_CHAN_LIMIT; } |
           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 @@ portblock: PORT {
   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 d23e2f2205b2411f3df4a7ed09d9938804c56b26..002b36d90a8e937c800bcc408d9b3ae45daa293a 100644 (file)
@@ -163,14 +163,10 @@ int m_oper(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
                           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 @@ int m_oper(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
     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 da1992964b3e5f18424b82108cfa64468ae236d7..6899c744cc5b0a194d5e63c03f3bc08a7bb4e651 100644 (file)
@@ -93,54 +93,18 @@ const char* debug_serveropts(void)
   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