}
}
-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 */