X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fclient.c;h=e3961b43ffac28d51545d7267d57f072532e8727;hb=refs%2Fheads%2Fupstream-ssl;hp=db6ce6fb4ed19a72e7f6e51bc13abde9cdc788d7;hpb=b4110670ae18c46af048d6fb8a22e7bb967f1cf9;p=ircu2.10.12-pk.git diff --git a/ircd/client.c b/ircd/client.c index db6ce6f..e3961b4 100644 --- a/ircd/client.c +++ b/ircd/client.c @@ -15,8 +15,10 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id$ + */ +/** @file + * @brief Implementation of functions for handling local clients. + * @version $Id$ */ #include "config.h" @@ -24,6 +26,7 @@ #include "class.h" #include "ircd.h" #include "ircd_features.h" +#include "ircd_log.h" #include "ircd_reply.h" #include "list.h" #include "msgq.h" @@ -33,15 +36,14 @@ #include "send.h" #include "struct.h" -#include +/* #include -- Now using assert in ircd_log.h */ #include -#define BAD_PING ((unsigned int)-2) - -/* - * client_get_ping - * returns shortest ping time in attached server or client conf - * classes or PINGFREQUENCY +/** Find the shortest non-zero ping time attached to a client. + * If all attached ping times are zero, return the value for + * FEAT_PINGFREQUENCY. + * @param[in] acptr Client to find ping time for. + * @return Ping time in seconds. */ int client_get_ping(const struct Client* acptr) { @@ -67,10 +69,27 @@ int client_get_ping(const struct Client* acptr) return ping; } -/* - * client_drop_sendq - * removes the client's connection from the list of connections with - * queued data +/** Find the default usermode for a client. + * @param[in] sptr Client to find default usermode for. + * @return Pointer to usermode string (or NULL, if there is no default). + */ +const char* client_get_default_umode(const struct Client* sptr) +{ + struct ConfItem* aconf; + struct SLink* link; + + assert(cli_verify(sptr)); + + for (link = cli_confs(sptr); link; link = link->next) { + aconf = link->value.aconf; + if ((aconf->status & CONF_CLIENT) && ConfUmode(aconf)) + return ConfUmode(aconf); + } + return NULL; +} + +/** Remove a connection from the list of connections with queued data. + * @param[in] con Connection with no queued data. */ void client_drop_sendq(struct Connection* con) { @@ -84,10 +103,9 @@ void client_drop_sendq(struct Connection* con) } } -/* - * client_add_sendq - * adds the client's connection to the list of connections with - * queued data +/** Add a connection to the list of connections with queued data. + * @param[in] con Connection with queued data. + * @param[in,out] con_p Previous pointer to next connection. */ void client_add_sendq(struct Connection* con, struct Connection** con_p) { @@ -101,125 +119,114 @@ void client_add_sendq(struct Connection* con, struct Connection** con_p) } } -static struct { - unsigned int priv; - enum Feature feat; - unsigned int flag; -} feattab[] = { - { PRIV_WHOX, FEAT_LAST_F, (FLAGS_OPER | FLAGS_LOCOP) }, - { PRIV_DISPLAY, FEAT_LAST_F, (FLAGS_OPER | FLAGS_LOCOP) }, - { PRIV_CHAN_LIMIT, FEAT_OPER_NO_CHAN_LIMIT, (FLAGS_OPER | FLAGS_LOCOP) }, - { PRIV_MODE_LCHAN, FEAT_OPER_MODE_LCHAN, (FLAGS_OPER | FLAGS_LOCOP) }, - { PRIV_LOCAL_OPMODE, FEAT_OPER_MODE_LCHAN, (FLAGS_OPER | FLAGS_LOCOP) }, - { PRIV_WALK_LCHAN, FEAT_OPER_WALK_THROUGH_LMODES, - (FLAGS_OPER | FLAGS_LOCOP) }, - { PRIV_DEOP_LCHAN, FEAT_NO_OPER_DEOP_LCHAN, (FLAGS_OPER | FLAGS_LOCOP) }, - { PRIV_SHOW_INVIS, FEAT_SHOW_INVISIBLE_USERS, (FLAGS_OPER | FLAGS_LOCOP) }, - { PRIV_SHOW_ALL_INVIS, FEAT_SHOW_ALL_INVISIBLE_USERS, - (FLAGS_OPER | FLAGS_LOCOP) }, - { PRIV_UNLIMIT_QUERY, FEAT_UNLIMIT_OPER_QUERY, (FLAGS_OPER | FLAGS_LOCOP) }, - { PRIV_LIST_CHAN, FEAT_LIST_CHAN, (FLAGS_OPER | FLAGS_LOCOP) }, - - { PRIV_KILL, FEAT_LOCAL_KILL_ONLY, 0 }, - { PRIV_GLINE, FEAT_CONFIG_OPERCMDS, ~0 }, - { PRIV_JUPE, FEAT_CONFIG_OPERCMDS, ~0 }, - { PRIV_OPMODE, FEAT_CONFIG_OPERCMDS, ~0 }, - { PRIV_BADCHAN, FEAT_CONFIG_OPERCMDS, ~0 }, - - { PRIV_PROPAGATE, FEAT_LAST_F, FLAGS_OPER }, - { PRIV_SEE_OPERS, FEAT_LAST_F, FLAGS_OPER }, - { PRIV_KILL, FEAT_OPER_KILL, FLAGS_OPER }, - { PRIV_LOCAL_KILL, FEAT_OPER_KILL, FLAGS_OPER }, - { PRIV_REHASH, FEAT_OPER_REHASH, FLAGS_OPER }, - { PRIV_RESTART, FEAT_OPER_RESTART, FLAGS_OPER }, - { PRIV_DIE, FEAT_OPER_DIE, FLAGS_OPER }, - { PRIV_GLINE, FEAT_OPER_GLINE, FLAGS_OPER }, - { PRIV_LOCAL_GLINE, FEAT_OPER_LGLINE, FLAGS_OPER }, - { PRIV_JUPE, FEAT_OPER_JUPE, FLAGS_OPER }, - { PRIV_LOCAL_JUPE, FEAT_OPER_LJUPE, FLAGS_OPER }, - { PRIV_OPMODE, FEAT_OPER_OPMODE, FLAGS_OPER }, - { PRIV_LOCAL_OPMODE, FEAT_OPER_LOPMODE, FLAGS_OPER }, - { PRIV_BADCHAN, FEAT_OPER_BADCHAN, FLAGS_OPER }, - { PRIV_LOCAL_BADCHAN, FEAT_OPER_LBADCHAN, FLAGS_OPER }, - { PRIV_SET, FEAT_OPER_SET, FLAGS_OPER }, - { PRIV_SEE_CHAN, FEAT_OPERS_SEE_IN_SECRET_CHANNELS, FLAGS_OPER }, - { PRIV_WIDE_GLINE, FEAT_OPER_WIDE_GLINE, FLAGS_OPER }, - - { PRIV_LOCAL_KILL, FEAT_LOCOP_KILL, FLAGS_LOCOP }, - { PRIV_REHASH, FEAT_LOCOP_REHASH, FLAGS_LOCOP }, - { PRIV_RESTART, FEAT_LOCOP_RESTART, FLAGS_LOCOP }, - { PRIV_DIE, FEAT_LOCOP_DIE, FLAGS_LOCOP }, - { PRIV_LOCAL_GLINE, FEAT_LOCOP_LGLINE, FLAGS_LOCOP }, - { PRIV_LOCAL_JUPE, FEAT_LOCOP_LJUPE, FLAGS_LOCOP }, - { PRIV_LOCAL_OPMODE, FEAT_LOCOP_LOPMODE, FLAGS_LOCOP }, - { PRIV_LOCAL_BADCHAN, FEAT_LOCOP_LBADCHAN, FLAGS_LOCOP }, - { PRIV_SET, FEAT_LOCOP_SET, FLAGS_LOCOP }, - { PRIV_SEE_CHAN, FEAT_LOCOP_SEE_IN_SECRET_CHANNELS, FLAGS_LOCOP }, - { PRIV_WIDE_GLINE, FEAT_LOCOP_WIDE_GLINE, FLAGS_LOCOP }, - { 0, FEAT_LAST_F, 0 } -}; +/** Default privilege set for global operators. */ +static struct Privs privs_global; +/** Default privilege set for local operators. */ +static struct Privs privs_local; +/** Non-zero if #privs_global and #privs_local have been initialized. */ +static int privs_defaults_set; /* client_set_privs(struct Client* client) * * Sets the privileges for opers. */ +/** Set the privileges for a client. + * @param[in] client Client who has become an operator. + * @param[in] oper Configuration item describing oper's privileges. + */ void -client_set_privs(struct Client* client) +client_set_privs(struct Client *client, struct ConfItem *oper) { - struct Privs privs; - struct Privs antiprivs; - int i; - - memset(&privs, 0, sizeof(struct Privs)); - memset(&antiprivs, 0, sizeof(struct Privs)); + struct Privs *source, *defaults; + enum Priv priv; - if (!IsAnOper(client)) { /* clear privilege mask */ - memset(&(cli_privs(client)), 0, sizeof(struct Privs)); - return; - } else if (!MyConnect(client)) { - memset(&(cli_privs(client)), 255, sizeof(struct Privs)); - PrivClr(&(cli_privs(client)), PRIV_SET); + if (!MyConnect(client)) return; + + /* Clear out client's privileges. */ + memset(cli_privs(client), 0, sizeof(struct Privs)); + + if (!IsAnOper(client) || !oper) + return; + + if (!privs_defaults_set) + { + memset(&privs_global, -1, sizeof(privs_global)); + FlagClr(&privs_global, PRIV_WALK_LCHAN); + FlagClr(&privs_global, PRIV_UNLIMIT_QUERY); + FlagClr(&privs_global, PRIV_SET); + FlagClr(&privs_global, PRIV_BADCHAN); + FlagClr(&privs_global, PRIV_LOCAL_BADCHAN); + FlagClr(&privs_global, PRIV_APASS_OPMODE); + + memset(&privs_local, 0, sizeof(privs_local)); + FlagSet(&privs_local, PRIV_CHAN_LIMIT); + FlagSet(&privs_local, PRIV_MODE_LCHAN); + FlagSet(&privs_local, PRIV_SHOW_INVIS); + FlagSet(&privs_local, PRIV_SHOW_ALL_INVIS); + FlagSet(&privs_local, PRIV_LOCAL_KILL); + FlagSet(&privs_local, PRIV_REHASH); + FlagSet(&privs_local, PRIV_LOCAL_GLINE); + FlagSet(&privs_local, PRIV_LOCAL_JUPE); + FlagSet(&privs_local, PRIV_LOCAL_OPMODE); + FlagSet(&privs_local, PRIV_WHOX); + FlagSet(&privs_local, PRIV_DISPLAY); + FlagSet(&privs_local, PRIV_FORCE_LOCAL_OPMODE); + + privs_defaults_set = 1; } - /* This sequence is temporary until the .conf is carefully rewritten */ - - for (i = 0; feattab[i].priv; i++) { - if (feattab[i].flag == 0) { - if (feature_bool(feattab[i].feat)) - PrivSet(&antiprivs, feattab[i].priv); - } else if (feattab[i].flag == ~0) { - if (!feature_bool(feattab[i].feat)) - PrivSet(&antiprivs, feattab[i].priv); - } else if (cli_flags(client) & feattab[i].flag) { - if (feattab[i].feat == FEAT_LAST_F || - feature_bool(feattab[i].feat)) - PrivSet(&privs, feattab[i].priv); - } + /* Decide whether to use global or local oper defaults. */ + if (FlagHas(&oper->privs_dirty, PRIV_PROPAGATE)) + defaults = FlagHas(&oper->privs, PRIV_PROPAGATE) ? &privs_global : &privs_local; + else if (FlagHas(&oper->conn_class->privs_dirty, PRIV_PROPAGATE)) + defaults = FlagHas(&oper->conn_class->privs, PRIV_PROPAGATE) ? &privs_global : &privs_local; + else { + assert(0 && "Oper has no propagation and neither does connection class"); + return; } - /* This is the end of the gross section */ + /* For each feature, figure out whether it comes from the operator + * conf, the connection class conf, or the defaults, then apply it. + */ + for (priv = 0; priv < PRIV_LAST_PRIV; ++priv) + { + /* Figure out most applicable definition for the privilege. */ + if (FlagHas(&oper->privs_dirty, priv)) + source = &oper->privs; + else if (FlagHas(&oper->conn_class->privs_dirty, priv)) + source = &oper->conn_class->privs; + else + source = defaults; - if (PrivHas(&privs, PRIV_PROPAGATE)) - PrivSet(&privs, PRIV_DISPLAY); /* force propagating opers to display */ - else { /* if they don't propagate oper status, prevent desyncs */ - PrivSet(&antiprivs, PRIV_KILL); - PrivSet(&antiprivs, PRIV_GLINE); - PrivSet(&antiprivs, PRIV_JUPE); - PrivSet(&antiprivs, PRIV_OPMODE); - PrivSet(&antiprivs, PRIV_BADCHAN); + /* Set it if necessary (privileges were already cleared). */ + if (FlagHas(source, priv)) + SetPriv(client, priv); } - for (i = 0; i <= _PRIV_IDX(PRIV_LAST_PRIV); i++) - privs.priv_mask[i] &= ~antiprivs.priv_mask[i]; - - cli_privs(client) = privs; + /* This should be handled in the config, but lets be sure... */ + if (HasPriv(client, PRIV_PROPAGATE)) + { + /* force propagating opers to display */ + SetPriv(client, PRIV_DISPLAY); + } + else + { + /* if they don't propagate oper status, prevent desyncs */ + ClrPriv(client, PRIV_KILL); + ClrPriv(client, PRIV_GLINE); + ClrPriv(client, PRIV_JUPE); + ClrPriv(client, PRIV_OPMODE); + ClrPriv(client, PRIV_BADCHAN); + } } +/** Array mapping privilege values to names and vice versa. */ static struct { - char *name; - unsigned int priv; + char *name; /**< Name of privilege. */ + unsigned int priv; /**< Enumeration value of privilege */ } privtab[] = { +/** Helper macro to define an array entry for a privilege. */ #define P(priv) { #priv, PRIV_ ## priv } P(CHAN_LIMIT), P(MODE_LCHAN), P(WALK_LCHAN), P(DEOP_LCHAN), P(SHOW_INVIS), P(SHOW_ALL_INVIS), P(UNLIMIT_QUERY), P(KILL), @@ -227,14 +234,16 @@ static struct { P(GLINE), P(LOCAL_GLINE), P(JUPE), P(LOCAL_JUPE), P(OPMODE), P(LOCAL_OPMODE), P(SET), P(WHOX), P(BADCHAN), P(LOCAL_BADCHAN), P(SEE_CHAN), P(PROPAGATE), - P(DISPLAY), P(SEE_OPERS), P(WIDE_GLINE), + P(DISPLAY), P(SEE_OPERS), P(WIDE_GLINE), P(LIST_CHAN), + P(FORCE_OPMODE), P(FORCE_LOCAL_OPMODE), P(APASS_OPMODE), #undef P { 0, 0 } }; -/* client_report_privs(struct Client *to, struct Client *client) - * - * Sends a summary of the oper's privileges to the oper. +/** Report privileges of \a client to \a to. + * @param[in] to Client requesting privilege list. + * @param[in] client Client whos privileges should be listed. + * @return Zero. */ int client_report_privs(struct Client *to, struct Client *client)