From 78e6b731e4210e6dc4de19bdc7ebc0184e84468a Mon Sep 17 00:00:00 2001 From: Stephen Bennett Date: Fri, 30 Apr 2010 22:01:21 +0100 Subject: [PATCH] Rework ircd-side MLOCK enforcement: instead of trying to track modes locked on or off, instead keep a simple list of mode letters that are locked, and reject any change to those modes. --- include/channel.h | 5 ++--- modules/core/m_mode.c | 2 +- src/channel.c | 1 + src/chmode.c | 45 +++++++++---------------------------------- 4 files changed, 13 insertions(+), 40 deletions(-) diff --git a/include/channel.h b/include/channel.h index 923871ed..b7a80f4f 100644 --- a/include/channel.h +++ b/include/channel.h @@ -39,7 +39,6 @@ struct Client; struct Mode { unsigned int mode; - unsigned int off_mode; int limit; char key[KEYLEN]; unsigned int join_num; @@ -52,7 +51,7 @@ struct Channel { rb_dlink_node node; struct Mode mode; - struct Mode mode_lock; + char *mode_lock; char *topic; char *topic_info; time_t topic_time; @@ -264,7 +263,7 @@ void resv_chan_forcepart(const char *name, const char *reason, int temp_time); extern void set_channel_mode(struct Client *client_p, struct Client *source_p, struct Channel *chptr, struct membership *msptr, int parc, const char *parv[]); extern void set_channel_mlock(struct Client *client_p, struct Client *source_p, - struct Channel *chptr, int parc, const char *parv[]); + struct Channel *chptr, const char *newmlock); extern struct ChannelMode chmode_table[256]; diff --git a/modules/core/m_mode.c b/modules/core/m_mode.c index 219b031c..4be9ab12 100644 --- a/modules/core/m_mode.c +++ b/modules/core/m_mode.c @@ -235,7 +235,7 @@ ms_mlock(struct Client *client_p, struct Client *source_p, int parc, const char return 0; if(IsServer(source_p)) - set_channel_mlock(client_p, source_p, chptr, parc - 3, parv + 3); + set_channel_mlock(client_p, source_p, chptr, parv[3]); return 0; } diff --git a/src/channel.c b/src/channel.c index 1a159f14..6c05cf1e 100644 --- a/src/channel.c +++ b/src/channel.c @@ -96,6 +96,7 @@ void free_channel(struct Channel *chptr) { rb_free(chptr->chname); + rb_free(chptr->mode_lock); rb_bh_free(channel_heap, chptr); } diff --git a/src/chmode.c b/src/chmode.c index ea0613ba..b345b8e1 100644 --- a/src/chmode.c +++ b/src/chmode.c @@ -516,7 +516,7 @@ chm_simple(struct Client *source_p, struct Channel *chptr, return; /* setting + */ - if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type) && !(chptr->mode_lock.off_mode & mode_type)) + if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type)) { /* if +f is disabled, ignore an attempt to set +QF locally */ if(!ConfigChannel.use_forward && MyClient(source_p) && @@ -533,7 +533,7 @@ chm_simple(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count++].arg = NULL; } - else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type) && !(chptr->mode_lock.mode & mode_type)) + else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type)) { chptr->mode.mode &= ~mode_type; @@ -1662,6 +1662,9 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, dir = MODE_QUERY; break; default: + /* If this mode char is locked, don't allow local users to change it. */ + if (MyClient(source_p) && chptr->mode_lock && strchr(chptr->mode_lock, c)) + continue; chmode_table[(unsigned char) c].set_func(fakesource_p, chptr, alevel, parc, &parn, parv, &errors, dir, c, @@ -1768,41 +1771,11 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, */ void set_channel_mlock(struct Client *client_p, struct Client *source_p, - struct Channel *chptr, int parc, const char *parv[]) + struct Channel *chptr, const char *newmlock) { - int dir = MODE_ADD; - const char *ml = parv[0]; - char c; - - memset(&chptr->mode_lock, '\0', sizeof(struct Mode)); - - for(; (c = *ml) != 0; ml++) - { - switch (c) - { - case '+': - dir = MODE_ADD; - break; - case '-': - dir = MODE_DEL; - break; - default: - if (chmode_table[(unsigned char) c].set_func == chm_simple) - switch(dir) - { - case MODE_ADD: - chptr->mode_lock.mode |= chmode_table[(unsigned char) c].mode_type; - chptr->mode_lock.off_mode &= ~chmode_table[(unsigned char) c].mode_type; - break; - case MODE_DEL: - chptr->mode_lock.off_mode |= chmode_table[(unsigned char) c].mode_type; - chptr->mode_lock.mode &= ~chmode_table[(unsigned char) c].mode_type; - break; - } - break; - } - } + rb_free(chptr->mode_lock); + chptr->mode_lock = rb_strdup(newmlock); sendto_server(client_p, NULL, CAP_TS6 | CAP_MLOCK, NOCAPS, ":%s MLOCK %ld %s %s", - source_p->id, (long) chptr->channelts, chptr->chname, channel_mlock(chptr, &me)); + source_p->id, (long) chptr->channelts, chptr->chname, chptr->mode_lock); }