override: only engage override code if we're needing to authorize a WRITE to a channel's state (closes #65)

This commit is contained in:
William Pitcock 2015-12-10 01:00:32 -06:00
parent c7708a0994
commit 202d496644
8 changed files with 32 additions and 9 deletions

View file

@ -108,7 +108,7 @@ m_remove(struct Client *client_p, struct Client *source_p, int parc, const char
return 0; return 0;
} }
if(get_channel_access(source_p, msptr) < CHFL_CHANOP) if(get_channel_access(source_p, msptr, MODE_ADD) < CHFL_CHANOP)
{ {
if(MyConnect(source_p)) if(MyConnect(source_p))
{ {
@ -178,6 +178,7 @@ m_remove(struct Client *client_p, struct Client *source_p, int parc, const char
hookdata.msptr = msptr; hookdata.msptr = msptr;
hookdata.target = who; hookdata.target = who;
hookdata.approved = 1; hookdata.approved = 1;
hookdata.dir = MODE_ADD; /* ensure modules like override speak up */
call_hook(h_can_kick, &hookdata); call_hook(h_can_kick, &hookdata);

View file

@ -153,6 +153,9 @@ hack_channel_access(void *vdata)
{ {
hook_data_channel_approval *data = (hook_data_channel_approval *) vdata; hook_data_channel_approval *data = (hook_data_channel_approval *) vdata;
if (data->dir == MODE_QUERY)
return;
if (data->approved == CHFL_CHANOP) if (data->approved == CHFL_CHANOP)
return; return;
@ -189,6 +192,9 @@ hack_can_send(void *vdata)
{ {
hook_data_channel_approval *data = (hook_data_channel_approval *) vdata; hook_data_channel_approval *data = (hook_data_channel_approval *) vdata;
if (data->dir == MODE_QUERY)
return;
if (data->approved == CAN_SEND_NONOP || data->approved == CAN_SEND_OPV) if (data->approved == CAN_SEND_NONOP || data->approved == CAN_SEND_OPV)
return; return;

View file

@ -270,7 +270,7 @@ extern int match_extban(const char *banstr, struct Client *client_p, struct Chan
extern int valid_extban(const char *banstr, struct Client *client_p, struct Channel *chptr, long mode_type); extern int valid_extban(const char *banstr, struct Client *client_p, struct Channel *chptr, long mode_type);
const char * get_extban_string(void); const char * get_extban_string(void);
extern int get_channel_access(struct Client *source_p, struct membership *msptr); extern int get_channel_access(struct Client *source_p, struct membership *msptr, int dir);
extern void send_channel_join(struct Channel *chptr, struct Client *client_p); extern void send_channel_join(struct Channel *chptr, struct Client *client_p);

View file

@ -82,6 +82,7 @@ typedef struct
struct membership *msptr; struct membership *msptr;
struct Client *target; struct Client *target;
int approved; int approved;
int dir;
} hook_data_channel_approval; } hook_data_channel_approval;
typedef struct typedef struct

View file

@ -97,7 +97,7 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p
return 0; return 0;
} }
if(get_channel_access(source_p, msptr) < CHFL_CHANOP) if(get_channel_access(source_p, msptr, MODE_ADD) < CHFL_CHANOP)
{ {
if(MyConnect(source_p)) if(MyConnect(source_p))
{ {
@ -167,6 +167,7 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p
hookdata.msptr = msptr; hookdata.msptr = msptr;
hookdata.target = who; hookdata.target = who;
hookdata.approved = 1; hookdata.approved = 1;
hookdata.dir = MODE_ADD; /* ensure modules like override speak up */
call_hook(h_can_kick, &hookdata); call_hook(h_can_kick, &hookdata);

View file

@ -119,7 +119,7 @@ m_topic(struct Client *client_p, struct Client *source_p, int parc, const char *
} }
if(((chptr->mode.mode & MODE_TOPICLIMIT) == 0 || if(((chptr->mode.mode & MODE_TOPICLIMIT) == 0 ||
get_channel_access(source_p, msptr) >= CHFL_CHANOP) && get_channel_access(source_p, msptr, MODE_ADD) >= CHFL_CHANOP) &&
(!MyClient(source_p) || (!MyClient(source_p) ||
can_send(chptr, source_p, msptr))) can_send(chptr, source_p, msptr)))
{ {

View file

@ -821,6 +821,7 @@ can_send(struct Channel *chptr, struct Client *source_p, struct membership *mspt
hook_data_channel_approval moduledata; hook_data_channel_approval moduledata;
moduledata.approved = CAN_SEND_NONOP; moduledata.approved = CAN_SEND_NONOP;
moduledata.dir = MODE_QUERY;
if(IsServer(source_p) || IsService(source_p)) if(IsServer(source_p) || IsService(source_p))
return CAN_SEND_OPV; return CAN_SEND_OPV;
@ -871,6 +872,7 @@ can_send(struct Channel *chptr, struct Client *source_p, struct membership *mspt
moduledata.chptr = msptr->chptr; moduledata.chptr = msptr->chptr;
moduledata.msptr = msptr; moduledata.msptr = msptr;
moduledata.target = NULL; moduledata.target = NULL;
moduledata.dir = (moduledata.approved == CAN_SEND_NO) ? MODE_ADD : MODE_QUERY;
call_hook(h_can_send, &moduledata); call_hook(h_can_send, &moduledata);

View file

@ -179,7 +179,7 @@ cflag_orphan(char c_)
} }
int int
get_channel_access(struct Client *source_p, struct membership *msptr) get_channel_access(struct Client *source_p, struct membership *msptr, int dir)
{ {
hook_data_channel_approval moduledata; hook_data_channel_approval moduledata;
@ -194,6 +194,7 @@ get_channel_access(struct Client *source_p, struct membership *msptr)
moduledata.msptr = msptr; moduledata.msptr = msptr;
moduledata.target = NULL; moduledata.target = NULL;
moduledata.approved = is_chanop(msptr) ? CHFL_CHANOP : CHFL_PEON; moduledata.approved = is_chanop(msptr) ? CHFL_CHANOP : CHFL_PEON;
moduledata.dir = dir;
call_hook(h_get_channel_access, &moduledata); call_hook(h_get_channel_access, &moduledata);
@ -518,7 +519,7 @@ check_forward(struct Client *source_p, struct Channel *chptr,
if(MyClient(source_p) && !(targptr->mode.mode & MODE_FREETARGET)) if(MyClient(source_p) && !(targptr->mode.mode & MODE_FREETARGET))
{ {
if((msptr = find_channel_membership(targptr, source_p)) == NULL || if((msptr = find_channel_membership(targptr, source_p)) == NULL ||
get_channel_access(source_p, msptr) != CHFL_CHANOP) get_channel_access(source_p, msptr, MODE_QUERY) != CHFL_CHANOP)
{ {
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
me.name, source_p->name, targptr->chname); me.name, source_p->name, targptr->chname);
@ -1632,13 +1633,14 @@ set_channel_mode(struct Client *client_p, struct Client *source_p,
char *pbuf; char *pbuf;
int cur_len, mlen, paralen, paracount, arglen, len; int cur_len, mlen, paralen, paracount, arglen, len;
int i, j, flags; int i, j, flags;
int dir = MODE_ADD; int dir = MODE_QUERY;
int parn = 1; int parn = 1;
int errors = 0; int errors = 0;
int alevel; int alevel;
const char *ml = parv[0]; const char *ml = parv[0];
char c; char c;
struct Client *fakesource_p; struct Client *fakesource_p;
int reauthorized = 0; /* if we change from MODE_QUERY to MODE_ADD/MODE_DEL, then reauth once, ugly but it works */
mask_pos = 0; mask_pos = 0;
removed_mask_pos = 0; removed_mask_pos = 0;
@ -1646,23 +1648,33 @@ set_channel_mode(struct Client *client_p, struct Client *source_p,
mode_limit = 0; mode_limit = 0;
mode_limit_simple = 0; mode_limit_simple = 0;
alevel = get_channel_access(source_p, msptr);
/* Hide connecting server on netburst -- jilles */ /* Hide connecting server on netburst -- jilles */
if (ConfigServerHide.flatten_links && IsServer(source_p) && !has_id(source_p) && !HasSentEob(source_p)) if (ConfigServerHide.flatten_links && IsServer(source_p) && !has_id(source_p) && !HasSentEob(source_p))
fakesource_p = &me; fakesource_p = &me;
else else
fakesource_p = source_p; fakesource_p = source_p;
alevel = get_channel_access(source_p, msptr, dir);
for(; (c = *ml) != 0; ml++) for(; (c = *ml) != 0; ml++)
{ {
switch (c) switch (c)
{ {
case '+': case '+':
dir = MODE_ADD; dir = MODE_ADD;
if (!reauthorized)
{
alevel = get_channel_access(source_p, msptr, dir);
reauthorized = 1;
}
break; break;
case '-': case '-':
dir = MODE_DEL; dir = MODE_DEL;
if (!reauthorized)
{
alevel = get_channel_access(source_p, msptr, dir);
reauthorized = 1;
}
break; break;
case '=': case '=':
dir = MODE_QUERY; dir = MODE_QUERY;