diff options
author | Luke Bratch <luke@bratch.co.uk> | 2019-05-17 22:18:28 +0100 |
---|---|---|
committer | Luke Bratch <luke@bratch.co.uk> | 2019-05-17 22:18:28 +0100 |
commit | 6c4c42c68c53091a0ca04ae6885ed3cc24216348 (patch) | |
tree | 8223b896b5da3f8f40cffe4970edf7e85c379cff /blabouncer.c | |
parent | 751bee2c2ceb7e9426bf00a669da5679c20ee41a (diff) |
Properly support changing our nick while connecting by updating it everywhere including initial server welcome strings.
Make sure channels are cleared when PARTing them.
Ignore most commands from clients until they are registered with us.
Send the correct current nick when sending NOTICEs.
Diffstat (limited to 'blabouncer.c')
-rw-r--r-- | blabouncer.c | 57 |
1 files changed, 41 insertions, 16 deletions
diff --git a/blabouncer.c b/blabouncer.c index 559e2b1..c4396f4 100644 --- a/blabouncer.c +++ b/blabouncer.c @@ -114,6 +114,7 @@ struct client { int fd; // Client socket fd - 0 means not connected, greater than 0 means connected and the value is the fd number (so we know which ones to try to read and send to) int authed; // Client authentication status - 0 means not authenticated, 1 means authenticated. SSL *ssl; // OpenSSL structures when using TLS, or faked by casting fd ints to SSL* if not. - TODO - Can we drop one of either "int fd" or "SSL *ssl" now? + int registered; // Whether the client has finished registering with the bouncer }; // Return index of requested client FD within the clients array. @@ -159,8 +160,8 @@ int sendtoclient(int fd, char *str, struct client *clients, struct settings *set } // Disconnect the client fd "fd" by close()ing it and remove -// it from the arr_clients array of clients. -// Also set its authentication status to 0. +// it from the array of clients. +// Also set its authentication and registration statuses to 0. int disconnectclient(int fd, struct client *clients) { printf("disconnectclient(): disconnecting client fd '%d'\n", fd); close(fd); // bye! @@ -170,6 +171,7 @@ int disconnectclient(int fd, struct client *clients) { printf("found and clearing fd %d from clients[%d]\n", fd, i); clients[i].fd = 0; clients[i].authed = 0; + clients[i].registered = 0; return 1; } } @@ -476,7 +478,12 @@ int removechannel(struct channel *channels, char *name) { if (strncmp(channels[i].name, name, strlen(name)) == 0) { // ..and NULL its name (0th character = '\0') channels[i].name[0] = '\0'; - printf("removechannel(): channel removed and topicwhen set to '%s'.\n", channels[i].topicwhen); + printf("removechannel(): channel '%s' removed and topicwhen set to '%s'.\n", name, channels[i].topicwhen); + // Finally clear all its users + for (int j = 0; j < MAXCHANUSERS; j++) { + channels[i].nicks[j][0] = '\0'; + } + printf("removechannel(): channel '%s' users cleared.\n", name); return 1; } } @@ -491,7 +498,7 @@ int removechannel(struct channel *channels, char *name) { // 'sourcefd' is the client to send to, and replayseconds is the number of // seconds of replay to replay. // Returns 1 for success or 0 for failure. -int doreplay(int sourcefd, int replayseconds, struct client *clients, struct settings *settings) { +int doreplay(int sourcefd, int replayseconds, struct client *clients, struct settings *settings, struct ircdstrings *ircdstrings) { char outgoingmsg[MAXDATASIZE]; // Figure out how many lines to replay @@ -502,7 +509,7 @@ int doreplay(int sourcefd, int replayseconds, struct client *clients, struct set printf("Error getting number of replay lines.\n"); exit(1); } else if (numlines == 0) { - snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :0 replay log lines found in the time requested, nothing to send.", settings->ircnick); + snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :0 replay log lines found in the time requested, nothing to send.", ircdstrings->ircnick); sendtoclient(sourcefd, outgoingmsg, clients, settings); return 1; } @@ -768,12 +775,19 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli // Was it us? if (strncmp(ircdstrings->nickuserhost, tokens[0], strlen(ircdstrings->nickuserhost)) == 0) { + // Make a copy of the old nickuserhost for updategreetings() below + char *nickuserhostcpy = strdup(ircdstrings->nickuserhost); // Update nickuserhost with the new :nick!user@host updatenickuserhost(ircdstrings->nickuserhost, tokens[2]); printf("Updated nickuserhost to '%s'.\n", ircdstrings->nickuserhost); - // Update ircnick + // Prepare to update ircnick and greetings strings + // Temporary copy of new nickuserhost char *prefixcopy = strdup(ircdstrings->nickuserhost); + // Get nick from it extractnickfromprefix(prefixcopy); + // Update greeting strings for relaying to new clients + updategreetings(ircdstrings->greeting001, ircdstrings->greeting002, ircdstrings->greeting003, ircdstrings->greeting004, ircdstrings->nickuserhost, nickuserhostcpy, tokens[2], ircdstrings->ircnick); + // Update our nick strcpy(ircdstrings->ircnick, prefixcopy); printf("Updated ircnick to '%s'.\n", ircdstrings->ircnick); } @@ -830,13 +844,13 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli sendtoclient(sourcefd, outgoingmsg, clients, settings); // Send our own greeting message - snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :Welcome to blabouncer!", settings->ircnick); + snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :Welcome to blabouncer!", ircdstrings->ircnick); sendtoclient(sourcefd, outgoingmsg, clients, settings); - snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :Blabouncer commands are all prefixed with BLABOUNCER which you can usually send using \"/QUOTE BLABOUNCER\"", settings->ircnick); + snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :Blabouncer commands are all prefixed with BLABOUNCER which you can usually send using \"/QUOTE BLABOUNCER\"", ircdstrings->ircnick); sendtoclient(sourcefd, outgoingmsg, clients, settings); - snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :Valid blabouncer commands are:", settings->ircnick); + snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :Valid blabouncer commands are:", ircdstrings->ircnick); sendtoclient(sourcefd, outgoingmsg, clients, settings); - snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :\"BLABOUNCER REPLAY [seconds]\" (Where [seconds] is the number of seconds of replay log to replay.)", settings->ircnick); + snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :\"BLABOUNCER REPLAY [seconds]\" (Where [seconds] is the number of seconds of replay log to replay.)", ircdstrings->ircnick); sendtoclient(sourcefd, outgoingmsg, clients, settings); // Get the channel count so we can enumerate over all channels. @@ -917,9 +931,19 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli sendtoclient(sourcefd, outgoingmsg, clients, settings); } + // Set the client as registered + clients[arrindex(clients, sourcefd)].registered = 1; + // Catch the client up with the default number of seconds of replay - doreplay(sourcefd, settings->replayseconds, clients, settings); + doreplay(sourcefd, settings->replayseconds, clients, settings, ircdstrings); + + return 1; + } + // Pretty much ignore anything else the client says if it's not registered yet, + // as the first thing we want to hear is either PASS or USER + if (!clients[arrindex(clients, sourcefd)].registered) { + printf("Ignoring client command '%s' from sourcefd '%d' as not registered yet.\n", tokens[0], sourcefd); return 1; } @@ -1021,19 +1045,19 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli int replayseconds; if ((replayseconds = strtol(tokens[2], NULL, 10)) == 0) { printf("Invalid number of replay seconds provided by REPLAY. Telling client.\n"); - snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :Invalid number of seconds of replay requested by REPLAY command.", settings->ircnick); + snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :Invalid number of seconds of replay requested by REPLAY command.", ircdstrings->ircnick); sendtoclient(sourcefd, outgoingmsg, clients, settings); return 1; } - doreplay(sourcefd, replayseconds, clients, settings); + doreplay(sourcefd, replayseconds, clients, settings, ircdstrings); return 1; // Unrecognised BLABOUNCER command received, send some help instructions } else { printf("Client BLABOUNCER unrecognised command found and it is: %s with length %zd! Sending a help message.\n", tokens[1], strlen(tokens[1])); - snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :Unrecognised BLABOUNCER command received. Valid commands are:", settings->ircnick); + snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :Unrecognised BLABOUNCER command received. Valid commands are:", ircdstrings->ircnick); sendtoclient(sourcefd, outgoingmsg, clients, settings); - snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :\"BLABOUNCER REPLAY [seconds]\" (Where [seconds] is the number of seconds of replay log to replay.)", settings->ircnick); + snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :\"BLABOUNCER REPLAY [seconds]\" (Where [seconds] is the number of seconds of replay log to replay.)", ircdstrings->ircnick); sendtoclient(sourcefd, outgoingmsg, clients, settings); return 1; } @@ -1186,10 +1210,11 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { // Set up clients structure struct client clients[MAXCLIENTS]; - // Set all the clients to be "not connected" and "not authenticated" + // Set all the clients to be "not connected", "not authenticated", and "not registered" for (int i = 0; i < MAXCLIENTS; i++) { clients[i].fd = 0; clients[i].authed = 0; + clients[i].registered = 0; } // Initialise OpenSSL (used for both client and server) |