diff -uNr ircservices-5.0.37/Changes ircservices-5.0.38/Changes --- ircservices-5.0.37/Changes 2004-07-27 18:03:00 +0900 +++ ircservices-5.0.38/Changes 2004-08-15 10:05:13 +0900 @@ -1,5 +1,9 @@ Version 5.0 ----------- +2004/08/15 .38 Services now checks channel joins against the channel's + current modes as well as mode locks, to prevent users + from "riding" netsplits into privileged channels. + Reported by Craig McLure 2004/07/27 .37 Autokicks now prefix the kick reason with "AKICK by " to avoid misleading kick messages. Suggested by Bergee diff -uNr ircservices-5.0.37/docs/6.html ircservices-5.0.38/docs/6.html --- ircservices-5.0.37/docs/6.html 2004-07-02 16:42:45 +0900 +++ ircservices-5.0.38/docs/6.html 2004-08-15 09:57:21 +0900 @@ -1354,20 +1354,24 @@

check_kick -
Parameters: User *user, ChannelInfo *ci, - char **mask_ret, +
Parameters: User *user, Channel *c, + ChannelInfo *ci, char **mask_ret, const char **reason_ret
Called when checking whether a user should be kicked from a - channel, before any standard checks are performed. The callback - routine may return: + channel, before any standard checks are performed. + user will not be NULL, but either or both + of c and ci may be NULL if + the channel is currently empty or not registered, respectively. + The callback routine may return:
  • 0, to allow normal processing to continue.
  • 1, to cause the user to be kicked from the channel. In this case, the callback routine must set *mask_ret - to a newly smalloc()'d memory area containing the - mask to be banned (create_mask() or sstrdup() - may also be used) and *reason_ret to a string - for use as the reason in the kick. + to a newly malloc()/smalloc()'d memory + area containing the mask to be banned (create_mask() + or sstrdup() may also be used) and + *reason_ret to a string for use as the + reason in the kick.
  • 2, to abort further processing and allow the user to enter the channel.
diff -uNr ircservices-5.0.37/modules/chanserv/check.c ircservices-5.0.38/modules/chanserv/check.c --- ircservices-5.0.37/modules/chanserv/check.c 2004-07-27 20:58:52 +0900 +++ ircservices-5.0.38/modules/chanserv/check.c 2004-08-15 10:26:44 +0900 @@ -282,6 +282,25 @@ goto kick; } + if (is_services_admin(user)) + return 0; + + i = call_callback_5(module, cb_check_kick, user, c, ci, &mask, &reason); + if (i == 2) + return 0; + else if (i == 1) + goto kick; + + /* Check join against channel's modes--this is properly the domain of + * the IRC server, but... */ + if (c) { + if ((c->mode & chanmode_opersonly) && !is_oper(user)) { + mask = create_mask(user, 1); + reason = getstring(user->ngi, CHAN_NOT_ALLOWED_TO_JOIN); + goto kick; + } + } + if (!ci) { if (CSRegisteredOnly && !is_oper(user)) { mask = sstrdup("*!*@*"); @@ -292,15 +311,6 @@ } } - if (is_services_admin(user)) - return 0; - - i = call_callback_4(module, cb_check_kick, user, ci, &mask, &reason); - if (i == 2) - return 0; - else if (i == 1) - goto kick; - if (is_oper(user)) return 0; diff -uNr ircservices-5.0.37/modules/protocol/ptlink.c ircservices-5.0.38/modules/protocol/ptlink.c --- ircservices-5.0.37/modules/protocol/ptlink.c 2004-07-27 20:58:52 +0900 +++ ircservices-5.0.38/modules/protocol/ptlink.c 2004-08-15 10:26:45 +0900 @@ -515,11 +515,11 @@ /*************************************************************************/ -static int do_check_kick(User *user, ChannelInfo *ci, char **mask_ret, - const char **reason_ret) +static int do_check_kick(User *user, Channel *c, ChannelInfo *ci, + char **mask_ret, const char **reason_ret) { /* Don't let plain opers into +A (admin only) channels */ - if ((ci->mlock_on & chanmode_admins_only) + if ((((c?c->mode:0) | (ci?ci->mlock_on:0)) & chanmode_admins_only) && !(user->mode & usermode_admin) ) { *mask_ret = create_mask(user, 1); diff -uNr ircservices-5.0.37/modules/protocol/unreal.c ircservices-5.0.38/modules/protocol/unreal.c --- ircservices-5.0.37/modules/protocol/unreal.c 2004-07-27 20:58:52 +0900 +++ ircservices-5.0.38/modules/protocol/unreal.c 2004-08-15 10:26:45 +0900 @@ -1279,15 +1279,15 @@ * secure-only, and no-hiding channel modes here. */ -static int do_check_kick(User *user, ChannelInfo *ci, char **mask_ret, - const char **reason_ret) +static int do_check_kick(User *user, Channel *c, ChannelInfo *ci, + char **mask_ret, const char **reason_ret) { /* Don't do anything to service pseudoclients */ if (user->mode & mode_char_to_flag('S', MODE_USER)) return 2; /* Don't let plain opers into +A (admin only) channels */ - if ((ci->mlock_on & chanmode_admins_only) + if ((((c?c->mode:0) | (ci?ci->mlock_on:0)) & chanmode_admins_only) && !(user->mode & usermode_admin) ) { *mask_ret = create_mask(user, 1); @@ -1295,7 +1295,7 @@ return 1; } /* Don't let users not on secure connections (-z) into +z channels */ - if ((ci->mlock_on & chanmode_secure_only) + if ((((c?c->mode:0) | (ci?ci->mlock_on:0)) & chanmode_secure_only) && !(user->mode & usermode_secure) ) { *mask_ret = create_mask(user, 1); @@ -1303,7 +1303,9 @@ return 1; } /* Don't let hiding users into no-hiding channels */ - if ((ci->mlock_on & chanmode_no_hiding) && (user->mode & usermode_hiding)){ + if ((((c?c->mode:0) | (ci?ci->mlock_on:0)) & chanmode_no_hiding) + && (user->mode & usermode_hiding) + ) { *mask_ret = create_mask(user, 1); *reason_ret = getstring(user->ngi, CHAN_NOT_ALLOWED_TO_JOIN); return 1; diff -uNr ircservices-5.0.37/version.sh ircservices-5.0.38/version.sh --- ircservices-5.0.37/version.sh 2004-07-27 18:08:26 +0900 +++ ircservices-5.0.38/version.sh 2004-08-15 10:15:25 +0900 @@ -6,7 +6,7 @@ # $PROGRAM is the string returned as the first part of a /VERSION reply, # and must not contain spaces. It is not used anywhere else. PROGRAM=ircservices -VERSION=5.0.37 +VERSION=5.0.38 # Increment Services build number if [ -f version.c ] ; then