commit eb9929e82c735100a0b432f878f83fce091eb636 from: Alexander Barton date: Thu Sep 03 14:22:36 2015 UTC Make server-to-server protocol more robust Now ngIRCd catches more errors on the server-to-server (S2S) protocol that could crash the daemon before. This hasn't been a real problem because the IRC S2S protocol is "trusted" by design, but the behavior is much better now. Thanks to wowaname on #ngircd for pointing this out! commit - c2e4c304e3adde2217056c2e6d674fd24e0cd800 commit + eb9929e82c735100a0b432f878f83fce091eb636 blob - 9fca622ba0ea66422940e2d71dc2dff0d5f2eee4 blob + a7955b14ae3b566b832b4879f445deb2dce21c38 --- src/ngircd/irc-login.c +++ src/ngircd/irc-login.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors. + * Copyright (c)2001-2015 Alexander Barton (alex@barton.de) and Contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -196,6 +196,7 @@ IRC_NICK( CLIENT *Client, REQUEST *Req ) /* Search "target" client */ if (Client_Type(Client) == CLIENT_SERVER) { + _IRC_REQUIRE_PREFIX_OR_RETURN_(Client, Req) target = Client_Search(Req->prefix); if (!target) return IRC_WriteErrClient(Client, @@ -378,6 +379,8 @@ IRC_SVSNICK(CLIENT *Client, REQUEST *Req) assert(Client != NULL); assert(Req != NULL); + + _IRC_REQUIRE_PREFIX_OR_RETURN_(Client, Req) /* Search the originator */ from = Client_Search(Req->prefix); @@ -481,6 +484,7 @@ IRC_USER(CLIENT * Client, REQUEST * Req) Client_Type(Client) == CLIENT_SERVICE) { /* Server/service updating an user */ _IRC_ARGC_EQ_OR_RETURN_(Client, Req, 4) + _IRC_REQUIRE_PREFIX_OR_RETURN_(Client, Req) c = Client_Search(Req->prefix); if (!c) @@ -653,6 +657,8 @@ IRC_QUIT( CLIENT *Client, REQUEST *Req ) if (Client_Type(Client) == CLIENT_SERVER) { /* Server */ + _IRC_REQUIRE_PREFIX_OR_RETURN_(Client, Req) + target = Client_Search(Req->prefix); if (!target) { Log(LOG_WARNING, @@ -741,9 +747,10 @@ IRC_PING(CLIENT *Client, REQUEST *Req) if (target != Client_ThisServer()) { /* Ok, we have to forward the PING */ - if (Client_Type(Client) == CLIENT_SERVER) + if (Client_Type(Client) == CLIENT_SERVER) { + _IRC_REQUIRE_PREFIX_OR_RETURN_(Client, Req) from = Client_Search(Req->prefix); - else + } else from = Client; if (!from) return IRC_WriteErrClient(Client, @@ -815,6 +822,8 @@ IRC_PONG(CLIENT *Client, REQUEST *Req) /* Forward? */ if (Req->argc == 2 && Client_Type(Client) == CLIENT_SERVER) { + _IRC_REQUIRE_PREFIX_OR_RETURN_(Client, Req) + target = Client_Search(Req->argv[0]); if (!target) return IRC_WriteErrClient(Client, ERR_NOSUCHSERVER_MSG, blob - dc18641d072f47b6220ecc08cca3d838240476ed blob + 2abb1614a8effc367bc7216bfcd34b7faece03cc --- src/ngircd/irc-macros.h +++ src/ngircd/irc-macros.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. + * Copyright (c)2001-2015 Alexander Barton (alex@barton.de) and Contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -66,6 +66,18 @@ if (Req->argc < Min || Req->argc > Max) { \ } /** + * Make sure that the command has a prefix. + * + * If there is no prefix, send an error to the client and return from + * the function. + */ +#define _IRC_REQUIRE_PREFIX_OR_RETURN_(Client, Req) \ +if (!Req->prefix) { \ + return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG, \ + Client_ID(Client), Req->command); \ +} + +/** * Get sender of an IRC command. * * The sender is either stored in the prefix if the command has been @@ -73,13 +85,17 @@ if (Req->argc < Min || Req->argc > Max) { \ * send an error to the client and return from the function. */ #define _IRC_GET_SENDER_OR_RETURN_(Sender, Req, Client) \ - if (Client_Type(Client) == CLIENT_SERVER) \ + if (Client_Type(Client) == CLIENT_SERVER) { \ + if (!Req->prefix) \ + return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG, \ + Client_ID(Client), Req->command); \ Sender = Client_Search(Req->prefix); \ - else \ + } else \ Sender = Client; \ if (!Sender) \ return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG, \ - Client_ID(Client), Req->prefix); + Client_ID(Client), \ + Req->prefix ? Req->prefix : "(none)"); /** * Get target of an IRC command and make sure that it is a server. blob - efb2201773686c7475af2e5c930aaa0fd69dc621 blob + 2a3de1b454cbba48cb0cbe6739f5f49a3350c801 --- src/ngircd/irc-metadata.c +++ src/ngircd/irc-metadata.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors. + * Copyright (c)2001-2015 Alexander Barton (alex@barton.de) and Contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ #include "conn-func.h" #include "channel.h" +#include "irc-macros.h" #include "irc-write.h" #include "log.h" #include "messages.h" @@ -47,6 +48,8 @@ IRC_METADATA(CLIENT *Client, REQUEST *Req) assert(Client != NULL); assert(Req != NULL); + _IRC_REQUIRE_PREFIX_OR_RETURN_(Client, Req) + prefix = Client_Search(Req->prefix); if (!prefix) return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG, blob - 1d69a6cc75cfa83f7598dd723fd3b3d8fb48b8f0 blob + ee0a556349b3c113f5dd6841a01f42e9b9baabef --- src/ngircd/irc-oper.c +++ src/ngircd/irc-oper.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors. + * Copyright (c)2001-2015 Alexander Barton (alex@barton.de) and Contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +30,7 @@ #include "class.h" #include "parse.h" #include "irc.h" +#include "irc-macros.h" #include "irc-write.h" #include "lists.h" #include "log.h" @@ -358,6 +359,7 @@ IRC_WALLOPS( CLIENT *Client, REQUEST *Req ) from = Client; break; case CLIENT_SERVER: + _IRC_REQUIRE_PREFIX_OR_RETURN_(Client, Req) from = Client_Search(Req->prefix); break; default: blob - 4cec3b18484e49c8266c3c4f6fb4febe57ae55ba blob + 4c775e2dea855f669ae22e5d3e81cfe0a4b98698 --- src/ngircd/irc.c +++ src/ngircd/irc.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors. + * Copyright (c)2001-2015 Alexander Barton (alex@barton.de) and Contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -526,7 +526,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int Force Client_ID(Client), Req->command); } - if (Client_Type(Client) == CLIENT_SERVER) + if (Client_Type(Client) == CLIENT_SERVER && Req->prefix) from = Client_Search(Req->prefix); else from = Client; blob - d9b43cf092bea1dff69ece518a57137b31dfd6cc blob + 13a92ac250bf06962c9b2984eba70c679d9a9401 --- src/ngircd/parse.c +++ src/ngircd/parse.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors. + * Copyright (c)2001-2015 Alexander Barton (alex@barton.de) and Contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -461,10 +461,10 @@ Handle_Numeric(CLIENT *client, REQUEST *Req) } /* Determine source */ - if (! Req->prefix[0]) { - /* Oops, no prefix!? */ - Log(LOG_WARNING, "Got status code %s from \"%s\" without prefix!?", - Req->command, Client_ID(client)); + if (!Req->prefix) { + Log(LOG_WARNING, + "Got status code %s from \"%s\" without prefix!?", + Req->command, Client_ID(client)); return true; }