Use the m_grant from ircd-seven
Charybdis' rewritten m_grant introduces at least one serious bug without providing any apparent benefit. I think the best solution here is the easiest one. The bug in question is that an empty mode change is triggered after seven's grant has done its work, and this is necessary in order to give umodes granted by oper privileges a chance to update. The rewrite removes this, generating a mode change only if it wants to change the state of +o, which means the grant victim can keep privileged modes they no longer have access to, or fail to gain new ones.
This commit is contained in:
parent
8b7503c89a
commit
c1649fd04d
1 changed files with 133 additions and 148 deletions
|
@ -1,23 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2006 Jilles Tjoelker
|
* Copyright (C) 2006 Jilles Tjoelker
|
||||||
* Copyright (C) 2006 Stephen Bennett <spb@gentoo.org>
|
* Copyright (C) 2006 Stephen Bennett <spb@gentoo.org>
|
||||||
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
|
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* $Id$
|
||||||
* 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"
|
#include "stdinc.h"
|
||||||
|
@ -30,161 +15,161 @@
|
||||||
#include "s_serv.h"
|
#include "s_serv.h"
|
||||||
#include "s_conf.h"
|
#include "s_conf.h"
|
||||||
#include "s_newconf.h"
|
#include "s_newconf.h"
|
||||||
#include "privilege.h"
|
|
||||||
|
|
||||||
|
static int mo_grant(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
|
||||||
|
static int me_grant(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
|
||||||
|
|
||||||
static
|
static int do_grant(struct Client *source_p, struct Client *target_p, const char *new_privset);
|
||||||
void set_mode(struct Client *const target,
|
|
||||||
const char *const str)
|
struct Message grant_msgtab = {
|
||||||
|
"GRANT", 0, 0, 0, MFLG_SLOW,
|
||||||
|
{ mg_ignore, mg_not_oper, mg_ignore, mg_ignore, {me_grant, 3}, {mo_grant, 3}}
|
||||||
|
};
|
||||||
|
|
||||||
|
mapi_clist_av1 grant_clist[] = { &grant_msgtab, NULL };
|
||||||
|
|
||||||
|
DECLARE_MODULE_AV1(grant, NULL, NULL, grant_clist, NULL, NULL, "$Revision$");
|
||||||
|
|
||||||
|
extern struct mode_table oper_table[];
|
||||||
|
|
||||||
|
static int
|
||||||
|
mo_grant(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
|
||||||
{
|
{
|
||||||
const char *mode[] =
|
struct Client *target_p;
|
||||||
{
|
|
||||||
target->name,
|
|
||||||
target->name,
|
|
||||||
str,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
user_mode(target, target, 3, mode);
|
if(!IsOperGrant(source_p))
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
void set_privset(struct Client *const source,
|
|
||||||
struct Client *const target,
|
|
||||||
const char *const privset_name)
|
|
||||||
{
|
|
||||||
struct PrivilegeSet *const privset = privilegeset_get(privset_name);
|
|
||||||
if(!privset)
|
|
||||||
{
|
|
||||||
sendto_one_notice(source, ":There is no privilege set named '%s'.", privset_name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(IsOper(target) && target->user->privset == privset)
|
|
||||||
{
|
|
||||||
sendto_one_notice(source, ":%s already has role of %s.", target->name, privset_name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(IsOper(target))
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct oper_conf oper =
|
|
||||||
{
|
|
||||||
.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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
void grant_revoke(struct Client *const source,
|
|
||||||
struct Client *const target)
|
|
||||||
{
|
|
||||||
if(!IsOper(target))
|
|
||||||
{
|
|
||||||
sendto_one_notice(source, ":You can't deoper someone who isn't an oper.");
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
void grant(struct MsgBuf *msgbuf, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
|
|
||||||
{
|
|
||||||
if(MyClient(source_p) && !HasPrivilege(source_p, "oper:grant"))
|
|
||||||
{
|
{
|
||||||
sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "grant");
|
sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "grant");
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(parc < 3)
|
target_p = find_named_person(parv[1]);
|
||||||
|
if (target_p == NULL)
|
||||||
{
|
{
|
||||||
sendto_one_notice(source_p, ":usage GRANT: <target nickname> <privilegese name | 'revoke'>");
|
sendto_one_numeric(source_p, ERR_NOSUCHNICK,
|
||||||
return;
|
form_str(ERR_NOSUCHNICK), parv[1]);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Client *const target_p = find_person(parv[1]);
|
if (MyClient(target_p))
|
||||||
|
|
||||||
if(!target_p)
|
|
||||||
{
|
{
|
||||||
if(IsPerson(source_p))
|
do_grant(source_p, target_p, parv[2]);
|
||||||
sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), parv[1]);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if(!MyClient(source_p) && !find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_GRANT))
|
|
||||||
{
|
|
||||||
sendto_one_notice(source_p, ":GRANT failed: You have no shared configuration block on this server.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(MyClient(target_p))
|
|
||||||
{
|
|
||||||
if(irccmp(parv[2], "revoke") == 0)
|
|
||||||
grant_revoke(source_p, target_p);
|
|
||||||
else
|
|
||||||
set_privset(source_p, target_p, parv[2]);
|
|
||||||
}
|
|
||||||
else if(MyClient(source_p))
|
|
||||||
{
|
{
|
||||||
sendto_one(target_p, ":%s ENCAP %s GRANT %s %s",
|
sendto_one(target_p, ":%s ENCAP %s GRANT %s %s",
|
||||||
get_id(source_p, target_p),
|
get_id(source_p, target_p), target_p->servptr->name,
|
||||||
target_p->servptr->name,
|
get_id(target_p, target_p), parv[2]);
|
||||||
get_id(target_p, target_p),
|
|
||||||
parv[2]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Message msgtab =
|
static int me_grant(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
|
||||||
{
|
{
|
||||||
"GRANT", 0, 0, 0, 0,
|
struct Client *target_p;
|
||||||
|
|
||||||
|
target_p = find_person(parv[1]);
|
||||||
|
if (target_p == NULL)
|
||||||
{
|
{
|
||||||
mg_ignore,
|
sendto_one_numeric(source_p, ERR_NOSUCHNICK,
|
||||||
mg_not_oper,
|
form_str(ERR_NOSUCHNICK), parv[1]);
|
||||||
mg_ignore,
|
return 0;
|
||||||
mg_ignore,
|
|
||||||
{ grant, 3 },
|
|
||||||
{ grant, 3 }
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
mapi_clist_av1 grant_clist[] =
|
if(!find_shared_conf(source_p->username, source_p->host,
|
||||||
|
source_p->servptr->name, SHARED_GRANT))
|
||||||
|
{
|
||||||
|
sendto_one(source_p, ":%s NOTICE %s :You don't have an appropriate shared"
|
||||||
|
"block to grant privilege on this server.", me.name, source_p->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_grant(source_p, target_p, parv[2]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int do_grant(struct Client *source_p, struct Client *target_p, const char *new_privset)
|
||||||
{
|
{
|
||||||
&msgtab,
|
int dooper = 0, dodeoper = 0;
|
||||||
NULL
|
struct PrivilegeSet *privset = 0;
|
||||||
};
|
|
||||||
|
|
||||||
static const char grant_desc[] =
|
if (!strcmp(new_privset, "deoper"))
|
||||||
"Provides the grant facility for giving other users specific privilege sets";
|
{
|
||||||
|
if (!IsAnyOper(target_p))
|
||||||
|
{
|
||||||
|
sendto_one_notice(source_p, ":You can't deoper someone who isn't an oper.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
new_privset = "default";
|
||||||
|
dodeoper = 1;
|
||||||
|
|
||||||
DECLARE_MODULE_AV2
|
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);
|
||||||
grant,
|
}
|
||||||
NULL,
|
else
|
||||||
NULL,
|
{
|
||||||
grant_clist,
|
if (!(privset = privilegeset_get(new_privset)))
|
||||||
NULL,
|
{
|
||||||
NULL,
|
sendto_one_notice(source_p, ":There is no privilege set named '%s'.", new_privset);
|
||||||
NULL,
|
return 0;
|
||||||
NULL,
|
}
|
||||||
grant_desc
|
|
||||||
);
|
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 (!dodeoper)
|
||||||
|
{
|
||||||
|
if (!IsAnyOper(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 (dodeoper)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dooper)
|
||||||
|
{
|
||||||
|
struct oper_conf oper;
|
||||||
|
oper.name = "<grant>";
|
||||||
|
oper.umodes = 0;
|
||||||
|
oper.snomask = 0;
|
||||||
|
oper.privset = privset;
|
||||||
|
|
||||||
|
oper_up(target_p, &oper);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_p->user->privset = 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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue