From 4ebf6862037bd6777e67d24cc2933a6aeb3b95e2 Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Wed, 3 Mar 2010 12:56:56 -0500 Subject: [PATCH 01/11] Add oper:override priv to the .confs --- doc/example.conf | 2 +- doc/reference.conf | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/example.conf b/doc/example.conf index b533f72..cf2f9f2 100755 --- a/doc/example.conf +++ b/doc/example.conf @@ -231,7 +231,7 @@ privset "global_op" { privset "admin" { extends = "global_op"; - privs = oper:admin, oper:die, oper:rehash, oper:spy; + privs = oper:admin, oper:die, oper:rehash, oper:spy, oper:override; }; operator "god" { diff --git a/doc/reference.conf b/doc/reference.conf index 94f07fe..0286bf6 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -419,6 +419,9 @@ privset "local_op" { * oper:xline: allows use of /quote xline/unxline * oper:resv: allows /quote resv/unresv and cmode +LP * oper:operwall: allows the oper to send/receive operwalls + * oper:override: allows the oper to set umode +p on themself + * which grants the ability to have implicit + * operator access in all channels. * oper:spy: allows 'operspy' features to see through +s * channels etc. see /quote help operspy * oper:hidden: hides the oper from /stats p @@ -442,7 +445,7 @@ privset "global_op" { privset "admin" { extends = "global_op"; - privs = oper:admin, oper:die, oper:rehash, oper:spy; + privs = oper:admin, oper:die, oper:rehash, oper:spy, oper:override; }; /* operator {}: defines ircd operators. (OLD O:) */ From c6fa55060c42f9cb2e788ddd3d0e774b945113a0 Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Wed, 3 Mar 2010 13:21:28 -0500 Subject: [PATCH 02/11] Made TOPIC override send snotes. --- modules/m_topic.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/modules/m_topic.c b/modules/m_topic.c index e81ce2c..cddf5f9 100644 --- a/modules/m_topic.c +++ b/modules/m_topic.c @@ -105,6 +105,8 @@ m_topic(struct Client *client_p, struct Client *source_p, int parc, const char * /* setting topic */ if(parc > 2) { + char topic_info[USERHOST_REPLYLEN]; + msptr = find_channel_membership(chptr, source_p); if(msptr == NULL) @@ -114,9 +116,20 @@ m_topic(struct Client *client_p, struct Client *source_p, int parc, const char * return 0; } - if((chptr->mode.mode & MODE_TOPICLIMIT) == 0 || is_any_op(msptr) || IsOverride(source_p)) + if(MyClient(source_p) && (chptr->mode.mode & MODE_TOPICLIMIT) && !is_chanop(msptr)) { - char topic_info[USERHOST_REPLYLEN]; + if(IsOverride(source_p)) + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "%s is overriding TOPIC on [%s]", + get_oper_name(source_p), chptr->chname); + else + { + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, parv[1]); + return 0; + } + + } if(ConfigChannel.host_in_topic) rb_sprintf(topic_info, "%s!%s@%s", @@ -135,11 +148,7 @@ m_topic(struct Client *client_p, struct Client *source_p, int parc, const char * source_p->name, source_p->username, source_p->host, chptr->chname, chptr->topic == NULL ? "" : chptr->topic); - } - else - sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), - get_id(&me, source_p), - get_id(source_p, source_p), name); + } else if(MyClient(source_p)) { From 4ed822ed95dd41839e83138c5d43c5078dca8780 Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Wed, 3 Mar 2010 13:52:31 -0500 Subject: [PATCH 03/11] Add override support to ban/quiet, owner, op, halfop and voice. --- src/chmode.c | 132 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 99 insertions(+), 33 deletions(-) diff --git a/src/chmode.c b/src/chmode.c index 2784ddc..ba6fbac 100644 --- a/src/chmode.c +++ b/src/chmode.c @@ -64,6 +64,7 @@ static int mode_count; static int mode_limit; static int mode_limit_simple; static int mask_pos; +static int no_override_deop; char cflagsbuf[256]; char cflagsmyinfo[256]; @@ -621,6 +622,7 @@ chm_staff(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].id = NULL; mode_changes[mode_count].mems = ALL_MEMBERS; + mode_changes[mode_count].override = 0; mode_changes[mode_count++].arg = NULL; } else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type)) @@ -632,6 +634,7 @@ chm_staff(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].caps = 0; mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].mems = ALL_MEMBERS; + mode_changes[mode_count].override = 0; mode_changes[mode_count].id = NULL; mode_changes[mode_count++].arg = NULL; } @@ -652,6 +655,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr, int rpl_endlist; int caps; int mems; + int override = 0; switch (mode_type) { @@ -725,11 +729,17 @@ chm_ban(struct Client *source_p, struct Channel *chptr, if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP && mode_type != CHFL_BAN && mode_type != CHFL_QUIET) { - if(!(*errors & SM_ERR_NOOPS)) - sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), - me.name, source_p->name, chptr->chname); - *errors |= SM_ERR_NOOPS; - return; + if(IsOverride(source_p)) + override = 1; + else + { + + if(!(*errors & SM_ERR_NOOPS)) + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, chptr->chname); + *errors |= SM_ERR_NOOPS; + return; + } } RB_DLINK_FOREACH(ptr, list->head) @@ -748,11 +758,17 @@ chm_ban(struct Client *source_p, struct Channel *chptr, if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { - if(!(*errors & SM_ERR_NOOPS)) - sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), - me.name, source_p->name, chptr->chname); - *errors |= SM_ERR_NOOPS; - return; + if(IsOverride(source_p)) + override = 1; + else + { + + if(!(*errors & SM_ERR_NOOPS)) + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, chptr->chname); + *errors |= SM_ERR_NOOPS; + return; + } } if(MyClient(source_p) && (++mode_limit > MAXMODEPARAMS)) @@ -804,6 +820,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].mems = mems; mode_changes[mode_count].id = NULL; + mode_changes[mode_count].override = override; mode_changes[mode_count++].arg = mask; } else if(dir == MODE_DEL) @@ -821,6 +838,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].mems = mems; mode_changes[mode_count].id = NULL; + mode_changes[mode_count].override = override; mode_changes[mode_count++].arg = mask; } } @@ -833,6 +851,7 @@ chm_owner(struct Client *source_p, struct Channel *chptr, struct membership *mstptr; const char *ownernick; struct Client *targ_p; + int override = 0; if(!ConfigChannel.use_owner) { @@ -845,11 +864,17 @@ chm_owner(struct Client *source_p, struct Channel *chptr, if(alevel != CHFL_OWNER) { - if(!(*errors & SM_ERR_NOOPS)) - sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), - me.name, source_p->name, chptr->chname); - *errors |= SM_ERR_NOOPS; - return; + if(IsOverride(source_p)) + override = 1; + else + { + + if(!(*errors & SM_ERR_NOOPS)) + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, chptr->chname); + *errors |= SM_ERR_NOOPS; + return; + } } if((dir == MODE_QUERY) || (parc <= *parn)) @@ -887,7 +912,11 @@ chm_owner(struct Client *source_p, struct Channel *chptr, if(dir == MODE_ADD) { if(targ_p == source_p) - return; + { + no_override_deop = 1; + if(!override) + return; + } mode_changes[mode_count].letter = c; mode_changes[mode_count].dir = MODE_ADD; @@ -896,6 +925,7 @@ chm_owner(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].arg = targ_p->name; + mode_changes[mode_count].override = override; mode_changes[mode_count++].client = targ_p; mstptr->flags |= CHFL_OWNER; @@ -916,6 +946,7 @@ chm_owner(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].arg = targ_p->name; + mode_changes[mode_count].override = override; mode_changes[mode_count++].client = targ_p; mstptr->flags &= ~CHFL_OWNER; @@ -930,14 +961,21 @@ chm_op(struct Client *source_p, struct Channel *chptr, struct membership *mstptr; const char *opnick; struct Client *targ_p; + int override = 0; if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER) { - if(!(*errors & SM_ERR_NOOPS)) - sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), - me.name, source_p->name, chptr->chname); - *errors |= SM_ERR_NOOPS; - return; + if(IsOverride(source_p)) + override = 1; + else + { + + if(!(*errors & SM_ERR_NOOPS)) + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, chptr->chname); + *errors |= SM_ERR_NOOPS; + return; + } } if((dir == MODE_QUERY) || (parc <= *parn)) @@ -975,7 +1013,11 @@ chm_op(struct Client *source_p, struct Channel *chptr, if(dir == MODE_ADD) { if(targ_p == source_p) - return; + { + no_override_deop = 1; + if(!override) + return; + } mode_changes[mode_count].letter = c; mode_changes[mode_count].dir = MODE_ADD; @@ -984,6 +1026,7 @@ chm_op(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].arg = targ_p->name; + mode_changes[mode_count].override = override; mode_changes[mode_count++].client = targ_p; mstptr->flags |= CHFL_CHANOP; @@ -1004,6 +1047,7 @@ chm_op(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].arg = targ_p->name; + mode_changes[mode_count].override = override; mode_changes[mode_count++].client = targ_p; mstptr->flags &= ~CHFL_CHANOP; @@ -1018,6 +1062,7 @@ chm_halfop(struct Client *source_p, struct Channel *chptr, struct membership *mstptr; const char *halfopnick; struct Client *targ_p; + int override = 0; if(!ConfigChannel.use_halfop) { @@ -1030,11 +1075,17 @@ chm_halfop(struct Client *source_p, struct Channel *chptr, if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER) { - if(!(*errors & SM_ERR_NOOPS)) - sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), - me.name, source_p->name, chptr->chname); - *errors |= SM_ERR_NOOPS; - return; + if(IsOverride(source_p)) + override = 1; + else + { + + if(!(*errors & SM_ERR_NOOPS)) + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, chptr->chname); + *errors |= SM_ERR_NOOPS; + return; + } } if((dir == MODE_QUERY) || (parc <= *parn)) @@ -1072,7 +1123,11 @@ chm_halfop(struct Client *source_p, struct Channel *chptr, if(dir == MODE_ADD) { if(targ_p == source_p) - return; + { + no_override_deop = 1; + if(!override) + return; + } mode_changes[mode_count].letter = c; mode_changes[mode_count].dir = MODE_ADD; @@ -1081,6 +1136,7 @@ chm_halfop(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].arg = targ_p->name; + mode_changes[mode_count].override = override; mode_changes[mode_count++].client = targ_p; mstptr->flags |= CHFL_HALFOP; @@ -1101,6 +1157,7 @@ chm_halfop(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].arg = targ_p->name; + mode_changes[mode_count].override = override; mode_changes[mode_count++].client = targ_p; mstptr->flags &= ~CHFL_HALFOP; @@ -1115,14 +1172,21 @@ chm_voice(struct Client *source_p, struct Channel *chptr, struct membership *mstptr; const char *opnick; struct Client *targ_p; + int override = 0; if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { - if(!(*errors & SM_ERR_NOOPS)) - sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), - me.name, source_p->name, chptr->chname); - *errors |= SM_ERR_NOOPS; - return; + if(IsOverride(source_p)) + override = 1; + else + { + + if(!(*errors & SM_ERR_NOOPS)) + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, chptr->chname); + *errors |= SM_ERR_NOOPS; + return; + } } if((dir == MODE_QUERY) || parc <= *parn) @@ -1166,6 +1230,7 @@ chm_voice(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].arg = targ_p->name; + mode_changes[mode_count].override = override; mode_changes[mode_count++].client = targ_p; mstptr->flags |= CHFL_VOICE; @@ -1179,6 +1244,7 @@ chm_voice(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].arg = targ_p->name; + mode_changes[mode_count].override = override; mode_changes[mode_count++].client = targ_p; mstptr->flags &= ~CHFL_VOICE; From b869e117f01851f05ff6d02b65b2719e829057a7 Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Wed, 3 Mar 2010 14:11:53 -0500 Subject: [PATCH 04/11] Woohoo! Override is complete barring a few possible cleanups in the futures. --- src/chmode.c | 119 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 88 insertions(+), 31 deletions(-) diff --git a/src/chmode.c b/src/chmode.c index ba6fbac..f6c3934 100644 --- a/src/chmode.c +++ b/src/chmode.c @@ -1259,14 +1259,20 @@ chm_limit(struct Client *source_p, struct Channel *chptr, const char *lstr; static char limitstr[30]; int limit; + int override = 0; if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { - if(!(*errors & SM_ERR_NOOPS)) - sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), - me.name, source_p->name, chptr->chname); - *errors |= SM_ERR_NOOPS; - return; + if(IsOverride(source_p)) + override = 1; + else + { + if(!(*errors & SM_ERR_NOOPS)) + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, chptr->chname); + *errors |= SM_ERR_NOOPS; + return; + } } if(dir == MODE_QUERY) @@ -1291,6 +1297,7 @@ chm_limit(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = NULL; + mode_changes[mode_count].override = override; mode_changes[mode_count++].arg = limitstr; chptr->mode.limit = limit; @@ -1308,6 +1315,7 @@ chm_limit(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = NULL; + mode_changes[mode_count].override = override; mode_changes[mode_count++].arg = NULL; } } @@ -1318,14 +1326,21 @@ chm_throttle(struct Client *source_p, struct Channel *chptr, const char **parv, int *errors, int dir, char c, long mode_type) { int joins = 0, timeslice = 0; + int override = 0; if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { - if(!(*errors & SM_ERR_NOOPS)) - sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), - me.name, source_p->name, chptr->chname); - *errors |= SM_ERR_NOOPS; - return; + if(IsOverride(source_p)) + override = 1; + else + { + + if(!(*errors & SM_ERR_NOOPS)) + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, chptr->chname); + *errors |= SM_ERR_NOOPS; + return; + } } if(dir == MODE_QUERY) @@ -1347,6 +1362,7 @@ chm_throttle(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = NULL; + mode_changes[mode_count].override = override; mode_changes[mode_count++].arg = parv[(*parn)]; (*parn)++; @@ -1370,6 +1386,7 @@ chm_throttle(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = NULL; + mode_changes[mode_count].override = override; mode_changes[mode_count++].arg = NULL; } } @@ -1382,6 +1399,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr, struct Channel *targptr = NULL; struct membership *msptr; const char *forward; + int override = 0; /* if +f is disabled, ignore local attempts to set it */ if(!ConfigChannel.use_forward && MyClient(source_p) && @@ -1404,11 +1422,16 @@ chm_forward(struct Client *source_p, struct Channel *chptr, #ifndef FORWARD_OPERONLY if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { - if(!(*errors & SM_ERR_NOOPS)) - sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), - me.name, source_p->name, chptr->chname); - *errors |= SM_ERR_NOOPS; - return; + if(IsOverride(source_p)) + override = 1; + else + { + if(!(*errors & SM_ERR_NOOPS)) + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, chptr->chname); + *errors |= SM_ERR_NOOPS; + return; + } } #else if(!IsOper(source_p) && !IsServer(source_p)) @@ -1454,9 +1477,14 @@ chm_forward(struct Client *source_p, struct Channel *chptr, if((msptr = find_channel_membership(targptr, source_p)) == NULL || is_any_op(msptr)) { - sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), - me.name, source_p->name, targptr->chname); - return; + if(IsOverride(source_p)) + override = 1; + else + { + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, targptr->chname); + return; + } } } @@ -1468,6 +1496,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].mems = ConfigChannel.use_forward ? ALL_MEMBERS : ONLY_SERVERS; mode_changes[mode_count].id = NULL; + mode_changes[mode_count].override = override; mode_changes[mode_count++].arg = forward; } else if(dir == MODE_DEL) @@ -1483,6 +1512,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = NULL; + mode_changes[mode_count].override = override; mode_changes[mode_count++].arg = NULL; } } @@ -1493,14 +1523,20 @@ chm_key(struct Client *source_p, struct Channel *chptr, const char **parv, int *errors, int dir, char c, long mode_type) { char *key; + int override = 0; if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { - if(!(*errors & SM_ERR_NOOPS)) - sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), - me.name, source_p->name, chptr->chname); - *errors |= SM_ERR_NOOPS; - return; + if(IsOverride(source_p)) + override = 1; + else + { + if(!(*errors & SM_ERR_NOOPS)) + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, chptr->chname); + *errors |= SM_ERR_NOOPS; + return; + } } if(dir == MODE_QUERY) @@ -1531,6 +1567,7 @@ chm_key(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = NULL; + mode_changes[mode_count].override = override; mode_changes[mode_count++].arg = chptr->mode.key; } else if(dir == MODE_DEL) @@ -1562,6 +1599,7 @@ chm_key(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = NULL; + mode_changes[mode_count].override = override; mode_changes[mode_count++].arg = "*"; } } @@ -1571,13 +1609,20 @@ chm_regonly(struct Client *source_p, struct Channel *chptr, int alevel, int parc, int *parn, const char **parv, int *errors, int dir, char c, long mode_type) { + int override = 0; + if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { - if(!(*errors & SM_ERR_NOOPS)) - sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), - me.name, source_p->name, chptr->chname); - *errors |= SM_ERR_NOOPS; - return; + if(IsOverride(source_p)) + override = 1; + else + { + if(!(*errors & SM_ERR_NOOPS)) + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, chptr->chname); + *errors |= SM_ERR_NOOPS; + return; + } } if(dir == MODE_QUERY) @@ -1601,6 +1646,7 @@ chm_regonly(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].id = NULL; + mode_changes[mode_count].override = override; mode_changes[mode_count++].arg = NULL; } @@ -1911,6 +1957,8 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, alevel = get_channel_access(source_p, msptr); + no_override_deop = 0; + /* Hide connecting server on netburst -- jilles */ if (ConfigServerHide.flatten_links && IsServer(source_p) && !has_id(source_p) && !HasSentEob(source_p)) fakesource_p = &me; @@ -1953,12 +2001,16 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, for (override = 0; override < (IsOverride(source_p) ? 2 : 1); ++override) { int was_on_chan = 0; + if(override) { if(msptr) + { was_on_chan = 1; + msptr->flags |= CHFL_CHANOP; + } else - add_user_to_channel(chptr, source_p, 0); + add_user_to_channel(chptr, source_p, CHFL_CHANOP); } for(j = 0, flags = ALL_MEMBERS; j < 2; j++, flags = ONLY_CHANOPS) @@ -2036,8 +2088,13 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, } } - if(override && !was_on_chan) - remove_user_from_channel(find_channel_membership(chptr, source_p)); + if(override) + { + if(!was_on_chan) + remove_user_from_channel(find_channel_membership(chptr, source_p)); + else if (!no_override_deop) + msptr->flags &= ~CHFL_CHANOP; + } } /* only propagate modes originating locally, or if we're hubbing */ if(MyClient(source_p) || rb_dlink_list_length(&serv_list) > 1) From 1cdd8fdfd7307c739623ec0a029ed61448742455 Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Wed, 3 Mar 2010 14:35:54 -0500 Subject: [PATCH 05/11] Framework for hidden (only opers can see/set them) chmodes. The first one of these is +M and the actual extension which handles +M will be added next commit. --- include/channel.h | 2 ++ include/chmode.h | 3 +++ src/channel.c | 4 ++++ src/chmode.c | 58 +++++++++++++++++++++++++++++++++++++++++++++-- src/send.c | 7 +++++- 5 files changed, 71 insertions(+), 3 deletions(-) diff --git a/include/channel.h b/include/channel.h index 1744acd..1cbcb1d 100644 --- a/include/channel.h +++ b/include/channel.h @@ -150,6 +150,7 @@ typedef int (*ExtbanFunc)(const char *data, struct Client *client_p, #define ONLY_SERVERS 0x0020 #define CHFL_HALFOP 0x0040 #define CHFL_OWNER 0x0080 +#define ONLY_OPERS 0x0100 #define ALL_MEMBERS CHFL_PEON #define ONLY_CHANOPS CHFL_CHANOP #define ONLY_CHANOPSVOICED (CHFL_CHANOP|CHFL_VOICE) @@ -183,6 +184,7 @@ typedef int (*ExtbanFunc)(const char *data, struct Client *client_p, #define MODE_NOCAPS 0x100000 /* Block messages in all capital letters */ #define MODE_NOREJOIN 0x200000 /* Block rejoin immediately after kick */ #define MODE_NOREPEAT 0x400000 /* Block repeat messages */ +#define MODE_NOOPERKICK 0x800000 /* disallow kicking opers */ #define CHFL_BAN 0x10000000 /* ban channel flag */ #define CHFL_EXCEPTION 0x20000000 /* exception to ban channel flag */ diff --git a/include/chmode.h b/include/chmode.h index 9538194..897c64f 100644 --- a/include/chmode.h +++ b/include/chmode.h @@ -48,6 +48,9 @@ extern void chm_simple(struct Client *source_p, struct Channel *chptr, extern void chm_ban(struct Client *source_p, struct Channel *chptr, int alevel, int parc, int *parn, const char **parv, int *errors, int dir, char c, long mode_type); +extern void chm_hidden(struct Client *source_p, struct Channel *chptr, + int alevel, int parc, int *parn, + const char **parv, int *errors, int dir, char c, long mode_type); extern void chm_staff(struct Client *source_p, struct Channel *chptr, int alevel, int parc, int *parn, const char **parv, int *errors, int dir, char c, long mode_type); diff --git a/src/channel.c b/src/channel.c index 89c271b..fb0fd35 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1252,8 +1252,12 @@ channel_modes(struct Channel *chptr, struct Client *client_p) *pbuf = '\0'; for (i = 0; i < 256; i++) + { + if(chmode_table[i].set_func == chm_hidden && !IsOper(client_p)) + continue; if(chptr->mode.mode & chmode_flags[i]) *mbuf++ = i; + } if(chptr->mode.limit) { diff --git a/src/chmode.c b/src/chmode.c index f6c3934..cb2e224 100644 --- a/src/chmode.c +++ b/src/chmode.c @@ -587,6 +587,59 @@ chm_orphaned(struct Client *source_p, struct Channel *chptr, } } +void +chm_hidden(struct Client *source_p, struct Channel *chptr, + int alevel, int parc, int *parn, + const char **parv, int *errors, int dir, char c, long mode_type) +{ + if(!IsOper(source_p) && !IsServer(source_p)) + { + if(!(*errors & SM_ERR_NOPRIVS)) + sendto_one_numeric(source_p, ERR_NOPRIVILEGES, form_str(ERR_NOPRIVILEGES)); + *errors |= SM_ERR_NOPRIVS; + return; + } + if(MyClient(source_p) && !IsOperAdmin(source_p)) + { + if(!(*errors & SM_ERR_NOPRIVS)) + sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, + source_p->name, "cmodes"); + *errors |= SM_ERR_NOPRIVS; + return; + } + + if(MyClient(source_p) && (++mode_limit_simple > MAXMODES_SIMPLE)) + return; + + /* setting + */ + if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type)) + { + chptr->mode.mode |= mode_type; + + mode_changes[mode_count].letter = c; + mode_changes[mode_count].dir = MODE_ADD; + mode_changes[mode_count].caps = 0; + mode_changes[mode_count].nocaps = 0; + mode_changes[mode_count].id = NULL; + mode_changes[mode_count].mems = ONLY_OPERS; + mode_changes[mode_count].override = 0; + mode_changes[mode_count++].arg = NULL; + } + else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type)) + { + chptr->mode.mode &= ~mode_type; + + mode_changes[mode_count].letter = c; + mode_changes[mode_count].dir = MODE_DEL; + mode_changes[mode_count].caps = 0; + mode_changes[mode_count].nocaps = 0; + mode_changes[mode_count].mems = ONLY_OPERS; + mode_changes[mode_count].id = NULL; + mode_changes[mode_count].override = 0; + mode_changes[mode_count++].arg = NULL; + } +} + void chm_staff(struct Client *source_p, struct Channel *chptr, int alevel, int parc, int *parn, @@ -1731,7 +1784,7 @@ struct ChannelMode chmode_table[256] = {chm_simple, MODE_NOREJOIN }, /* J */ {chm_simple, MODE_NOREPEAT }, /* K */ {chm_staff, MODE_EXLIMIT }, /* L */ - {chm_nosuch, 0 }, /* M */ + {chm_hidden, MODE_NOOPERKICK }, /* M */ {chm_simple, MODE_NONICK }, /* N */ {chm_nosuch, 0 }, /* O */ {chm_staff, MODE_PERMANENT }, /* P */ @@ -1949,6 +2002,7 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, const char *ml = parv[0]; char c; struct Client *fakesource_p; + int flags_list[3] = { ALL_MEMBERS, ONLY_CHANOPS, ONLY_OPERS }; mask_pos = 0; mode_count = 0; @@ -2013,7 +2067,7 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, add_user_to_channel(chptr, source_p, CHFL_CHANOP); } - for(j = 0, flags = ALL_MEMBERS; j < 2; j++, flags = ONLY_CHANOPS) + for(j = 0, flags = flags_list[0]; j < 3; j++, flags = flags_list[j]) { cur_len = mlen; mbuf = modebuf + mlen; diff --git a/src/send.c b/src/send.c index e5d71f2..db98c57 100644 --- a/src/send.c +++ b/src/send.c @@ -646,7 +646,12 @@ sendto_channel_local(int type, struct Channel *chptr, const char *pattern, ...) if(IsIOError(target_p)) continue; - if(type && ((msptr->flags & type) == 0)) + if(type == ONLY_OPERS) + { + if(!IsOper(target_p)) + continue; + } + else if(type && ((msptr->flags & type) == 0)) continue; _send_linebuf(target_p, &linebuf); From 0e4a619958a799b87c24c0200db8b17985bf6fe4 Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Wed, 3 Mar 2010 14:44:41 -0500 Subject: [PATCH 06/11] Added immune extension. Maybe it'll be added to the docs later...Maybe not.. --- extensions/Makefile.in | 1 + extensions/make_override_immune.c | 36 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 extensions/make_override_immune.c diff --git a/extensions/Makefile.in b/extensions/Makefile.in index 1c234eb..2b80314 100644 --- a/extensions/Makefile.in +++ b/extensions/Makefile.in @@ -46,6 +46,7 @@ SRCS = \ force_user_invis.c \ hurt.c \ ip_cloaking.c \ + make_override_immune.c \ sno_farconnect.c \ sno_globalkline.c \ sno_globaloper.c \ diff --git a/extensions/make_override_immune.c b/extensions/make_override_immune.c new file mode 100644 index 0000000..148b8d9 --- /dev/null +++ b/extensions/make_override_immune.c @@ -0,0 +1,36 @@ +#include "stdinc.h" +#include "modules.h" +#include "hook.h" +#include "client.h" +#include "ircd.h" +#include "send.h" +#include "numeric.h" +#include "chmode.h" +#include "s_newconf.h" + +static void can_kick(hook_data_channel_approval *); + +mapi_hfn_list_av1 nooperkick_hfnlist[] = { + { "can_kick", (hookfn) can_kick }, + { NULL, NULL } +}; + +DECLARE_MODULE_AV1(chm_no_oper_kick, NULL, NULL, NULL, NULL, nooperkick_hfnlist, "$Revision$"); + +static void +can_kick(hook_data_channel_approval *data) +{ + struct Client *source_p = data->client; + struct Client *target_p = data->target; + struct Channel *chptr = data->chptr; + + if (target_p->umodes & UMODE_OVERRIDE && data->approved) + { + sendto_one_numeric(source_p, ERR_ISCHANSERVICE, + "%s %s :User is immune from kick.", + target_p->name, chptr->chname); + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Overriding KICK from %s on %s in %s (user is immune)", + source_p->name, target_p->name, chptr->chname); + data->approved = 0; + } +} From f428b59fa812e7ce6c3f7a038d19dde27bdfc0aa Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Wed, 3 Mar 2010 14:51:25 -0500 Subject: [PATCH 07/11] Add +M awareness to KICK. --- modules/core/m_kick.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/modules/core/m_kick.c b/modules/core/m_kick.c index 8ed49f4..12bf5de 100644 --- a/modules/core/m_kick.c +++ b/modules/core/m_kick.c @@ -173,6 +173,17 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p return 0; } + if (MyClient(source_p) && chptr->mode.mode & MODE_NOOPERKICK && IsOper(who)) + { + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "Overriding KICK from %s on %s in %s (channel is +M)", + source_p->name, who->name, chptr->chname); + sendto_one_numeric(source_p, ERR_ISCHANSERVICE, + "%s %s :Cannot kick IRC operators from that channel.", + who->name, chptr->chname); + return 0; + } + if(MyClient(source_p)) { hook_data_channel_approval hookdata; From 565f4362f206d5f45a5e0acbe656aa3e0389140e Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Wed, 3 Mar 2010 15:16:06 -0500 Subject: [PATCH 08/11] A couple more chm_hidden cleanups/fixes. --- modules/core/m_join.c | 64 ++++++++++++++++++++++++++++++++++--------- src/channel.c | 2 +- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/modules/core/m_join.c b/modules/core/m_join.c index 79ab428..3a5d05c 100644 --- a/modules/core/m_join.c +++ b/modules/core/m_join.c @@ -67,9 +67,10 @@ static void remove_ban_list(struct Channel *chptr, struct Client *source_p, rb_dlink_list * list, char c, int mems); static char modebuf[MODEBUFLEN]; +static char omodebuf[MODEBUFLEN]; static char parabuf[MODEBUFLEN]; static const char *para[MAXMODEPARAMS]; -static char *mbuf; +static char *mbuf, *ombuf; static int pargs; /* @@ -122,6 +123,7 @@ ms_join(struct Client *client_p, struct Client *source_p, int parc, const char * return 0; mbuf = modebuf; + ombuf = omodebuf; mode.key[0] = mode.forward[0] = '\0'; mode.mode = mode.limit = mode.join_num = mode.join_time = 0; @@ -190,7 +192,12 @@ ms_join(struct Client *client_p, struct Client *source_p, int parc, const char * ":%s MODE %s %s %s", source_p->servptr->name, chptr->chname, modebuf, parabuf); - *modebuf = *parabuf = '\0'; + if(*omodebuf != '\0') + sendto_channel_local(ONLY_OPERS, chptr, + ":%s MODE %s %s %s", + source_p->servptr->name, + chptr->chname, modebuf, parabuf); + *omodebuf = *modebuf = *parabuf = '\0'; } if(!IsMember(source_p, chptr)) @@ -249,7 +256,7 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char if(*parv[2] == '&') return 0; - modebuf[0] = parabuf[0] = mode.key[0] = mode.forward[0] = '\0'; + omodebuf[0] = modebuf[0] = parabuf[0] = mode.key[0] = mode.forward[0] = '\0'; pargs = mode.mode = mode.limit = mode.join_num = mode.join_time = 0; /* Hide connecting server on netburst -- jilles */ @@ -259,6 +266,7 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char fakesource_p = source_p; mbuf = modebuf; + ombuf = omodebuf; newts = atol(parv[1]); s = parv[3]; @@ -457,7 +465,11 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s %s %s", fakesource_p->name, chptr->chname, modebuf, parabuf); - *modebuf = *parabuf = '\0'; + if(*omodebuf != '\0') + sendto_channel_local(ONLY_OPERS, chptr, ":%s MODE %s %s %s", + fakesource_p->name, chptr->chname, omodebuf, parabuf); + + *omodebuf = *modebuf = *parabuf = '\0'; if(parv[3][0] != '0' && keep_new_modes) modes = channel_modes(chptr, source_p); @@ -469,6 +481,7 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char ptr_uid = buf_uid + mlen_uid; mbuf = modebuf; + ombuf = omodebuf; para[0] = para[1] = para[2] = para[3] = empty; pargs = 0; len_nick = len_uid = 0; @@ -799,7 +812,7 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char static void set_final_mode(struct Mode *mode, struct Mode *oldmode) { - int dir = MODE_QUERY; + int dir = MODE_QUERY, odir = MODE_QUERY; char *pbuf = parabuf; int len; int i; @@ -809,12 +822,25 @@ set_final_mode(struct Mode *mode, struct Mode *oldmode) { if((mode->mode & chmode_flags[i]) && !(oldmode->mode & chmode_flags[i])) { - if(dir != MODE_ADD) + if (chmode_table[i].set_func == chm_hidden) { - *mbuf++ = '+'; - dir = MODE_ADD; + if(odir != MODE_ADD) + { + *ombuf++ = '+'; + odir = MODE_ADD; + } + *ombuf++ = i; + } + else + { + if(dir != MODE_ADD) + { + *mbuf++ = '+'; + dir = MODE_ADD; + } + *mbuf++ = i; + } - *mbuf++ = i; } } @@ -823,12 +849,24 @@ set_final_mode(struct Mode *mode, struct Mode *oldmode) { if((oldmode->mode & chmode_flags[i]) && !(mode->mode & chmode_flags[i])) { - if(dir != MODE_DEL) + if(chmode_table[i].set_func == chm_hidden) { - *mbuf++ = '-'; - dir = MODE_DEL; + if(odir != MODE_DEL) + { + *ombuf++ = '-'; + odir = MODE_DEL; + } + *ombuf++ = i; + } + else + { + if(dir != MODE_DEL) + { + *mbuf++ = '-'; + dir = MODE_DEL; + } + *mbuf++ = i; } - *mbuf++ = i; } } diff --git a/src/channel.c b/src/channel.c index fb0fd35..4dd6b82 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1253,7 +1253,7 @@ channel_modes(struct Channel *chptr, struct Client *client_p) for (i = 0; i < 256; i++) { - if(chmode_table[i].set_func == chm_hidden && !IsOper(client_p)) + if(chmode_table[i].set_func == chm_hidden && !IsOper(client_p) && IsClient(client_p)) continue; if(chptr->mode.mode & chmode_flags[i]) *mbuf++ = i; From cb097b8840594b6a77aab21d0b4c20f036a7d012 Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Wed, 3 Mar 2010 15:34:57 -0500 Subject: [PATCH 09/11] Don't discard self-oppings from remote override opers. There's a small chance this could be incorrect. Also, the final set of override cleanups. --- modules/core/m_kick.c | 2 +- src/chmode.c | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/modules/core/m_kick.c b/modules/core/m_kick.c index 12bf5de..2dcdcc5 100644 --- a/modules/core/m_kick.c +++ b/modules/core/m_kick.c @@ -206,7 +206,7 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p if(is_override) sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is overriding KICK [%s] on [%s] [%s]", - get_oper_name(source_p), who->name, chptr->chname, comment); + get_oper_name(source_p), command, who->name, chptr->chname, comment); /* jdc * - In the case of a server kicking a user (i.e. CLEARCHAN), diff --git a/src/chmode.c b/src/chmode.c index cb2e224..442d6f1 100644 --- a/src/chmode.c +++ b/src/chmode.c @@ -783,7 +783,12 @@ chm_ban(struct Client *source_p, struct Channel *chptr, mode_type != CHFL_QUIET) { if(IsOverride(source_p)) - override = 1; + { + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "%s is overriding modes on %s: (%s list)", + get_oper_name(source_p), chptr->chname, + mode_type == CHFL_INVEX ? "invex" : "exempt"); + } else { @@ -967,8 +972,11 @@ chm_owner(struct Client *source_p, struct Channel *chptr, if(targ_p == source_p) { no_override_deop = 1; + /* Don't reject modes from remote. It desyncs, and this is perfectly + * legitimate from a remote override oper. if(!override) return; + */ } mode_changes[mode_count].letter = c; @@ -1068,8 +1076,11 @@ chm_op(struct Client *source_p, struct Channel *chptr, if(targ_p == source_p) { no_override_deop = 1; + /* Don't reject modes from remote. It desyncs, and this is perfectly + * legitimate from a remote override oper. if(!override) return; + */ } mode_changes[mode_count].letter = c; @@ -1178,8 +1189,11 @@ chm_halfop(struct Client *source_p, struct Channel *chptr, if(targ_p == source_p) { no_override_deop = 1; + /* Don't reject modes from remote. It desyncs, and this is perfectly + * legitimate from a remote override oper. if(!override) return; + */ } mode_changes[mode_count].letter = c; @@ -2052,7 +2066,7 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, source_p->name, source_p->username, source_p->host, chptr->chname); - for (override = 0; override < (IsOverride(source_p) ? 2 : 1); ++override) + for (override = 0; override < (IsOverride(source_p) && alevel != CHFL_CHANOP ? 2 : 1); ++override) { int was_on_chan = 0; From e7c1f6a51fe23d457a813cad1e7936da54696aa0 Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Wed, 3 Mar 2010 15:38:28 -0500 Subject: [PATCH 10/11] Luke! Use the fail Luke! The fail. I am made of it. * Jdhore boards the failboat. --- modules/core/m_kick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/m_kick.c b/modules/core/m_kick.c index 2dcdcc5..12bf5de 100644 --- a/modules/core/m_kick.c +++ b/modules/core/m_kick.c @@ -206,7 +206,7 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p if(is_override) sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is overriding KICK [%s] on [%s] [%s]", - get_oper_name(source_p), command, who->name, chptr->chname, comment); + get_oper_name(source_p), who->name, chptr->chname, comment); /* jdc * - In the case of a server kicking a user (i.e. CLEARCHAN), From fbb60f41c5a45c64284f5dc4f507f19e183c25d0 Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Wed, 3 Mar 2010 20:28:22 -0500 Subject: [PATCH 11/11] Remove override and immune from the shadow TODO since they're done now. --- TODO-SHADOW | 2 -- 1 file changed, 2 deletions(-) diff --git a/TODO-SHADOW b/TODO-SHADOW index 3b1f247..790b21f 100644 --- a/TODO-SHADOW +++ b/TODO-SHADOW @@ -4,8 +4,6 @@ Todo list for ShadowIRCd 6.0 * custom operstrings * norepeat cmode * kicknorejoin (+J in inspircd chmode) -* operoverride umode (+p), steal this from ircd-seven -* immune cmode (+M), steal this from ircd-seven too * Anything else we think of between now and release. :P Todo list for ShadowIRCd 6.1