From 3b85b88516fbc4c793a456674265b6a64d92eee2 Mon Sep 17 00:00:00 2001 From: Luke Bratch Date: Sun, 19 May 2019 15:11:05 +0100 Subject: Only relay WHOIS and WHOWAS requests to the server and their responses to the requesting client. Also fix flag for pending LIST responses. --- blabouncer.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 143 insertions(+), 4 deletions(-) diff --git a/blabouncer.c b/blabouncer.c index f85e58c..846695b 100644 --- a/blabouncer.c +++ b/blabouncer.c @@ -7,7 +7,6 @@ // - Perhaps rename clients.ssl and server_ssl since they may not even be OpenSSL sockets // - Is it possible to replay JOINs/PARTs accurately? // - Add help output for missing certs -// - Only relay WHOIS replies to requesting client // - Remove any old channel name/mode/prefix code that isn't needed any more // "server" means the real IRC server @@ -110,6 +109,8 @@ struct client { int pendingban; // Whether the client is waiting to hear back from a "MODE #channel b" command int pendingwho; // Whether the client is waiting to hear back from a "MODE #channel" command int pendinglist; // Whether the client is waiting to hear back from a "LIST" command + int pendingwhois; // Whether the client is waiting to hear back from a "WHOIS" command + int pendingwhowas; // Whether the client is waiting to hear back from a "WHOWAS" command int pendingnames; // Count of RPL_NAMREPLYs the client is waiting on. }; @@ -285,6 +286,8 @@ int disconnectclient(int fd, struct client *clients, struct ircdstrings *ircdstr clients[i].pendingban = 0; clients[i].pendingwho = 0; clients[i].pendinglist = 0; + clients[i].pendingwhois = 0; + clients[i].pendingwhowas = 0; clients[i].pendingnames = 0; // Finish up with OpenSSL SSL_free(clients[i].ssl); @@ -1002,11 +1005,34 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli // Relay to all pending clients for (int i = 0; i < MAXCLIENTS; i++) { - if (clients[i].pendingwho == 1 && clients[i].fd) { + if (clients[i].pendinglist == 1 && clients[i].fd) { sendtoclient(clients[i].fd, str, clients, settings); // And clear the pending flag if it's 323 (RPL_LISTEND) if (strncmp(tokens[1], "323", strlen(tokens[1])) == 0) { - clients[i].pendingwho = 0; + clients[i].pendinglist = 0; + } + } + } + + free(strcopyPtr); + return 1; + } + + // Server 307 (RPL_SUSERHOST), 311 (RPL_WHOISUSER), 312 (RPL_WHOISSERVER), 317 (RPL_WHOISIDLE), 319 (RPL_WHOISCHANNELS), or 318 (RPL_ENDOFWHOIS) received? + // Send to any clients who requested a WHOIS. + if (strncmp(tokens[1], "307", strlen(tokens[1])) == 0 || strncmp(tokens[1], "311", strlen(tokens[1])) == 0 || + strncmp(tokens[1], "312", strlen(tokens[1])) == 0 || strncmp(tokens[1], "317", strlen(tokens[1])) == 0 || + strncmp(tokens[1], "319", strlen(tokens[1])) == 0 || strncmp(tokens[1], "318", strlen(tokens[1])) == 0) { + printf("Server 307 RPL_SUSERHOST, 311 RPL_WHOISUSER, 312 RPL_WHOISSERVER, 317 RPL_WHOISIDLE, 319 RPL_WHOISCHANNELS, or 318 RPL_ENDOFWHOIS " + "found and it is: %s with length %zd! Sending to clients who are pending one of these.\n", tokens[1], strlen(tokens[1])); + + // Relay to all pending clients + for (int i = 0; i < MAXCLIENTS; i++) { + if (clients[i].pendingwhois == 1 && clients[i].fd) { + sendtoclient(clients[i].fd, str, clients, settings); + // And clear the pending flag if it's 318 RPL_ENDOFWHOIS + if (strncmp(tokens[1], "318", strlen(tokens[1])) == 0) { + clients[i].pendingwhois = 0; } } } @@ -1015,6 +1041,99 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli return 1; } + // Server 307 (RPL_SUSERHOST), 311 (RPL_WHOISUSER), 317 (RPL_WHOISIDLE), 319 (RPL_WHOISCHANNELS), or 318 (RPL_ENDOFWHOIS) received? + // Send to any clients who requested a WHOIS. + if (strncmp(tokens[1], "307", strlen(tokens[1])) == 0 || strncmp(tokens[1], "311", strlen(tokens[1])) == 0 || + strncmp(tokens[1], "317", strlen(tokens[1])) == 0 || strncmp(tokens[1], "319", strlen(tokens[1])) == 0 || + strncmp(tokens[1], "318", strlen(tokens[1])) == 0) { + printf("Server 307 RPL_SUSERHOST, 311 RPL_WHOISUSER, 317 RPL_WHOISIDLE, 319 RPL_WHOISCHANNELS, or 318 RPL_ENDOFWHOIS " + "found and it is: %s with length %zd! Sending to clients who are pending one of these.\n", tokens[1], strlen(tokens[1])); + + // Relay to all pending clients + for (int i = 0; i < MAXCLIENTS; i++) { + if (clients[i].pendingwhowas == 1 && clients[i].fd) { + sendtoclient(clients[i].fd, str, clients, settings); + // And clear the pending flag if it's 318 RPL_ENDOFWHOIS + if (strncmp(tokens[1], "318", strlen(tokens[1])) == 0) { + clients[i].pendingwhowas = 0; + } + } + } + + free(strcopyPtr); + return 1; + } + + // Server 314 (RPL_WHOWASUSER), 406 (ERR_WASNOSUCHNICK), or 369 (RPL_ENDOFWHOWAS) received? + // Send to any clients who requested a WHOWAS. + if (strncmp(tokens[1], "314", strlen(tokens[1])) == 0 || strncmp(tokens[1], "406", strlen(tokens[1])) == 0 || strncmp(tokens[1], "369", strlen(tokens[1])) == 0) { + printf("314 (RPL_WHOWASUSER), 406 (ERR_WASNOSUCHNICK), or 369 (RPL_ENDOFWHOWAS) " + "found and it is: %s with length %zd! Sending to clients who are pending one of these.\n", tokens[1], strlen(tokens[1])); + + // Relay to all pending clients + for (int i = 0; i < MAXCLIENTS; i++) { + if (clients[i].pendingwhowas == 1 && clients[i].fd) { + sendtoclient(clients[i].fd, str, clients, settings); + // And clear the pending flag if it's 369 RPL_ENDOFWHOWAS + if (strncmp(tokens[1], "369", strlen(tokens[1])) == 0) { + clients[i].pendingwhowas = 0; + } + } + } + + free(strcopyPtr); + return 1; + } + + // Server 312 (RPL_WHOISSERVER) received? Check to see if anyone was pending a WHOIS or a WHOWAS and send to them, if not send to everyone. + if (strncmp(tokens[1], "312", strlen(tokens[1])) == 0) { + printf("Server 312 (RPL_WHOISSERVER) found and it is: %s with length %zd! Sending to clients who are pending this or to everyone if nobody is.\n", tokens[1], strlen(tokens[1])); + + int waspending = 0; + + // Relay to all pending clients + for (int i = 0; i < MAXCLIENTS; i++) { + if (clients[i].pendingwhois == 1 || clients[i].pendingwhowas == 1) { + sendtoclient(clients[i].fd, str, clients, settings); + // Note that we were pending this + waspending = 1; + } + } + + // If no client was pending this, send to everyone + if (!waspending) { + sendtoallclients(clients, str, 0, settings); + } + + free(strcopyPtr); + return 1; + } + + + // Server 401 (ERR_NOSUCHNICK) received? Check to see if anyone was pending a WHOIS and send to them, if not send to everyone. + if (strncmp(tokens[1], "401", strlen(tokens[1])) == 0) { + printf("Server 401 (ERR_NOSUCHNICK) found and it is: %s with length %zd! Sending to clients who are pending this or to everyone if nobody is.\n", tokens[1], strlen(tokens[1])); + + int waspending = 0; + + // Relay to all pending clients + for (int i = 0; i < MAXCLIENTS; i++) { + if (clients[i].pendingwhois == 1) { + sendtoclient(clients[i].fd, str, clients, settings); + // Note that we were pending this + waspending = 1; + } + } + + // If no client was pending this, send to everyone + if (!waspending) { + sendtoallclients(clients, str, 0, settings); + } + + free(strcopyPtr); + return 1; + } + // Server 432 (ERR_ERRONEUSNICKNAME) or 433 (ERR_NICKNAMEINUSE) received? See which nick we're on and try another. if (strncmp(tokens[1], "432", strlen(tokens[1])) == 0 || strncmp(tokens[1], "433", strlen(tokens[1])) == 0) { printf("Server 432 (ERR_ERRONEUSNICKNAME) or 433 (ERR_NICKNAMEINUSE) found and it is: %s with length %zd! Trying another nick...\n", tokens[1], strlen(tokens[1])); @@ -1350,7 +1469,7 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli // LIST requested, mark the client as waiting for the reply (so not all clients get it) and send it on the server if (strncmp(tokens[0], "LIST", strlen(tokens[0])) == 0) { printf("Client LIST found and it is: %s with length %zd! Marking as pending.\n", tokens[0], strlen(tokens[0])); - clients[arrindex(clients, sourcefd)].pendingwho = 1; + clients[arrindex(clients, sourcefd)].pendinglist = 1; // Either way, send it on the server sendtoserver(server_ssl, str, strlen(str), sourcefd, clients, settings); @@ -1358,6 +1477,24 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli return 1; } + // Client WHOIS received, send straight on to server and mark the client as pending the response + if (strncmp(tokens[0], "WHOIS", strlen(tokens[0])) == 0) { + printf("Client WHOIS found and it is: %s with length %zd! Sending to server and setting client as pending.\n", tokens[0], strlen(tokens[0])); + clients[arrindex(clients, sourcefd)].pendingwhois = 1; + sendtoserver(server_ssl, str, strlen(str), sourcefd, clients, settings); + free(strcopyPtr); + return 1; + } + + // Client WHOWAS received, send straight on to server and mark the client as pending the response + if (strncmp(tokens[0], "WHOWAS", strlen(tokens[0])) == 0) { + printf("Client WHOWAS found and it is: %s with length %zd! Sending to server and setting client as pending.\n", tokens[0], strlen(tokens[0])); + clients[arrindex(clients, sourcefd)].pendingwhowas = 1; + sendtoserver(server_ssl, str, strlen(str), sourcefd, clients, settings); + free(strcopyPtr); + return 1; + } + // Custom BLABOUNCER command received // Case insensitive comparisons here since clients won't be recognising and uppercasing these commands if (strncasecmp(tokens[0], "BLABOUNCER", strlen(tokens[0])) == 0) { @@ -1549,6 +1686,8 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { clients[i].pendingban = 0; clients[i].pendingwho = 0; clients[i].pendinglist = 0; + clients[i].pendingwhois = 0; + clients[i].pendingwhowas = 0; clients[i].pendingnames = 0; } -- cgit v1.2.3