X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/b9da417b4e5c56fe63fd7cefccc0cd9b2fa4b4b8..01fb744c405792dd3f0859a53f74cd4cb5fd166f:/modules/m_grant.c diff --git a/modules/m_grant.c b/modules/m_grant.c index 3788fb95..0f41f4c7 100644 --- a/modules/m_grant.c +++ b/modules/m_grant.c @@ -1,23 +1,6 @@ /* * Copyright (C) 2006 Jilles Tjoelker * Copyright (C) 2006 Stephen Bennett - * Copyright (C) 2016 Jason Volk - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * 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" @@ -30,161 +13,174 @@ #include "s_serv.h" #include "s_conf.h" #include "s_newconf.h" -#include "privilege.h" +#include "msgbuf.h" +static void mo_grant(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]); +static void me_grant(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]); -static -void set_mode(struct Client *const target, - const char *const str) -{ - const char *mode[] = - { - target->name, - target->name, - str, - NULL - }; +static int do_grant(struct Client *source_p, struct Client *target_p, const char *new_privset); - user_mode(target, target, 3, mode); -} +struct Message grant_msgtab = { + "GRANT", 0, 0, 0, 0, + { mg_ignore, mg_not_oper, mg_ignore, mg_ignore, {me_grant, 3}, {mo_grant, 3}} +}; + +mapi_clist_av1 grant_clist[] = { &grant_msgtab, NULL }; + +static const char grant_desc[] = "Allows operators to set or remove operator privileges on other users"; +DECLARE_MODULE_AV2(grant, NULL, NULL, grant_clist, NULL, NULL, NULL, NULL, grant_desc); -static -void set_privset(struct Client *const source, - struct Client *const target, - const char *const privset_name) +static void +mo_grant(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { - struct PrivilegeSet *const privset = privilegeset_get(privset_name); - if(!privset) + struct Client *target_p; + + if(!HasPrivilege(source_p, "oper:grant")) { - sendto_one_notice(source, ":There is no privilege set named '%s'.", privset_name); + sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "grant"); return; } - if(IsOper(target) && target->user->privset == privset) + target_p = find_named_person(parv[1]); + if (target_p == NULL) { - sendto_one_notice(source, ":%s already has role of %s.", target->name, privset_name); + sendto_one_numeric(source_p, ERR_NOSUCHNICK, + form_str(ERR_NOSUCHNICK), parv[1]); return; } - if(IsOper(target)) + if (MyClient(target_p)) { - sendto_one_notice(target, ":%s has changed your role to %s.", source->name, privset_name); - sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has changed %s's role to %s.", get_oper_name(source), target->name, privset_name); - target->user->privset = privset; - return; + do_grant(source_p, target_p, parv[2]); } - - struct oper_conf oper = + else { - .name = (char *)privset->name, - .privset = privset, - }; - - oper_up(target, &oper); - set_mode(target, "+o"); - sendto_one_notice(target, ":%s has granted you the role of %s.", source->name, privset_name); - sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has granted %s the role of %s.", get_oper_name(source), target->name, privset_name); + sendto_one(target_p, ":%s ENCAP %s GRANT %s %s", + get_id(source_p, target_p), target_p->servptr->name, + get_id(target_p, target_p), parv[2]); + } } - -static -void grant_revoke(struct Client *const source, - struct Client *const target) +static void +me_grant(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { - if(!IsOper(target)) + struct Client *target_p; + + target_p = find_person(parv[1]); + if (target_p == NULL) { - sendto_one_notice(source, ":You can't deoper someone who isn't an oper."); + sendto_one_numeric(source_p, ERR_NOSUCHNICK, + form_str(ERR_NOSUCHNICK), parv[1]); return; } - set_mode(target, "-o"); - sendto_one_notice(target, ":%s has deopered you.", source->name); - sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has deopered %s.", get_oper_name(source), target->name); + do_grant(source_p, target_p, parv[2]); } -static -void grant(struct MsgBuf *msgbuf, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) +static int do_grant(struct Client *source_p, struct Client *target_p, const char *new_privset) { - if(MyClient(source_p) && !HasPrivilege(source_p, "oper:grant")) + int dooper = 0, dodeoper = 0; + struct PrivilegeSet *privset = NULL, *old_privset = NULL; + + if (!strcasecmp(new_privset, "deoper")) { - sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "grant"); - return; + if (!IsOper(target_p)) + { + sendto_one_notice(source_p, ":You can't deoper someone who isn't an oper."); + return 0; + } + dodeoper = 1; + + sendto_one_notice(target_p, ":%s is deopering you.", source_p->name); + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is deopering %s.", get_oper_name(source_p), target_p->name); } - - if(parc < 3) + else { - sendto_one_notice(source_p, ":usage GRANT: "); - return; + if (!(privset = privilegeset_get(new_privset))) + { + sendto_one_notice(source_p, ":There is no privilege set named '%s'.", new_privset); + return 0; + } + + if (privset == target_p->user->privset) + { + sendto_one_notice(source_p, ":%s already has privilege set %s.", target_p->name, target_p->user->privset->name); + return 0; + } + + if (ConfigFileEntry.oper_secure_only && !IsSecureClient(target_p)) + { + sendto_one_notice(source_p, ":Cannot GRANT %s, opers must be using secure connections.", target_p->name); + return 0; + } } - struct Client *const target_p = find_person(parv[1]); - - if(!target_p) + if (!dodeoper) { - if(IsPerson(source_p)) - sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), parv[1]); - - return; + if (!IsOper(target_p)) + { + sendto_one_notice(target_p, ":%s is opering you with privilege set %s", source_p->name, privset->name); + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is opering %s with privilege set %s", get_oper_name(source_p), target_p->name, privset->name); + dooper = 1; + } + else + { + sendto_one_notice(target_p, ":%s is changing your privilege set to %s", source_p->name, privset->name); + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is changing the privilege set of %s to %s", get_oper_name(source_p), target_p->name, privset->name); + } + + if (!IsOper(target_p)) + { + dooper = 1; + } } - if(!MyClient(source_p) && !find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_GRANT)) + if (dodeoper) { - sendto_one_notice(source_p, ":GRANT failed: You have no shared configuration block on this server."); - return; + const char *modeparv[4]; + modeparv[0] = modeparv[1] = target_p->name; + modeparv[2] = "-o"; + modeparv[3] = NULL; + user_mode(target_p, target_p, 3, modeparv); + + return 0; } - if(MyClient(target_p)) + if (dooper) { - if(irccmp(parv[2], "revoke") == 0) - grant_revoke(source_p, target_p); - else - set_privset(source_p, target_p, parv[2]); + struct oper_conf oper = {0}; + oper.name = ""; + oper.privset = privset; + + oper_up(target_p, &oper); } - else if(MyClient(source_p)) + else { - sendto_one(target_p, ":%s ENCAP %s GRANT %s %s", - get_id(source_p, target_p), - target_p->servptr->name, - get_id(target_p, target_p), - parv[2]); - } + if (privset != NULL) + privilegeset_ref(privset); - return; -} + if (target_p->user->privset != NULL) + old_privset = target_p->user->privset; -struct Message msgtab = -{ - "GRANT", 0, 0, 0, 0, - { - mg_ignore, - mg_not_oper, - mg_ignore, - mg_ignore, - { grant, 3 }, - { grant, 3 } - } -}; + target_p->user->privset = privset; -mapi_clist_av1 grant_clist[] = -{ - &msgtab, - NULL -}; + if (privset != NULL) + sendto_server(NULL, NULL, CAP_TS6, NOCAPS, ":%s OPER %s %s", + use_id(target_p), target_p->user->opername, privset->name); -static const char grant_desc[] = - "Provides the grant facility for giving other users specific privilege sets"; - -DECLARE_MODULE_AV2 -( - grant, - NULL, - NULL, - grant_clist, - NULL, - NULL, - NULL, - NULL, - grant_desc -); + report_priv_change(target_p, old_privset, privset); + + if (old_privset != NULL) + privilegeset_unref(old_privset); + + const char *modeparv[4]; + modeparv[0] = modeparv[1] = target_p->name; + modeparv[2] = "+"; + modeparv[3] = NULL; + user_mode(target_p, target_p, 3, modeparv); + } + + return 0; +}