+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.
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
# 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
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
# "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";
};
#define INCLUDED_sys_types_h
#endif
-struct Client;
+#include "client.h"
+
struct ConfItem;
struct StatDesc;
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;
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 */
};
/* 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,
}
}
-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)
*
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))
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 */
/* 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),
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;
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];
%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
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");
} ';';
classitems: classitem classitems | classitem;
classitem: classname | classpingfreq | classconnfreq | classmaxlinks |
- classsendq | classusermode | error;
+ classsendq | classusermode | priv | error;
classname: NAME '=' QSTRING ';'
{
MyFree(name);
{
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;
}
}
};
operitems: operitem | operitems operitem;
-operitem: opername | operpass | operhost | operclass | operpriv | error;
+operitem: opername | operpass | operhost | operclass | priv | error;
opername: NAME '=' 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;
};
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; }|
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; };
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;
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;
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);
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