X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/66e1914beb3c8290b6537ec9aaa5c80be63f75e0..ea41b24fd4807e3565bf5f8f293e2efc4c20b62d:/modules/m_privs.c diff --git a/modules/m_privs.c b/modules/m_privs.c index d8a32ebb..29e141ae 100644 --- a/modules/m_privs.c +++ b/modules/m_privs.c @@ -38,6 +38,7 @@ #include "modules.h" #include "s_conf.h" #include "s_newconf.h" +#include "hash.h" static const char privs_desc[] = "Provides the PRIVS command to inspect an operator's privileges"; @@ -55,63 +56,82 @@ mapi_clist_av1 privs_clist[] = { NULL }; -/* XXX this is a copy, not so nice */ +/* XXX this is a copy, not so nice + * + * Sort of... it's int in newconf.c since oper confs don't need 64-bit wide flags. + * --Elizafox + */ struct mode_table { const char *name; - unsigned int mode; + uint64_t mode; }; /* there is no such table like this anywhere else */ static struct mode_table auth_client_table[] = { - {"resv_exempt", FLAGS2_EXEMPTRESV }, - {"kline_exempt", FLAGS2_EXEMPTKLINE }, - {"flood_exempt", FLAGS2_EXEMPTFLOOD }, - {"spambot_exempt", FLAGS2_EXEMPTSPAMBOT }, - {"shide_exempt", FLAGS2_EXEMPTSHIDE }, - {"jupe_exempt", FLAGS2_EXEMPTJUPE }, - {"extend_chans", FLAGS2_EXTENDCHANS }, + {"resv_exempt", FLAGS_EXEMPTRESV }, + {"kline_exempt", FLAGS_EXEMPTKLINE }, + {"flood_exempt", FLAGS_EXEMPTFLOOD }, + {"spambot_exempt", FLAGS_EXEMPTSPAMBOT }, + {"shide_exempt", FLAGS_EXEMPTSHIDE }, + {"jupe_exempt", FLAGS_EXEMPTJUPE }, + {"extend_chans", FLAGS_EXTENDCHANS }, {NULL, 0} }; DECLARE_MODULE_AV2(privs, NULL, NULL, privs_clist, NULL, NULL, NULL, NULL, privs_desc); +static void append_priv(struct Client *source_p, struct Client *target_p, char *buf, const char *s1, const char *s2) +{ + /* 510 - ":" - " 270 " - " " - " :* " */ + size_t sourcelen = strlen(source_p->name); + if (sourcelen < 9) sourcelen = 9; + size_t limit = 499 - strlen(me.name) - sourcelen - strlen(target_p->name); + if (strlen(s1) + strlen(s2) + strlen(buf) + 1 > limit) + { + sendto_one_numeric(source_p, RPL_PRIVS, "%s :* %s", target_p->name, buf); + buf[0] = '\0'; + } + if (buf[0] != '\0') + rb_strlcat(buf, " ", BUFSIZE); + rb_strlcat(buf, s1, BUFSIZE); + rb_strlcat(buf, s2, BUFSIZE); +} + static void show_privs(struct Client *source_p, struct Client *target_p) { - char buf[512]; + char buf[BUFSIZE]; struct mode_table *p; buf[0] = '\0'; - if (target_p->localClient->privset) - rb_strlcat(buf, target_p->localClient->privset->privs, sizeof buf); - if (IsOper(target_p)) - { - if (buf[0] != '\0') - rb_strlcat(buf, " ", sizeof buf); - rb_strlcat(buf, "operator:", sizeof buf); - rb_strlcat(buf, target_p->localClient->opername, sizeof buf); - if (target_p->localClient->privset) + if (target_p->user->privset) + for (char *s = target_p->user->privset->privs; s != NULL; (s = strchr(s, ' ')) && s++) { - if (buf[0] != '\0') - rb_strlcat(buf, " ", sizeof buf); - rb_strlcat(buf, "privset:", sizeof buf); - rb_strlcat(buf, target_p->localClient->privset->name, sizeof buf); + char *c = strchr(s, ' '); + if (c) *c = '\0'; + append_priv(source_p, target_p, buf, s, ""); + if (c) *c = ' '; } + + if (IsOper(target_p)) + { + if (target_p->user->opername) + append_priv(source_p, target_p, buf, "operator:", target_p->user->opername); + + if (target_p->user->privset) + append_priv(source_p, target_p, buf, "privset:", target_p->user->privset->name); } p = &auth_client_table[0]; while (p->name != NULL) { - if (target_p->flags2 & p->mode) - { - if (buf[0] != '\0') - rb_strlcat(buf, " ", sizeof buf); - rb_strlcat(buf, p->name, sizeof buf); - } + if (target_p->flags & p->mode) + append_priv(source_p, target_p, buf, p->name, ""); p++; } - sendto_one_numeric(source_p, RPL_PRIVS, form_str(RPL_PRIVS), - target_p->name, buf); + + if (buf[0] != '\0') + sendto_one_numeric(source_p, RPL_PRIVS, "%s :%s", target_p->name, buf); } static void @@ -122,8 +142,9 @@ me_privs(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source if (!IsOper(source_p) || parc < 2 || EmptyString(parv[1])) return; - /* we cannot show privs for remote clients */ - if((target_p = find_person(parv[1])) && MyClient(target_p)) + target_p = find_person(parv[1]); + + if (target_p != NULL) show_privs(source_p, target_p); } @@ -131,13 +152,24 @@ static void mo_privs(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Client *target_p; + struct Client *server_p; if (parc < 2 || EmptyString(parv[1])) - target_p = source_p; + { + server_p = target_p = source_p; + } else { - target_p = find_named_person(parv[1]); - if (target_p == NULL) + if (parc >= 3) + { + server_p = find_named_client(parv[1]); + target_p = find_named_person(parv[2]); + } + else + { + server_p = target_p = find_named_person(parv[1]); + } + if (server_p == NULL || target_p == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), parv[1]); @@ -145,12 +177,22 @@ mo_privs(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source } } - if (MyClient(target_p)) + if (target_p != source_p && !HasPrivilege(source_p, "oper:privs")) + { + sendto_one(source_p, form_str(ERR_NOPRIVS), + me.name, source_p->name, "privs"); + return; + } + + if (!IsServer(server_p)) + server_p = server_p->servptr; + + if (IsMe(server_p)) show_privs(source_p, target_p); else - sendto_one(target_p, ":%s ENCAP %s PRIVS %s", - get_id(source_p, target_p), - target_p->servptr->name, + sendto_one(server_p, ":%s ENCAP %s PRIVS %s", + get_id(source_p, server_p), + server_p->name, use_id(target_p)); }