X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fclient.c;h=8bfdfe8a01a686413e6d80316c90a91847d599e5;hb=03b8f45e5712f9d4a46dc03f695dd9ac5426626e;hp=0b4e4f93daed6282a1bc688e7e69a4e9116f728d;hpb=4878eb8548700d2851d43ee801b020bdf15d5f09;p=ircu2.10.12-pk.git diff --git a/ircd/client.c b/ircd/client.c index 0b4e4f9..8bfdfe8 100644 --- a/ircd/client.c +++ b/ircd/client.c @@ -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 */