X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fircd_relay.c;h=b7a751d7cc4a9446100f904c7c7dd2424867fae3;hb=refs%2Fheads%2Fupstream;hp=32f2df0a61e9758aa2f3c3b3e43b85e01256b51c;hpb=32bebbce4d986728924a2bf4650c6cfd30ac6710;p=ircu2.10.12-pk.git diff --git a/ircd/ircd_relay.c b/ircd/ircd_relay.c index 32f2df0..b7a751d 100644 --- a/ircd/ircd_relay.c +++ b/ircd/ircd_relay.c @@ -19,8 +19,29 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/** @file + * @brief Helper functions to relay various types of messages. + * @version $Id$ + * + * There are four basic types of messages, each with four subtypes. + * + * The basic types are: channel, directed, masked, and private. + * Channel messages are (perhaps obviously) sent directly to a + * channel. Directed messages are sent to "NICK[%host]@server", but + * only allowed if the server is a services server (to avoid + * information leaks for normal clients). Masked messages are sent to + * either *@*host.mask or *.server.mask. Private messages are sent to + * NICK. + * + * The subtypes for each type are: client message, client notice, + * server message, and server notice. Client subtypes are sent by a + * local user, and server subtypes are given to us by a server. + * Notice subtypes correspond to the NOTICE command, and message + * subtypes correspond to the PRIVMSG command. * - * $Id$ + * As a special note, directed messages do not have server subtypes, + * since there is no difference in handling them based on origin. */ #include "config.h" @@ -30,6 +51,8 @@ #include "hash.h" #include "ircd.h" #include "ircd_chattr.h" +#include "ircd_features.h" +#include "ircd_log.h" #include "ircd_reply.h" #include "ircd_string.h" #include "match.h" @@ -41,7 +64,7 @@ #include "s_user.h" #include "send.h" -#include +/* #include -- Now using assert in ircd_log.h */ #include #include #include @@ -53,6 +76,13 @@ * to be cleaned up a bit. The idea is to factor out the common checks * but not introduce any IsOper/IsUser/MyUser/IsServer etc. stuff. */ + +/** Relay a local user's message to a channel. + * Generates an error if the client cannot send to the channel. + * @param[in] sptr Client that originated the message. + * @param[in] name Name of target channel. + * @param[in] text %Message to relay. + */ void relay_channel_message(struct Client* sptr, const char* name, const char* text) { struct Channel* chptr; @@ -67,7 +97,7 @@ void relay_channel_message(struct Client* sptr, const char* name, const char* te /* * This first: Almost never a server/service */ - if (!client_can_send_to_channel(sptr, chptr)) { + if (!client_can_send_to_channel(sptr, chptr, 0)) { send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname); return; } @@ -75,10 +105,17 @@ void relay_channel_message(struct Client* sptr, const char* name, const char* te check_target_limit(sptr, chptr, chptr->chname, 0)) return; + RevealDelayedJoinIfNeeded(sptr, chptr); sendcmdto_channel_butone(sptr, CMD_PRIVATE, chptr, cli_from(sptr), SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text); } +/** Relay a local user's notice to a channel. + * Silently exits if the client cannot send to the channel. + * @param[in] sptr Client that originated the message. + * @param[in] name Name of target channel. + * @param[in] text %Message to relay. + */ void relay_channel_notice(struct Client* sptr, const char* name, const char* text) { struct Channel* chptr; @@ -91,17 +128,25 @@ void relay_channel_notice(struct Client* sptr, const char* name, const char* tex /* * This first: Almost never a server/service */ - if (!client_can_send_to_channel(sptr, chptr)) + if (!client_can_send_to_channel(sptr, chptr, 0)) return; if ((chptr->mode.mode & MODE_NOPRIVMSGS) && check_target_limit(sptr, chptr, chptr->chname, 0)) - return; + return; + RevealDelayedJoinIfNeeded(sptr, chptr); sendcmdto_channel_butone(sptr, CMD_NOTICE, chptr, cli_from(sptr), SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text); } +/** Relay a message to a channel. + * Generates an error if the client cannot send to the channel, + * or if the channel is a local channel + * @param[in] sptr Client that originated the message. + * @param[in] name Name of target channel. + * @param[in] text %Message to relay. + */ void server_relay_channel_message(struct Client* sptr, const char* name, const char* text) { struct Channel* chptr; @@ -109,10 +154,7 @@ void server_relay_channel_message(struct Client* sptr, const char* name, const c assert(0 != name); assert(0 != text); - if (0 == (chptr = FindChannel(name))) { - /* - * XXX - do we need to send this back from a remote server? - */ + if (IsLocalChannel(name) || 0 == (chptr = FindChannel(name))) { send_reply(sptr, ERR_NOSUCHCHANNEL, name); return; } @@ -120,7 +162,7 @@ void server_relay_channel_message(struct Client* sptr, const char* name, const c * This first: Almost never a server/service * Servers may have channel services, need to check for it here */ - if (client_can_send_to_channel(sptr, chptr) || IsChannelService(sptr)) { + if (client_can_send_to_channel(sptr, chptr, 1) || IsChannelService(sptr)) { sendcmdto_channel_butone(sptr, CMD_PRIVATE, chptr, cli_from(sptr), SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text); } @@ -128,6 +170,13 @@ void server_relay_channel_message(struct Client* sptr, const char* name, const c send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname); } +/** Relay a notice to a channel. + * Generates an error if the client cannot send to the channel, + * or if the channel is a local channel + * @param[in] sptr Client that originated the message. + * @param[in] name Name of target channel. + * @param[in] text %Message to relay. + */ void server_relay_channel_notice(struct Client* sptr, const char* name, const char* text) { struct Channel* chptr; @@ -135,19 +184,27 @@ void server_relay_channel_notice(struct Client* sptr, const char* name, const ch assert(0 != name); assert(0 != text); - if (0 == (chptr = FindChannel(name))) + if (IsLocalChannel(name) || 0 == (chptr = FindChannel(name))) return; /* * This first: Almost never a server/service * Servers may have channel services, need to check for it here */ - if (client_can_send_to_channel(sptr, chptr) || IsChannelService(sptr)) { + if (client_can_send_to_channel(sptr, chptr, 1) || IsChannelService(sptr)) { sendcmdto_channel_butone(sptr, CMD_NOTICE, chptr, cli_from(sptr), SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text); } } - +/** Relay a directed message. + * Generates an error if the named server does not exist, if it is not + * a services server, or if \a name names a local user and a hostmask + * is specified but does not match. + * @param[in] sptr Client that originated the message. + * @param[in] name Target nickname, with optional "%hostname" suffix. + * @param[in] server Name of target server. + * @param[in] text %Message to relay. + */ void relay_directed_message(struct Client* sptr, char* name, char* server, const char* text) { struct Client* acptr; @@ -158,14 +215,16 @@ void relay_directed_message(struct Client* sptr, char* name, char* server, const assert(0 != text); assert(0 != server); - if (0 == (acptr = FindServer(server + 1))) { + if ((acptr = FindServer(server + 1)) == NULL || !IsService(acptr)) + { send_reply(sptr, ERR_NOSUCHNICK, name); return; } /* * NICK[%host]@server addressed? See if is me first */ - if (!IsMe(acptr)) { + if (!IsMe(acptr)) + { sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%s :%s", name, text); return; } @@ -178,8 +237,23 @@ void relay_directed_message(struct Client* sptr, char* name, char* server, const if ((host = strchr(name, '%'))) *host++ = '\0'; + /* As reported by Vampire-, it's possible to brute force finding users + * by sending a message to each server and see which one succeeded. + * This means we have to remove error reporting. Sigh. Better than + * removing the ability to send directed messages to client servers + * Thanks for the suggestion Vampire=. -- Isomer 2001-08-28 + * Argh, /ping nick@server, disallow messages to non +k clients :/ I hate + * this. -- Isomer 2001-09-16 + */ if (!(acptr = FindUser(name)) || !MyUser(acptr) || - (!EmptyString(host) && 0 != match(host, cli_user(acptr)->host))) { + (!EmptyString(host) && 0 != match(host, cli_user(acptr)->host)) || + !IsChannelService(acptr)) + { + /* + * By this stage we might as well not bother because they will + * know that this server is currently linked because of the + * increased lag. + */ send_reply(sptr, ERR_NOSUCHNICK, name); return; } @@ -192,6 +266,15 @@ void relay_directed_message(struct Client* sptr, char* name, char* server, const sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%s :%s", name, text); } +/** Relay a directed notice. + * Generates an error if the named server does not exist, if it is not + * a services server, or if \a name names a local user and a hostmask + * is specified but does not match. + * @param[in] sptr Client that originated the message. + * @param[in] name Target nickname, with optional "%hostname" suffix. + * @param[in] server Name of target server. + * @param[in] text %Message to relay. + */ void relay_directed_notice(struct Client* sptr, char* name, char* server, const char* text) { struct Client* acptr; @@ -232,6 +315,14 @@ void relay_directed_notice(struct Client* sptr, char* name, char* server, const sendcmdto_one(sptr, CMD_NOTICE, acptr, "%s :%s", name, text); } +/** Relay a private message from a local user. + * Returns an error if the user does not exist or sending to him would + * exceed the source's free targets. Sends an AWAY status message if + * the target is marked as away. + * @param[in] sptr Client that originated the message. + * @param[in] name Nickname of target user. + * @param[in] text %Message to relay. + */ void relay_private_message(struct Client* sptr, const char* name, const char* text) { struct Client* acptr; @@ -244,8 +335,8 @@ void relay_private_message(struct Client* sptr, const char* name, const char* te send_reply(sptr, ERR_NOSUCHNICK, name); return; } - if (!IsChannelService(acptr) && - check_target_limit(sptr, acptr, cli_name(acptr), 0) || + if ((!IsChannelService(acptr) && + check_target_limit(sptr, acptr, cli_name(acptr), 0)) || is_silenced(sptr, acptr)) return; @@ -263,6 +354,14 @@ void relay_private_message(struct Client* sptr, const char* name, const char* te sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%C :%s", acptr, text); } +/** Relay a private notice from a local user. + * Returns an error if the user does not exist or sending to him would + * exceed the source's free targets. Sends an AWAY status message if + * the target is marked as away. + * @param[in] sptr Client that originated the message. + * @param[in] name Nickname of target user. + * @param[in] text %Message to relay. + */ void relay_private_notice(struct Client* sptr, const char* name, const char* text) { struct Client* acptr; @@ -272,8 +371,8 @@ void relay_private_notice(struct Client* sptr, const char* name, const char* tex if (0 == (acptr = FindUser(name))) return; - if (!IsChannelService(acptr) && - check_target_limit(sptr, acptr, cli_name(acptr), 0) || + if ((!IsChannelService(acptr) && + check_target_limit(sptr, acptr, cli_name(acptr), 0)) || is_silenced(sptr, acptr)) return; /* @@ -285,6 +384,12 @@ void relay_private_notice(struct Client* sptr, const char* name, const char* tex sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text); } +/** Relay a private message that arrived from a server. + * Returns an error if the user does not exist. + * @param[in] sptr Client that originated the message. + * @param[in] name Nickname of target user. + * @param[in] text %Message to relay. + */ void server_relay_private_message(struct Client* sptr, const char* name, const char* text) { struct Client* acptr; @@ -295,8 +400,9 @@ void server_relay_private_message(struct Client* sptr, const char* name, const c * nickname addressed? */ if (0 == (acptr = findNUser(name)) || !IsUser(acptr)) { - send_reply(sptr, SND_EXPLICIT | ERR_NOSUCHNICK, "* :Target left UnderNet. " - "Failed to deliver: [%.20s]", text); + send_reply(sptr, SND_EXPLICIT | ERR_NOSUCHNICK, "* :Target left %s. " + "Failed to deliver: [%.20s]", feature_str(FEAT_NETWORK), + text); return; } if (is_silenced(sptr, acptr)) @@ -309,6 +415,12 @@ void server_relay_private_message(struct Client* sptr, const char* name, const c } +/** Relay a private notice that arrived from a server. + * Returns an error if the user does not exist. + * @param[in] sptr Client that originated the message. + * @param[in] name Nickname of target user. + * @param[in] text %Message to relay. + */ void server_relay_private_notice(struct Client* sptr, const char* name, const char* text) { struct Client* acptr; @@ -330,6 +442,13 @@ void server_relay_private_notice(struct Client* sptr, const char* name, const ch sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text); } +/** Relay a masked message from a local user. + * Sends an error response if there is no top-level domain label in \a + * mask, or if that TLD contains a wildcard. + * @param[in] sptr Client that originated the message. + * @param[in] mask Target mask for the message. + * @param[in] text %Message to relay. + */ void relay_masked_message(struct Client* sptr, const char* mask, const char* text) { const char* s; @@ -365,6 +484,13 @@ void relay_masked_message(struct Client* sptr, const char* mask, const char* tex "%s :%s", mask, text); } +/** Relay a masked notice from a local user. + * Sends an error response if there is no top-level domain label in \a + * mask, or if that TLD contains a wildcard. + * @param[in] sptr Client that originated the message. + * @param[in] mask Target mask for the message. + * @param[in] text %Message to relay. + */ void relay_masked_notice(struct Client* sptr, const char* mask, const char* text) { const char* s; @@ -400,6 +526,11 @@ void relay_masked_notice(struct Client* sptr, const char* mask, const char* text "%s :%s", mask, text); } +/** Relay a masked message that arrived from a server. + * @param[in] sptr Client that originated the message. + * @param[in] mask Target mask for the message. + * @param[in] text %Message to relay. + */ void server_relay_masked_message(struct Client* sptr, const char* mask, const char* text) { const char* s = mask; @@ -418,6 +549,11 @@ void server_relay_masked_message(struct Client* sptr, const char* mask, const ch "%s :%s", mask, text); } +/** Relay a masked notice that arrived from a server. + * @param[in] sptr Client that originated the message. + * @param[in] mask Target mask for the message. + * @param[in] text %Message to relay. + */ void server_relay_masked_notice(struct Client* sptr, const char* mask, const char* text) { const char* s = mask;