From d5e8b0339ab451beb8ac6b97211109b02d6c66c8 Mon Sep 17 00:00:00 2001 From: pk910 Date: Tue, 19 Jul 2011 00:15:43 +0200 Subject: [PATCH] extended MODE_FORWARD check (check if the user is allowed to use the passed target channel) --- src/chanserv.c | 8 ++++---- src/proto-bahamut.c | 2 +- src/proto-common.c | 2 +- src/proto-p10.c | 24 ++++++++++++++++++++++-- src/proto.h | 2 +- 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/chanserv.c b/src/chanserv.c index e1fc974..9044b20 100644 --- a/src/chanserv.c +++ b/src/chanserv.c @@ -4420,7 +4420,7 @@ static CHANSERV_FUNC(cmd_mode) base_oplevel = 1; else base_oplevel = 1 + UL_OWNER - uData->access; - change = mod_chanmode_parse(channel, argv+1, argc-1, MCP_KEY_FREE|MCP_IGN_REGISTERED|MCP_NO_APASS, base_oplevel); + change = mod_chanmode_parse(channel, user, argv+1, argc-1, MCP_KEY_FREE|MCP_IGN_REGISTERED|MCP_NO_APASS, base_oplevel); if(!change) { reply("MSG_INVALID_MODES", unsplit_string(argv+1, argc-1, NULL)); @@ -5674,7 +5674,7 @@ static MODCMD_FUNC(chan_opt_modes) { memset(&channel->channel_info->modes, 0, sizeof(channel->channel_info->modes)); } - else if(!(new_modes = mod_chanmode_parse(channel, argv+1, argc-1, MCP_KEY_FREE|MCP_IGN_REGISTERED|MCP_NO_APASS|(IsOper(user) && IsHelping(user) ? MCP_OPERMODE : 0), 0))) + else if(!(new_modes = mod_chanmode_parse(channel, user, argv+1, argc-1, MCP_KEY_FREE|MCP_IGN_REGISTERED|MCP_NO_APASS|(IsOper(user) && IsHelping(user) ? MCP_OPERMODE : 0), 0))) { reply("CSMSG_INVALID_MODE_LOCK", unsplit_string(argv+1, argc-1, NULL)); return 0; @@ -7701,7 +7701,7 @@ chanserv_conf_read(void) str = "+nt"; safestrncpy(mode_line, str, sizeof(mode_line)); ii = split_line(mode_line, 0, ArrayLength(modes), modes); - if((change = mod_chanmode_parse(NULL, modes, ii, MCP_KEY_FREE|MCP_NO_APASS, 0)) + if((change = mod_chanmode_parse(NULL, NULL, modes, ii, MCP_KEY_FREE|MCP_NO_APASS, 0)) && (change->argc < 2)) { chanserv_conf.default_modes = *change; @@ -8128,7 +8128,7 @@ chanserv_channel_read(const char *key, struct record_data *hir) if(!IsSuspended(cData) && (str = database_get_data(channel, KEY_MODES, RECDB_QSTRING)) && (argc = split_line(str, 0, ArrayLength(argv), argv)) - && (modes = mod_chanmode_parse(cNode, argv, argc, MCP_KEY_FREE|MCP_NO_APASS, 0))) { + && (modes = mod_chanmode_parse(cNode, NULL, argv, argc, MCP_KEY_FREE|MCP_NO_APASS, 0))) { cData->modes = *modes; if(off_channel > 0) cData->modes.modes_set |= MODE_REGISTERED; diff --git a/src/proto-bahamut.c b/src/proto-bahamut.c index 18bceeb..99ffa3b 100644 --- a/src/proto-bahamut.c +++ b/src/proto-bahamut.c @@ -1230,7 +1230,7 @@ void mod_usermode(struct userNode *user, const char *mode_change) { } struct mod_chanmode * -mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, unsigned int flags, short base_oplevel) +mod_chanmode_parse(struct chanNode *channel, struct userNode *user, char **modes, unsigned int argc, unsigned int flags, short base_oplevel) { struct mod_chanmode *change; unsigned int ii, in_arg, ch_arg, add; diff --git a/src/proto-common.c b/src/proto-common.c index 3b424d4..e690726 100644 --- a/src/proto-common.c +++ b/src/proto-common.c @@ -709,7 +709,7 @@ mod_chanmode(struct userNode *who, struct chanNode *channel, char **modes, unsig base_oplevel = member->oplevel; else base_oplevel = MAXOPLEVEL; - if (!(change = mod_chanmode_parse(channel, modes, argc, flags, base_oplevel))) + if (!(change = mod_chanmode_parse(channel, who, modes, argc, flags, base_oplevel))) return 0; if (flags & MC_ANNOUNCE) mod_chanmode_announce(who, channel, change); diff --git a/src/proto-p10.c b/src/proto-p10.c index c1271db..29bf7ac 100644 --- a/src/proto-p10.c +++ b/src/proto-p10.c @@ -2557,7 +2557,7 @@ keyncpy(char output[], char input[], size_t output_size) } struct mod_chanmode * -mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, unsigned int flags, short base_oplevel) +mod_chanmode_parse(struct chanNode *channel, struct userNode *user, char **modes, unsigned int argc, unsigned int flags, short base_oplevel) { struct mod_chanmode *change; unsigned int ii, in_arg, ch_arg, add; @@ -2677,8 +2677,28 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un if (add) { if (in_arg >= argc) goto error; + char *altchan = modes[in_arg++]; + struct chanNode *target; + if(!IsChannelName(altchan) || !(target = GetChannel(altchan))) + goto error; + if(!(flags & MCP_OPERMODE)) { + //check if the user has the permissions to use this channel as target + struct modeNode *mn; + struct userData *uData; + struct chanData *cData; + if(user && (mn = GetUserMode(target, user)) && (mn->modes & MODE_CHANOP)) { + //allow - user is opped on target channel + } else if(user && user->handle_info && + (uData = GetChannelUser(channel->channel_info, user->handle_info)) && + (cData = uData->channel) && + uData->access >= cData->lvlOpts[lvlGiveOps] + ) { + //allow - user has access to get op on the channel + } else + goto error; + } change->modes_set |= MODE_ALTCHAN; - safestrncpy(change->new_altchan, modes[in_arg++], sizeof(change->new_altchan)); + safestrncpy(change->new_altchan, altchan, sizeof(change->new_altchan)); } else { change->modes_clear |= MODE_ALTCHAN; } diff --git a/src/proto.h b/src/proto.h index aa83e83..54c5e23 100644 --- a/src/proto.h +++ b/src/proto.h @@ -234,7 +234,7 @@ struct mod_chanmode { struct mod_chanmode *mod_chanmode_alloc(unsigned int argc); struct mod_chanmode *mod_chanmode_dup(struct mod_chanmode *orig, unsigned int extra); -struct mod_chanmode *mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, unsigned int flags, short base_oplevel); +struct mod_chanmode *mod_chanmode_parse(struct chanNode *channel, struct userNode *user, char **modes, unsigned int argc, unsigned int flags, short base_oplevel); void mod_chanmode_apply(struct userNode *who, struct chanNode *channel, struct mod_chanmode *change); void mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod_chanmode *change); char *mod_chanmode_format(struct mod_chanmode *desc, char *buffer); -- 2.20.1