diff --git a/extensions/Makefile.in b/extensions/Makefile.in index e7d6a57b..d9272d1c 100644 --- a/extensions/Makefile.in +++ b/extensions/Makefile.in @@ -54,6 +54,7 @@ SRCS = \ m_okick.c \ m_omode.c \ m_opme.c \ + m_privs.c \ m_webirc.c \ no_locops.c \ no_oper_invis.c \ diff --git a/extensions/m_privs.c b/extensions/m_privs.c new file mode 100644 index 00000000..beb8b9ea --- /dev/null +++ b/extensions/m_privs.c @@ -0,0 +1,179 @@ +/* + * m_privs.c: Shows effective operator privileges + * + * Copyright (C) 2008 Jilles Tjoelker + * Copyright (C) 2008 charybdis development team + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1.Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2.Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3.The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdinc.h" +#include "client.h" +#include "common.h" +#include "numeric.h" +#include "send.h" +#include "msg.h" +#include "parse.h" +#include "modules.h" +#include "s_conf.h" +#include "s_newconf.h" + +#define RPL_PRIVS 270 /* from ircu */ + +static int me_privs(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]); +static int mo_privs(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]); + +struct Message privs_msgtab = { + "PRIVS", 0, 0, 0, MFLG_SLOW, + {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_privs, 0}, {mo_privs, 0}} +}; + +mapi_clist_av1 privs_clist[] = { + &privs_msgtab, + NULL +}; + +/* XXX this is a copy, not so nice */ +struct mode_table +{ + const char *name; + int mode; +}; + +static struct mode_table oper_table[] = { + /*{"encrypted", OPER_ENCRYPTED },*/ + {"local_kill", OPER_LOCKILL }, + {"global_kill", OPER_GLOBKILL/*|OPER_LOCKILL*/ }, + {"remote", OPER_REMOTE }, + {"kline", OPER_KLINE }, + {"unkline", OPER_UNKLINE }, + {"gline", OPER_GLINE }, + {"nick_changes", OPER_NICKS }, + {"rehash", OPER_REHASH }, + {"die", OPER_DIE }, + {"admin", OPER_ADMIN }, + {"hidden_admin", OPER_HADMIN }, + {"xline", OPER_XLINE }, + {"resv", OPER_RESV }, + {"operwall", OPER_OPERWALL }, + {"oper_spy", OPER_SPY }, + {"hidden_oper", OPER_INVIS }, + {"remoteban", OPER_REMOTEBAN }, + {"mass_notice", OPER_MASSNOTICE }, + {NULL, 0} +}; + +/* there is no such table like this anywhere else */ +static struct mode_table auth_client_table[] = { + {"resv_exempt", FLAGS2_EXEMPTRESV }, + {"gline_exempt", FLAGS2_EXEMPTGLINE }, + {"kline_exempt", FLAGS2_EXEMPTKLINE }, + {"flood_exempt", FLAGS2_EXEMPTFLOOD }, + /*{"exceed_limit", FLAGS2_NOLIMIT }, no effect (?) */ + {"spambot_exempt", FLAGS2_EXEMPTSPAMBOT }, + {"shide_exempt", FLAGS2_EXEMPTSHIDE }, + {"jupe_exempt", FLAGS2_EXEMPTJUPE }, + {NULL, 0} +}; + +DECLARE_MODULE_AV1(privs, NULL, NULL, privs_clist, NULL, NULL, ""); + +static void show_privs(struct Client *source_p, struct Client *target_p) +{ + char buf[512]; + struct mode_table *p; + + buf[0] = '\0'; + p = &oper_table[0]; + while (p->name != NULL) + { + if (target_p->flags2 & p->mode) + { + if (buf[0] != '\0') + strlcat(buf, " ", sizeof buf); + strlcat(buf, p->name, sizeof buf); + } + p++; + } + if (IsOper(target_p)) + { + if (buf[0] != '\0') + strlcat(buf, " ", sizeof buf); + strlcat(buf, "O", sizeof buf); + } + p = &auth_client_table[0]; + while (p->name != NULL) + { + if (target_p->flags2 & p->mode) + { + if (buf[0] != '\0') + strlcat(buf, " ", sizeof buf); + strlcat(buf, p->name, sizeof buf); + } + p++; + } + sendto_one_numeric(source_p, RPL_PRIVS, "%s :%s", target_p->name, buf); +} + +static int me_privs(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) +{ + struct Client *target_p; + + if (!IsOper(source_p) || parc < 2 || EmptyString(parv[1])) + return 0; + + /* we cannot show privs for remote clients */ + if((target_p = find_person(parv[1])) && MyClient(target_p)) + show_privs(source_p, target_p); + + return 0; +} + +static int mo_privs(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) +{ + struct Client *target_p; + + if (parc < 2 || EmptyString(parv[1])) + target_p = source_p; + else + { + target_p = find_named_person(parv[1]); + if (target_p == NULL) + { + sendto_one_numeric(source_p, ERR_NOSUCHNICK, + form_str(ERR_NOSUCHNICK), parv[1]); + return 0; + } + } + + if (MyClient(target_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, + use_id(target_p)); + return 0; +}