diff -uNr ircservices-5.0.29/Changes ircservices-5.0.30/Changes --- ircservices-5.0.29/Changes 2004-03-24 19:14:20 +0900 +++ ircservices-5.0.30/Changes 2004-04-14 11:25:26 +0900 @@ -1,5 +1,32 @@ Version 5.0 ----------- +2004/04/09 .30 Added logic to configure script to avoid the use of the + -fstack-protector option if doing so would trigger a + compiler bug. Reported by Torbjo"rn Svennson + +2004/04/06 ChanServ no longer requires an explicit IDENTIFY to use INFO + ALL. Reported by Wolfgang Urban +2004/04/06 NickServ LISTCHANS now properly aborts when a non-servadmin + uses the nickname form of the command. Reported by + Elijah +2004/04/04 The ChanServ DEPROTECT command now clears channel-owner + status on those IRC servers that support such a mode. + Suggested by +2004/04/02 Fixed additional bug causing autokill exclusions to not + function properly in some cases. +2004/04/02 Fixed bug causing autokill exclusions to not function under + Unreal. Reported by Eric Murphy +2004/03/31 Fixed bug allowing users to improperly be identified for + newly-registered nicknames awaiting authentication. + Reported by +2004/03/30 Added workaround for Unreal SQLINE "bouncing" issue. + Reported by Craig Edwards +2004/03/30 ChanServ SET RESTRICTED no longer modifies the internal + NOJOIN level. +2004/03/30 Fixed failure to reset internal-use AUTODEOP and NOJOIN + channel levels when loading databases from version 4.5 + and earlier. Reported by Wolfgang Urban + 2004/03/24 .29 Added support for extended ban types, new channel mode +f format, and other feeping creaturism in Unreal 3.2. 2004/03/24 Fixed PTlink channel database reading, and added workaround @@ -234,7 +261,7 @@ 2003/04/23 Fixed bug causing NickServ LIST to not return matches to Services admins for a pattern matching real hostnames but not fake ones. Reported by Craig Edwards - + 2003/04/22 Fixed bug processing %hd and missing my_snprintf() in vsnprintf.c. 2003/04/20 .17 Fixed crash when using UNLINK FORCE with non-linked nicks. diff -uNr ircservices-5.0.29/TODO ircservices-5.0.30/TODO --- ircservices-5.0.29/TODO 2004-02-05 20:46:17 +0900 +++ ircservices-5.0.30/TODO 2004-04-14 10:16:34 +0900 @@ -1,5 +1,8 @@ Things to probably do: +CS Make DROP work like NickServ: require password for regular users, + have separate DROPCHAN command for servadmins +** Rate-limit message floods (e.g. botnet autokill expiration) OS AKILL/etc. DEL ALL (or CLEAR?) NS/MS Add a separate mail address field for memo forwarding CS Add a modules.conf option to set the default channel mlock @@ -51,6 +54,12 @@ Things to think about: +CS Option to autokill users entering a forbidden channel (botnets) + [] +NS "Online as linked nick" field in INFO? eg "Online as SomeNick[away]" + [Craig McLure ] +NS Allow masks for "unregisterable-but-usable" nicks + [Mark Hetherington ] CS Allow autokick exceptions [Dionisios K. ] CS Specify (in conf file) modes that users are not allowed to change @@ -159,3 +168,7 @@ wrong address is given in a REGISTER or SET EMAIL command, a Services administrator will need to manually intervene and either reset the address or drop the nick. +CS Automatically set/clear op/voice/etc. on channel access list change + Access list changes are typically one-time events, and don't + warrant the added complexity of such a feature; it's easy + enough to manually op/voice the user. diff -uNr ircservices-5.0.29/configure ircservices-5.0.30/configure --- ircservices-5.0.29/configure 2004-02-18 23:03:25 +0900 +++ ircservices-5.0.30/configure 2004-04-09 17:38:06 +0900 @@ -52,7 +52,14 @@ # Return the default flags for the given C compiler. def_cc_flags () { - if [ "X$1" = "Xgcc" -o "X$1" = "Xgcc3" -o "X$1" = "Xkgcc" ] ; then + GCC=no + a=`echo "x$1" | cut -c1-4` + if [ "$a" = "xgcc" -o "x$1" = "xkgcc" ] ; then + GCC=yes + elif "$1" --version 2>/dev/null | grep_q '(GCC)' ; then + GCC=yes + fi + if [ $GCC = yes ] ; then echo "-O2 -fno-strict-aliasing" elif [ "X$1" = "Xicc" ] ; then echo "-O0 -wd144,167,556" @@ -149,6 +156,8 @@ with information about your system, the output from this script, and the \`configure.log' file generated by this script. +Configuration aborted. + EOT exit 4 } @@ -178,7 +187,7 @@ # Variable initialization. -MY_CONFIG_VERSION=6 +MY_CONFIG_VERSION=7 CONFIG_VERSION= PROGRAM=ircservices @@ -517,6 +526,10 @@ # deprecated GCC < 3.2, so recheck compiler CC= fi + if [ $CONFIG_VERSION -lt 7 ] ; then + # Added -fstack-protector avoidance, so recheck compiler flags + CC= + fi if [ "$USE_DYNAMIC_MODULES" ] ; then STATIC_MODULES= RANLIB= @@ -974,7 +987,34 @@ echo "Compiler flags: (cached) $CC_FLAGS" log cache supplied flags: \`"$CC_FLAGS'" else + CC_FLAGS=$DEF_CC_FLAGS + + # Test for GCC stack-protector patch (generates broken code). + log "check for SSP" + cat >$CONFTMP/test.c <1 ? 24 : 42); return 0; } +EOT + if run $CC $CC_FLAGS -fstack-protector $CONFTMP/test.c -o $CONFTMP/test + then + log "SSP present" + # See if the bug exists; if so, disable stack protection. Test + # twice just in case the bug exists bug the stack happens to + # randomly contain 42. + a=`run $CONFTMP/test` + b=`run $CONFTMP/test x` + if [ "$a" != 42 -o "$b" != 24 ] ; then + CC_FLAGS="$CC_FLAGS -fno-stack-protector" + log "SSP bug found, disabling" + else + log "SSP bug not detected" + fi + else + log "SSP not present" + fi + echo2 "Testing default compiler flags ($CC_FLAGS)... " cat >$CONFTMP/test.c <$CONFTMP/test.c <1?9:42)); return 0; } +EOT + if run $CC $CC_FLAGS $CONFTMP/test.c -o $CONFTMP/test && run $CONFTMP/test + then + a=`run $CONFTMP/test` + b=`run $CONFTMP/test x` + if [ "$a" != "42 2" -o "$b" != "9 1" ] ; then + cat <#13891) -has been filed with the GCC development team, and the OpenBSD developers -are apparently working on importing GCC 3.3.2 into OpenBSD, but until one -or the other is complete, you will need to use either an older version of -OpenBSD or a different operating system to run Services. (It may be -possible to compile Services on an OpenBSD 3.3 or earlier system and use -the resulting executable on OpenBSD 3.4; this has not been tested.) +(#13891 +[gcc.gnu.org]) has been filed with the GCC +development team, and the OpenBSD developers are apparently working on +importing GCC 3.3.2 into OpenBSD, but until one or the other is complete, +you will need to use either an older version of OpenBSD or a different +operating system to run Services. (It may be possible to compile Services +on an OpenBSD 3.3 or earlier system and use the resulting executable on +OpenBSD 3.4; this has not been tested.)

  • A supported IRC server (IRCD). Services supports several different types of IRC servers, as listed in Table 2-1 below. Your IRC @@ -69,11 +70,19 @@ removed completely in a future version. Also note that early versions in the 3.x series were reported to have problems, and should not be used. -

    Warning: GCC version 2.96, provided in some Red Hat and related -Linux distributions, has bugs which cause Services to be compiled +

    Warning: GCC version 2.96, provided in some Red Hat and +related Linux distributions, has bugs which cause Services to be compiled incorrectly (see FAQ B.1 for details). Do not use this compiler to compile Services in any circumstances. +

    Notice: Services will not work with the +SSP (stack-smashing +protector) [www.trl.ibm.com] patch to GCC, +due to a bug in SSP triggered by Services that causes crashes. The +configure script (see below) will automatically detect the +presence of this patch and deactivate the stack-protection feature, or +refuse to compile if it cannot be deactivated. +

  • GNU make [www.gnu.org], version 3.79 or later. Services uses complex Makefiles which may or may not work with diff -uNr ircservices-5.0.29/docs/3.html ircservices-5.0.30/docs/3.html --- ircservices-5.0.29/docs/3.html 2003-05-28 15:31:04 +0900 +++ ircservices-5.0.30/docs/3.html 2004-04-02 12:22:42 +0900 @@ -1578,7 +1578,7 @@ server-based autokill mechanism; such servers will block the user from connecting without informing Services, so the last-used time will show only the first time a matching user connected. (If the -ImmediatelySendAutokill + option in modules.conf is enabled, the last-used time will never be set at all on these servers.) @@ -1595,7 +1595,12 @@ option in modules.conf. The autokill exclusion list is managed with the EXCLUDE command, which functions in much the same way as the AKILL command described -above. +above. (However, newly-added exclusions are always sent immediately to the +server regardless of the state of the +ImmediatelySendAutokill +setting; this is to avoid an autokill being triggered by a non-excluded +match before the exclusion has been sent, resulting in the excluded users +being autokilled as well.)

    When autokill exclusions are in use, Services will first check the exclusion list for each user connecting to the network. If a matching mask diff -uNr ircservices-5.0.29/docs/4.html ircservices-5.0.30/docs/4.html --- ircservices-5.0.29/docs/4.html 2003-11-17 16:39:09 +0900 +++ ircservices-5.0.30/docs/4.html 2004-04-02 12:19:41 +0900 @@ -2619,7 +2619,10 @@

    The ADD, DEL, LIST, VIEW, and COUNT subcommands function the same way as the subcommands for the AKILL command; see -the AKILL help for more information. +the AKILL help for more information. (Note that autokill +exclusions are not affected by the state of the +ImmediatelySendAutokill +setting, and are always immediately sent to the server.)

    Limited to Services operators. diff -uNr ircservices-5.0.29/docs/a.html ircservices-5.0.30/docs/a.html --- ircservices-5.0.29/docs/a.html 2004-03-24 19:19:26 +0900 +++ ircservices-5.0.30/docs/a.html 2004-04-09 17:51:16 +0900 @@ -934,9 +934,12 @@

    • ImmediatelySendAutokill    [OPTIONAL] -

      Causes OperServ to inform all servers of a new autokill or -autokill exclusion the moment it is added, rather than waiting -for someone to match it first. +

      Causes OperServ to inform all servers of a new autokill the +moment it is added, rather than waiting for someone to match it +first. (Note that autokill exclusions are always sent to the +server immediately; this is to avoid an autokill being triggered +by a non-excluded match before the exclusion has been sent, +resulting in the excluded users being autokilled as well.)

      Example: ImmediatelySendAutokill

    diff -uNr ircservices-5.0.29/modes.c ircservices-5.0.30/modes.c --- ircservices-5.0.29/modes.c 2004-03-24 19:23:25 +0900 +++ ircservices-5.0.30/modes.c 2004-04-14 11:33:35 +0900 @@ -130,7 +130,8 @@ /* Return the flag corresponding to the given mode character, or 0 if no * such mode exists. Return MODE_INVALID if the mode exists but has no - * assigned flag. + * assigned flag. `which' indicates the mode set to be used: MODE_USER, + * MODE_CHANNEL, or MODE_CHANUSER. */ int32 mode_char_to_flag(char c, int which) @@ -153,7 +154,8 @@ /*************************************************************************/ /* Return the mode character corresponding to the given flag, or 0 if no - * such mode exists. + * such mode exists. If more than one bit is set in `f', then the mode + * character corresponding to the highest bit is used. */ char mode_flag_to_char(int32 f, int which) @@ -170,10 +172,10 @@ /*************************************************************************/ -/* Return the flag set corresponding to the given string of mode - * characters. If MODE_NOERROR is set in `which', invalid mode characters - * are ignored; if not set, (CMODE_INVALID | modechar) is returned for the - * first invalid mode character found. +/* Return the flag set corresponding to the given string of mode characters + * in the given mode set. If MODE_NOERROR is set in `which', invalid mode + * characters are ignored; if not set, (CMODE_INVALID | modechar) is + * returned for the first invalid mode character found. */ int32 mode_string_to_flags(const char *s, int which) diff -uNr ircservices-5.0.29/modules/chanserv/chanserv.h ircservices-5.0.30/modules/chanserv/chanserv.h --- ircservices-5.0.29/modules/chanserv/chanserv.h 2004-03-24 19:23:26 +0900 +++ ircservices-5.0.30/modules/chanserv/chanserv.h 2004-04-14 11:33:35 +0900 @@ -150,12 +150,12 @@ #define CA_SET 2 /* but not FOUNDER or PASSWORD */ #define CA_UNBAN 3 #define CA_AUTOOP 4 -#define CA_AUTODEOP 5 /* Maximum, not minimum */ +#define CA_AUTODEOP 5 /* Maximum, not minimum; internal use only*/ #define CA_AUTOVOICE 6 #define CA_OPDEOP 7 /* ChanServ commands OP and DEOP */ #define CA_ACCESS_LIST 8 #define CA_CLEAR 9 -#define CA_NOJOIN 10 /* Maximum */ +#define CA_NOJOIN 10 /* Maximum; internal use only */ #define CA_ACCESS_CHANGE 11 #define CA_MEMO 12 #define CA_VOICE 13 /* VOICE/DEVOICE commands */ @@ -163,7 +163,7 @@ #define CA_HALFOP 15 /* HALFOP/DEHALFOP commands */ #define CA_AUTOPROTECT 16 #define CA_PROTECT 17 -#define CA_AUTOOWNER 18 /* dummy entry for auto +q */ +#define CA_AUTOOWNER 18 /* Dummy entry for auto +q */ #define CA_KICK 19 #define CA_STATUS 20 #define CA_TOPIC 21 diff -uNr ircservices-5.0.29/modules/chanserv/main.c ircservices-5.0.30/modules/chanserv/main.c --- ircservices-5.0.29/modules/chanserv/main.c 2004-03-24 19:23:26 +0900 +++ ircservices-5.0.30/modules/chanserv/main.c 2004-04-14 11:33:35 +0900 @@ -866,7 +866,7 @@ } else { /* Only show all the channel's settings to sadmins and founders. */ - can_show_all = (is_identified(u, ci) || is_servadmin); + can_show_all = (is_founder(u, ci) || is_servadmin); if ((param && stricmp(param, "ALL") == 0) && can_show_all) show_all = 1; @@ -1079,7 +1079,6 @@ int add, target_acc, success_msg, failure_msg, already_msg; int target_nextacc; /* Target level upper bound for DEVOICE, DEHALFOP */ int32 mode; - char modechar; ARRAY2_SEARCH(opvoice_data, lenof(opvoice_data), cmd, cmd, strcmp, i); if (i >= lenof(opvoice_data)) { @@ -1088,8 +1087,7 @@ return; } add = opvoice_data[i].add; - modechar = opvoice_data[i].mode; - mode = mode_char_to_flag(modechar, MODE_CHANUSER); + mode = mode_char_to_flag(opvoice_data[i].mode, MODE_CHANUSER); target_acc = opvoice_data[i].target_acc; success_msg = opvoice_data[i].success_msg; already_msg = opvoice_data[i].already_msg; @@ -1101,6 +1099,9 @@ target_nextacc = CA_AUTOOP; else target_nextacc = -1; + /* Special case for DEPROTECT: also remove channel-owner mode, if any */ + if (strcmp(cmd, "DEPROTECT") == 0 && chanusermode_owner) + mode |= chanusermode_owner; if (target) { target_user = get_user(target); @@ -1134,26 +1135,40 @@ } else { struct c_userlist *cu; char modebuf[3]; + int32 umode, thismode; /* Retrieve c_userlist entry and see (1) if they're even on the - * channel and (2) if they already have the mode */ + * channel and (2) if they already have / don't have the mode */ LIST_SEARCH_SCALAR(c->users, user, target_user, cu); if (!cu) { notice_lang(s_ChanServ, u, NICK_X_NOT_ON_CHAN_X, target, chan); return; } - if (add ? (cu->mode & mode) : !(cu->mode & mode)) { - /* Target user already has (or doesn't have, if !add) mode, so - * don't do anything */ + umode = cu->mode & mode; + if (add) + umode ^= mode; /* make note of which ones they DON'T have */ + if (!umode) { + /* Target user already has (or doesn't have, if !add) mode(s), + * so don't do anything */ notice_lang(s_ChanServ, u, already_msg, target, chan); return; } - /* Set appropriate mode */ + /* Set appropriate mode(s) */ modebuf[0] = add ? '+' : '-'; - modebuf[1] = modechar; modebuf[2] = 0; - set_cmode(s_ChanServ, c, modebuf, target); + thismode = 1; + while (umode) { + while (!(umode & thismode)) + thismode <<= 1; + if (!thismode) { /* impossible */ + module_log("BUG: thismode==0 in opvoice!"); + break; + } + modebuf[1] = mode_flag_to_char(thismode, MODE_CHANUSER); + set_cmode(s_ChanServ, c, modebuf, target); + umode &= ~thismode; + } set_cmode(NULL, c); /* Flush mode change out */ if (ci->flags & CI_OPNOTICE) { notice(s_ChanServ, chan, "%s command used for %s by %s", diff -uNr ircservices-5.0.29/modules/chanserv/set.c ircservices-5.0.30/modules/chanserv/set.c --- ircservices-5.0.29/modules/chanserv/set.c 2004-03-24 19:23:26 +0900 +++ ircservices-5.0.30/modules/chanserv/set.c 2004-04-14 11:33:35 +0900 @@ -540,23 +540,9 @@ { if (stricmp(param, "ON") == 0) { ci->flags |= co->flag; - /* Only set CA_NOJOIN if the levels have already been changed from - * the default; otherwise check_access() will take care of it */ - if (co->flag == CI_RESTRICTED - && ci->levels - && ci->levels[CA_NOJOIN] < 0 - ) { - ci->levels[CA_NOJOIN] = 0; - } notice_lang(s_ChanServ, u, co->onstr, ci->name); } else if (stricmp(param, "OFF") == 0) { ci->flags &= ~co->flag; - if (co->flag == CI_RESTRICTED - && ci->levels - && ci->levels[CA_NOJOIN] >= 0 - ) { - ci->levels[CA_NOJOIN] = -100; - } notice_lang(s_ChanServ, u, co->offstr, ci->name); } else { char buf[BUFSIZE]; diff -uNr ircservices-5.0.29/modules/database/version4.c ircservices-5.0.30/modules/database/version4.c --- ircservices-5.0.29/modules/database/version4.c 2004-03-24 19:23:26 +0900 +++ ircservices-5.0.30/modules/database/version4.c 2004-04-14 11:33:36 +0900 @@ -51,9 +51,10 @@ /*************************************************************************/ #define FILE_VERSION 11 /* Must remain constant */ -#define LOCAL_VERSION 25 /* For extensions to database files */ +#define LOCAL_VERSION 26 /* For extensions to database files */ /* LOCAL_VERSION change history: + * 26: Forced AUTODEOP and NOJOIN to default values * 25: Added trircd +J handling (ci->mlock_joindelay field) * 24: Moved nickname authentication reason into its own field (no * longer stored as part of authentication code) @@ -1219,6 +1220,17 @@ } need_memomax_check = 0; } + if (ver < 26) { + /* Reset all AUTODEOP/NOJOIN levels to the defaults (version 4.x + * databases may have them set to non-default levels, and version 5 + * doesn't allow them to be changed) */ + for (ci = first_channelinfo(); ci; ci = next_channelinfo()) { + if (ci->levels) { + ci->levels[CA_AUTODEOP] = -1; + ci->levels[CA_NOJOIN] = -100; + } + } + } /* Add the memomax check callback if needed. */ if (need_memomax_check) diff -uNr ircservices-5.0.29/modules/nickserv/main.c ircservices-5.0.30/modules/nickserv/main.c --- ircservices-5.0.29/modules/nickserv/main.c 2004-03-24 19:23:26 +0900 +++ ircservices-5.0.30/modules/nickserv/main.c 2004-04-14 11:33:36 +0900 @@ -556,7 +556,6 @@ memcpy(ngi->pass, passbuf, PASSMAX); memset(passbuf, 0, PASSMAX); ni->time_registered = ni->last_seen = time(NULL); - ni->id_stamp = u->servicestamp; ni->authstat = NA_IDENTIFIED | NA_RECOGNIZED; if (email) ngi->email = sstrdup(email); @@ -566,6 +565,10 @@ ngi->language = LANG_DEFAULT; ngi->timezone = TIMEZONE_DEFAULT; call_callback_4(module, cb_registered, u, ni, ngi, &replied); + /* If the IDENTIFIED flag is still set (a module might have + * cleared it, e.g. mail-auth), record the ID stamp */ + if (nick_identified(ni)) + ni->id_stamp = u->servicestamp; /* Link back and forth to user record and store modified data */ u->ni = ni; u->ngi = ngi; @@ -589,9 +592,9 @@ memset(pass, 0, len); /* Note time REGISTER command was used */ u->lastnickreg = time(NULL); - /* Set +r (or other registered-nick mode) */ + /* Set +r (or other registered-nick mode) if IDENTIFIED is still + * set. */ if (nick_identified(ni) && usermode_reg) { - /* Re-check IDENTIFIED because a module might have cleared it */ send_cmd(s_NickServ, "SVSMODE %s :+%s", u->nick, mode_flags_to_string(usermode_reg, MODE_USER)); } @@ -994,20 +997,27 @@ NickInfo *ni = u->ni; NickGroupInfo *ngi; - if (is_services_admin(u)) { + if (is_oper(u)) { char *nick = strtok(NULL, " "); if (nick) { - ni = get_nickinfo(nick); - if (!ni) { + NickInfo *ni2 = get_nickinfo(nick); + if (ni2 == ni) { + /* Let the command through even for non-servadmins if they + * gave their own nick; it's less confusing than a + * "Permission denied" error */ + } else if (!is_services_admin(u)) { + notice_lang(s_NickServ, u, PERMISSION_DENIED); + return; + } else if (!ni2) { notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); return; + } else { + ni = ni2; } } } else if (strtok_remaining()) { - if (is_oper(u)) - notice_lang(s_NickServ, u, PERMISSION_DENIED); - else - syntax_error(s_NickServ, u, "LISTCHANS", NICK_LISTCHANS_SYNTAX); + syntax_error(s_NickServ, u, "LISTCHANS", NICK_LISTCHANS_SYNTAX); + return; } if (!ni) { notice_lang(s_NickServ, u, NICK_NOT_REGISTERED); diff -uNr ircservices-5.0.29/modules/nickserv/util.c ircservices-5.0.30/modules/nickserv/util.c --- ircservices-5.0.29/modules/nickserv/util.c 2004-03-24 19:23:26 +0900 +++ ircservices-5.0.30/modules/nickserv/util.c 2004-04-14 11:33:36 +0900 @@ -305,7 +305,8 @@ /*************************************************************************/ /* Update the last_usermask, last_realmask, and last_realname nick fields - * from the given user's data. Assumes u->ni is non-NULL. + * from the given user's data, and sets last_seen to the current time. + * Assumes u->ni is non-NULL. */ void update_userinfo(User *u) @@ -384,52 +385,58 @@ return 0; } - if (has_identified_nick(u, ngi->id)) { - set_identified(u, ni, ngi); - return 1; - } - - if (!NoSplitRecovery) { - /* - * This can be exploited to gain improper privilege if an attacker - * has the same Services stamp, username and hostname as the - * victim. - * - * Under ircd.dal 4.4.15+ (Dreamforge) and other servers supporting - * a Services stamp, Services guarantees that the first condition - * cannot occur unless the stamp counter rolls over (2^31-1 client - * connections). This is practically infeasible given present - * technology. As an example, on a network of 30 servers, an - * attack introducing 50 new clients every second on every server, - * requiring at least 10-15 megabits of bandwidth, would need to be - * sustained for over 16 days to cause the stamp to roll over. - * - * Under other servers, an attack is theoretically possible, but - * would require access to either the computer the victim is using - * for IRC or the DNS servers for the victim's domain and IP - * address range in order to have the same hostname, and would - * require that the attacker connect so that he has the same server - * timestamp as the victim. Practically, the former can be - * accomplished either by finding a victim who uses a shell account - * on a multiuser system and obtaining an account on the same - * system, or through the scripting capabilities of many IRC - * clients combined with social engineering; the latter could be - * accomplished by finding a server with a clock slower than that - * of the victim's server and timing the connection attempt - * properly. - * - * If someone gets a hacked server into your network, all bets are - * off. - */ - if (ni->id_stamp != 0 && u->servicestamp == ni->id_stamp) { - char buf[BUFSIZE]; - snprintf(buf, sizeof(buf), "%s@%s", u->username, u->host); - if (ni->last_realmask && strcmp(buf, ni->last_realmask) == 0) { - set_identified(u, ni, ngi); - return 1; + if (!ngi->authcode) { + /* Neither of these checks should be done if the nick is awaiting + * authentication */ + + if (has_identified_nick(u, ngi->id)) { + set_identified(u, ni, ngi); + return 1; + } + + if (!NoSplitRecovery) { + /* + * This can be exploited to gain improper privilege if an attacker + * has the same Services stamp, username and hostname as the + * victim. + * + * Under ircd.dal 4.4.15+ (Dreamforge) and other servers supporting + * a Services stamp, Services guarantees that the first condition + * cannot occur unless the stamp counter rolls over (2^31-1 client + * connections). This is practically infeasible given present + * technology. As an example, on a network of 30 servers, an + * attack introducing 50 new clients every second on every server, + * requiring at least 10-15 megabits of bandwidth, would need to be + * sustained for over 16 days to cause the stamp to roll over. + * + * Under other servers, an attack is theoretically possible, but + * would require access to either the computer the victim is using + * for IRC or the DNS servers for the victim's domain and IP + * address range in order to have the same hostname, and would + * require that the attacker connect so that he has the same server + * timestamp as the victim. Practically, the former can be + * accomplished either by finding a victim who uses a shell account + * on a multiuser system and obtaining an account on the same + * system, or through the scripting capabilities of many IRC + * clients combined with social engineering; the latter could be + * accomplished by finding a server with a clock slower than that + * of the victim's server and timing the connection attempt + * properly. + * + * If someone gets a hacked server into your network, all bets are + * off. + */ + if (ni->id_stamp != 0 && u->servicestamp == ni->id_stamp) { + char buf[BUFSIZE]; + snprintf(buf, sizeof(buf), "%s@%s", u->username, u->host); + if (ni->last_realmask && strcmp(buf, ni->last_realmask) == 0) { + set_identified(u, ni, ngi); + return 1; + } } } - } + + } /* if (!ngi->authcode) */ is_recognized = (call_callback_1(module, cb_check_recognized, u) == 1); @@ -518,7 +525,6 @@ ni->authstat &= ~NA_IDENT_NOMAIL; ni->authstat |= NA_IDENTIFIED; ni->id_stamp = u->servicestamp; - ni->last_seen = time(NULL); if (!nick_recognized(ni)) { update_userinfo(u); ni->authstat |= NA_RECOGNIZED; diff -uNr ircservices-5.0.29/modules/operserv/akill.c ircservices-5.0.30/modules/operserv/akill.c --- ircservices-5.0.29/modules/operserv/akill.c 2004-03-24 19:23:26 +0900 +++ ircservices-5.0.30/modules/operserv/akill.c 2004-04-14 11:33:36 +0900 @@ -517,8 +517,7 @@ wallops(s_OperServ, "%s added an EXCLUDE for \2%s\2 (%s)", u->nick, md->mask, buf); } - if (ImmediatelySendAutokill) - send_exclude(md); + send_exclude(md); } /*************************************************************************/ diff -uNr ircservices-5.0.29/modules/protocol/unreal.c ircservices-5.0.30/modules/protocol/unreal.c --- ircservices-5.0.29/modules/protocol/unreal.c 2004-03-24 19:23:26 +0900 +++ ircservices-5.0.30/modules/protocol/unreal.c 2004-04-14 11:33:36 +0900 @@ -502,10 +502,14 @@ * longer "valid" from Services' perspective. Any TKLs that really are * valid will be re-added as soon as a user matches them. * - * As a special case, when we receive a TKL - Z, we first check whether + * As a special case, when we receive a TKL + Z, we first check whether * such a TKL exists in the SZline list, and do not remove it if it's * found; Unreal does not report IP address information for users, so * we have no way to re-add the masks by checking connecting users. + * + * FIXME: Unreal 3.2 converts an SQLINE into a TKL and sends it back to + * us! Previous Unreal releases don't understand TKL Q, so for now + * check these against the SQline list. */ /* Pointer to the `get_maskdata' function defined in the database @@ -521,6 +525,8 @@ return; if (*av[1] == 'Z' && (*p_get_maskdata)(MD_SZLINE, av[3])) return; + if (*av[1] == 'Q' && (*p_get_maskdata)(MD_SQLINE, av[3])) + return; send_cmd(ServerName, "TKL - %c %s %s %s", *av[1], av[2], av[3], ServerName); } @@ -889,10 +895,6 @@ } else { /* Successfully parsed */ unreal_version = ver; - /* Unreal 3.2 (protocol version 2303) and above support - * autokill exclusions, so make a note of that */ - if (ver >= 2303) - protocol_features |= PF_AKILL_EXCL; } } return 0; diff -uNr ircservices-5.0.29/version.sh ircservices-5.0.30/version.sh --- ircservices-5.0.29/version.sh 2004-03-24 19:14:06 +0900 +++ ircservices-5.0.30/version.sh 2004-04-14 11:25:34 +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.29 +VERSION=5.0.30 # Increment Services build number if [ -f version.c ] ; then