diff options
author | Luke Bratch <luke@bratch.co.uk> | 2019-05-11 22:11:42 +0100 |
---|---|---|
committer | Luke Bratch <luke@bratch.co.uk> | 2019-05-11 22:11:42 +0100 |
commit | 34d410dc82e05f4255ec23a9deaff212b7903955 (patch) | |
tree | 75f70464ca07411c85f79263af5cd55867ad9993 | |
parent | 231656bf59da65036b171ce5ccc06eeadd64a05a (diff) |
Implement authentication in the form of the bouncer having a configurable server password
-rw-r--r-- | blabouncer.c | 184 | ||||
-rw-r--r-- | blabouncer.conf | 3 | ||||
-rw-r--r-- | config.c | 47 | ||||
-rw-r--r-- | config.h | 2 | ||||
-rw-r--r-- | replay.c | 3 |
5 files changed, 186 insertions, 53 deletions
diff --git a/blabouncer.c b/blabouncer.c index 29b90ae..c748ebc 100644 --- a/blabouncer.c +++ b/blabouncer.c @@ -8,9 +8,9 @@ // - Add blabouncer MOTD (375, 372, 376) // - "01:53:47 -!- ServerMode/#test [b] by irc.tghost.co.uk" on existing clients when new client connects // - Keep track of changing user nicks/modes -// - Relay log can just be "log/resend everything that ever hit sendto[all]client[s]()" (or maybe just PRIVMSGs? + NOTICEs and friends?) +// - Should relay log do more than PRIVMSGs? // - Implement TLS -// - Implement password/login +// - Check authentication before even getting to the send functions to save unnecessary processing // // Example WHOIS reply: // BOUNCER-SERVER RECEIVED: :irc.tghost.co.uk 307 blabounce l_bratch :is identified for this nick @@ -79,9 +79,20 @@ struct ircdstrings { int debugmode = 0; // Send whatever string to a specific client by providing the FD -int sendtoclient(int fd, char *str) { +int sendtoclient(int fd, char *str, int arr_clients[], int arr_authed[]) { appendcrlf(str); // Do this just before sending so callers don't need to worry about it + // Find the client in the clients array and make sure they are authenticated + for (int i = 0; i < MAXCLIENTS; i++) { + if (arr_clients[i] == fd) { + // Found client in array, check authentication status + if (!arr_authed[i]) { + printf("sendtoclient(): skipping unauthenticated client with fd %d.\n", arr_clients[i]); + return 0; + } + } + } + printf("sendtoclient(): sending \"%s\" (length %zd) to client with fd %d.\n", str, strlen(str), fd); if (send(fd, str, strlen(str), 0) == -1) { perror("error: sendtoclient() send()\n"); @@ -92,8 +103,9 @@ int sendtoclient(int fd, char *str) { } // Disconnect the client fd "fd" by close()ing it and remove -// it from the arr_clients array of clients -int disconnectclient(int fd, int arr_clients[]) { +// it from the arr_clients array of clients. +// Also set its authentication status to 0. +int disconnectclient(int fd, int arr_clients[], int arr_authed[]) { printf("disconnectclient(): disconnecting client fd '%d'\n", fd); close(fd); // bye! // Remove the client from the clients array @@ -101,6 +113,7 @@ int disconnectclient(int fd, int arr_clients[]) { if (arr_clients[j] == fd) { printf("found and clearing fd %d from arr_clients[%d]\n", fd, j); arr_clients[j] = 0; + arr_authed[j] = 0; return 1; } } @@ -112,8 +125,9 @@ int disconnectclient(int fd, int arr_clients[]) { // Relay/send message to all clients (optionally except one) // "except" is used to send to all clients _except_ the fd provided (except = 0 (EXCEPT_NONE) avoids this, i.e. sends to all) +// "except" is really the "sourcefd" and is also used as part of the authentication check - this is messy and they should perhaps be two separate arguments. // TODO - is passing str_len useful if we're appendcrlfing and then using strlen(str) in the send? I guess not... (As long as we're always null terminated in the correct place.) -int sendtoallclients(int *clientsockfd, int fdmax, int arr_clients[], char *str, int except) { +int sendtoallclients(int *clientsockfd, int fdmax, int arr_clients[], char *str, int except, int arr_authed[]) { char *sendertype; @@ -128,6 +142,22 @@ int sendtoallclients(int *clientsockfd, int fdmax, int arr_clients[], char *str, sendertype = "bouncer-server"; } + // Find the sending client in the clients array and make sure they are authenticated + for (int i = 0; i < MAXCLIENTS; i++) { + // Trust clientfd of 0, only we can set that ourselves + if (!except) { + printf("sendtoallclients(): trusting clientfd of 0.\n"); + break; + } + if (arr_clients[i] == except) { + // Found client in array, check authentication status + if (!arr_authed[i]) { + printf("sendtoallclients(): skipping unauthenticated client with fd %d.\n", arr_clients[i]); + return 0; + } + } + } + // relay/send to all clients... for (int i = *clientsockfd + 1; i <= fdmax; i++) { // Skip the current client if "except" non-zero (no need to send back to itself) @@ -138,7 +168,11 @@ int sendtoallclients(int *clientsockfd, int fdmax, int arr_clients[], char *str, // ...but only if they are connected for (int j = 0; j < MAXCLIENTS; j++) { if (arr_clients[j] == i) { - printf("sendtoallclients(): %s: sending %s to client with fd %d.\n", sendertype, str, i); + if (!arr_authed[j]) { + printf("sendtoallclients(): skipping unauthenticated client with fd %d.\n", arr_clients[j]); + continue; + } + printf("sendtoallclients(): %s: sending '%s' to client with fd %d.\n", sendertype, str, i); if (send(i, str, strlen(str), 0) == -1) { perror("error: sendtoallclients() send()\n"); } @@ -150,15 +184,36 @@ int sendtoallclients(int *clientsockfd, int fdmax, int arr_clients[], char *str, } // Send whatever string to the real IRC server -int sendtoserver(int *serversockfd, char *str, int str_len) { +// Client FD and arrays needed to make sure anything relayed from a client is from an authenticated client. +// clientfd of "0" means trusted, used when we are sending things ourselves that weren't relayed +// from a relay client. +int sendtoserver(int *serversockfd, char *str, int str_len, int clientfd, int arr_clients[], int arr_authed[]) { appendcrlf(str); // Do this just before sending so callers don't need to worry about it str_len = strlen(str); // Recalculate str_len in case it changed (TODO: so do we even need to pass it to this function?) + + // Find the sending client in the clients array and make sure they are authenticated + for (int i = 0; i < MAXCLIENTS; i++) { + // Trust clientfd of 0, only we can set that ourselves + if (!clientfd) { + printf("sendtoserver(): trusting clientfd of 0.\n"); + break; + } + if (arr_clients[i] == clientfd) { + // Found client in array, check authentication status + if (!arr_authed[i]) { + printf("sendtoserver(): skipping unauthenticated client with fd %d.\n", arr_clients[i]); + return 0; + } + } + } + printf("sendtoserver(): sending %s to IRC server (length %d).\n", str, str_len); if (send(*serversockfd, str, str_len, 0) == -1) { // 0 is bitwise OR for no send() flags printf("error: sendtoserver() send()\n"); + return 0; } - return 0; + return 1; } int createchannel(struct channel *channels, char *name, char *topic, char *topicwho, char *topicwhen, char *modes, char *namestype) { @@ -336,7 +391,7 @@ int removechannel(struct channel *channels, char *name) { // Figure out what to do with each CRLF-split IRC message (if anything) // by splitting out the different components by space character (ASCII 0x20). // -// serversockfd, clientsockfd, fdmax, arr_clients, except all passed to here so we can +// serversockfd, clientsockfd, fdmax, arr_clients, arr_authed, all passed to here so we can // send/relay a response to server or (other) client(s) directly from this function if // we want to. // @@ -347,7 +402,7 @@ int removechannel(struct channel *channels, char *name) { // Return 1 if we processed something and expect the caller to not need to do anything more // Return 0 if we didn't process it and the caller might want to do something //int processircmessage(int *serversockfd, int *clientsockfd, char *str, int source) { -int processircmessage(int *serversockfd, int *clientsockfd, char *str, int source, int fdmax, int arr_clients[], int sourcefd, struct ircdstrings *ircdstrings, struct channel *channels) { +int processircmessage(int *serversockfd, int *clientsockfd, char *str, int source, int fdmax, int arr_clients[], int sourcefd, struct ircdstrings *ircdstrings, struct channel *channels, int arr_authed[]) { // Track which space-separated token within this response we're on int counter = 0; @@ -383,7 +438,8 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc fprintf(stderr, "Error while preparing PONG response!\n"); exit(1); } - sendtoserver(serversockfd, outgoingmsg, strlen(outgoingmsg)); + // sourcefd = 0 as this is a trusted response + sendtoserver(serversockfd, outgoingmsg, strlen(outgoingmsg), 0, arr_clients, arr_authed); // We processed something so return true return 1; @@ -455,7 +511,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc } // And then send to all clients - sendtoallclients(clientsockfd, fdmax, arr_clients, str, sourcefd); + sendtoallclients(clientsockfd, fdmax, arr_clients, str, sourcefd, arr_authed); return 1; } @@ -476,7 +532,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc } // And then send to all clients - sendtoallclients(clientsockfd, fdmax, arr_clients, str, sourcefd); + sendtoallclients(clientsockfd, fdmax, arr_clients, str, sourcefd, arr_authed); return 1; } @@ -543,7 +599,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc setchanneltopicwhotime(channels, tokens[2], prefixcopy, timenowstr); // And then finally relay to all clients - sendtoallclients(clientsockfd, fdmax, arr_clients, str, sourcefd); + sendtoallclients(clientsockfd, fdmax, arr_clients, str, sourcefd, arr_authed); return 1; } @@ -551,7 +607,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc if (strncmp(tokens[1], "PRIVMSG", strlen(tokens[1])) == 0) { printf("Server PRIVMSG found and it is: %s with length %zd! Next token is '%s'. Relaying to all clients.\n", tokens[0], strlen(tokens[0]), tokens[2]); - sendtoallclients(clientsockfd, fdmax, arr_clients, str, sourcefd); + sendtoallclients(clientsockfd, fdmax, arr_clients, str, sourcefd, arr_authed); // Write to relay log writerelayline(str); @@ -564,23 +620,40 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc break; case SOURCE_CLIENT: // If message(s) were from a real IRC client + // PASS received? User is trying to log in, check their password. + if (strncmp(tokens[0], "PASS", strlen(tokens[0])) == 0) { + if (checkpassword(tokens[1])) { + printf("Password accepted! Setting fd %d to authenticated.\n", sourcefd); + // Find the client in the clients array and set them as authenticated + for (int i = 0; i < MAXCLIENTS; i++) { + if (arr_clients[i] == sourcefd) { + // Found client in array, set to authenticated + arr_authed[i] = 1; + printf("Found and authenticated fd in arr_authed.\n"); + } + } + } else { + printf("Password rejected, disconnecting fd %d.\n", sourcefd); + disconnectclient(sourcefd, arr_clients, arr_authed); + } + + return 1; + } + // USER received? If so, assume this is a new client connecting and catch them on up on the state if (strncmp(tokens[0], "USER", strlen(tokens[0])) == 0) { - // Need to sort out channel structure first!! - printf("TODO: USER received!\n"); - // Somewhere to store the several strings we will need to build and send char outgoingmsg[MAXDATASIZE]; // String to send to client // Send IRC greeting strings (001/RPL_WELCOME, 002/RPL_YOURHOST, 003/RPL_CREATED, 004/RPL_MYINFO) to client snprintf(outgoingmsg, MAXDATASIZE, "%s", ircdstrings->greeting001); - sendtoclient(sourcefd, outgoingmsg); + sendtoclient(sourcefd, outgoingmsg, arr_clients, arr_authed); snprintf(outgoingmsg, MAXDATASIZE, "%s", ircdstrings->greeting002); - sendtoclient(sourcefd, outgoingmsg); + sendtoclient(sourcefd, outgoingmsg, arr_clients, arr_authed); snprintf(outgoingmsg, MAXDATASIZE, "%s", ircdstrings->greeting003); - sendtoclient(sourcefd, outgoingmsg); + sendtoclient(sourcefd, outgoingmsg, arr_clients, arr_authed); snprintf(outgoingmsg, MAXDATASIZE, "%s", ircdstrings->greeting004); - sendtoclient(sourcefd, outgoingmsg); + sendtoclient(sourcefd, outgoingmsg, arr_clients, arr_authed); // Get the channel count so we can enumerate over all channels. // Storing separately so we can skip over blank channels. @@ -601,7 +674,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc fprintf(stderr, "Error while preparing USER just connected, channel JOIN responses!\n"); exit(1); } - sendtoclient(sourcefd, outgoingmsg); + sendtoclient(sourcefd, outgoingmsg, arr_clients, arr_authed); // Send topic (or lack thereof) to client // If there isn't one set (we guess this if topic timestamp is 0), send 331 RPL_NOTOPIC @@ -612,7 +685,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc exit(1); } // ..and send it to the client - sendtoclient(sourcefd, outgoingmsg); + sendtoclient(sourcefd, outgoingmsg, arr_clients, arr_authed); // If there is one set, send 332 RPL_TOPIC and 333 RPL_TOPICWHOTIME } else { // Prepare the topic message... @@ -621,7 +694,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc exit(1); } // ..and send it to the client - sendtoclient(sourcefd, outgoingmsg); + sendtoclient(sourcefd, outgoingmsg, arr_clients, arr_authed); // Next prepare the topic who/when message... if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s 333 %s %s %s %s", ircdstrings->ircdname, ircdstrings->ircnick, channels[i].name, channels[i].topicwho, channels[i].topicwhen)) { @@ -629,7 +702,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc exit(1); } // ..and send it to the client - sendtoclient(sourcefd, outgoingmsg); + sendtoclient(sourcefd, outgoingmsg, arr_clients, arr_authed); } // Send list of names @@ -649,7 +722,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc fprintf(stderr, "Error while preparing USER just connected, channel NAMES responses!\n"); exit(1); } - sendtoclient(sourcefd, outgoingmsg); + sendtoclient(sourcefd, outgoingmsg, arr_clients, arr_authed); } // Once all names are sent, send the "end of /NAMES" 366 (RPL_ENDOFNAMES) message @@ -657,7 +730,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc fprintf(stderr, "Error while preparing USER just connected, end of NAMES response!\n"); exit(1); } - sendtoclient(sourcefd, outgoingmsg); + sendtoclient(sourcefd, outgoingmsg, arr_clients, arr_authed); } // Send the client however many relay lines have been requested @@ -679,7 +752,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc exit(1); } printf("Sending relay line: '%s'.\n", outgoingmsg); - sendtoclient(sourcefd, outgoingmsg); + sendtoclient(sourcefd, outgoingmsg, arr_clients, arr_authed); } return 1; @@ -694,7 +767,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc fprintf(stderr, "Error while preparing PONG response!\n"); exit(1); } - sendtoclient(sourcefd, outgoingmsg); + sendtoclient(sourcefd, outgoingmsg, arr_clients, arr_authed); // We processed something so return true return 1; @@ -709,7 +782,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc // Just send NICK to server and let it change all clients' nicks if needed if (strncmp(tokens[0], "NICK", strlen(tokens[0])) == 0) { printf("Client NICK found and it is: %s with length %zd! Sending to server...\n", tokens[0], strlen(tokens[0])); - sendtoserver(serversockfd, str, strlen(str)); + sendtoserver(serversockfd, str, strlen(str), sourcefd, arr_clients, arr_authed); return 1; } @@ -717,7 +790,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc if (strncmp(tokens[0], "PRIVMSG", strlen(tokens[0])) == 0) { printf("Client PRIVMSG found and it is: %s with length %zd! Sending to server then back to other clients...\n", tokens[0], strlen(tokens[0])); // Send original request straight to server - sendtoserver(serversockfd, str, strlen(str)); + sendtoserver(serversockfd, str, strlen(str), sourcefd, arr_clients, arr_authed); // Rebuild to full PRIVMSG string and relay to all other clients char outgoingmsg[MAXDATASIZE]; // String to send to client @@ -727,7 +800,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc exit(1); } // Send to all except source client - sendtoallclients(clientsockfd, fdmax, arr_clients, outgoingmsg, sourcefd); + sendtoallclients(clientsockfd, fdmax, arr_clients, outgoingmsg, sourcefd, arr_authed); // Write to relay log writerelayline(outgoingmsg); @@ -738,7 +811,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc // Just send JOIN to server and let it talk back to clients as required if (strncmp(tokens[0], "JOIN", strlen(tokens[0])) == 0) { printf("Client JOIN found and it is: %s with length %zd! Sending to server...\n", tokens[0], strlen(tokens[0])); - sendtoserver(serversockfd, str, strlen(str)); + sendtoserver(serversockfd, str, strlen(str), sourcefd, arr_clients, arr_authed); return 1; } @@ -747,21 +820,21 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc if (strncmp(tokens[0], "QUIT", strlen(tokens[0])) == 0) { printf("Client QUIT found from fd %d and it is: %s with length %zd! Disconnecting that fd.\n", sourcefd, tokens[0], strlen(tokens[0])); close(sourcefd); - disconnectclient(sourcefd, arr_clients); + disconnectclient(sourcefd, arr_clients, arr_authed); return 1; } // Just send PART to server and let it talk back to clients as required if (strncmp(tokens[0], "PART", strlen(tokens[0])) == 0) { printf("Client PART found and it is: %s with length %zd! Sending to server...\n", tokens[0], strlen(tokens[0])); - sendtoserver(serversockfd, str, strlen(str)); + sendtoserver(serversockfd, str, strlen(str), sourcefd, arr_clients, arr_authed); return 1; } // Just send TOPIC to server and let it talk back to clients as required if (strncmp(tokens[0], "TOPIC", strlen(tokens[0])) == 0) { printf("Client TOPIC found and it is: %s with length %zd! Sending to server...\n", tokens[0], strlen(tokens[0])); - sendtoserver(serversockfd, str, strlen(str)); + sendtoserver(serversockfd, str, strlen(str), sourcefd, arr_clients, arr_authed); return 1; } @@ -784,7 +857,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc // or send on to all other clients (if from the server) or to the server (if from a client) // if we don't know how to. // -// serversockfd, clientsockfd, fdmax, arr_clients, except all passed to here so we can +// serversockfd, clientsockfd, fdmax, arr_clients, arr_authed all passed to here so we can // send/relay a response to server or (other) client(s) for things we don't know how to process here, // or for any other reasons we need to send stuff for // @@ -794,7 +867,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc // // Return 0 if something went wrong // Return 1 if everything OK -int processrawstring(int *serversockfd, int *clientsockfd, char *str, int source, int fdmax, int arr_clients[], int sourcefd, struct ircdstrings *ircdstrings, struct channel *channels) { +int processrawstring(int *serversockfd, int *clientsockfd, char *str, int source, int fdmax, int arr_clients[], int sourcefd, struct ircdstrings *ircdstrings, struct channel *channels, int arr_authed[]) { // Copy to a temporary string so we still have the original in case it's not processed char *strcopy = strdup(str); @@ -823,7 +896,7 @@ int processrawstring(int *serversockfd, int *clientsockfd, char *str, int source for (int i = 0; i < messagecount; i++) { // Copy to a temporary string so we still have the original in case it's not processed char *messagecopy = strdup(messages[i]); - if (processircmessage(serversockfd, clientsockfd, messagecopy, source, fdmax, arr_clients, sourcefd, ircdstrings, channels)) { + if (processircmessage(serversockfd, clientsockfd, messagecopy, source, fdmax, arr_clients, sourcefd, ircdstrings, channels, arr_authed)) { printf("Message processed: \"%s\", NULLing...\n", messages[i]); messages[i][0] = '\0'; } @@ -839,16 +912,16 @@ int processrawstring(int *serversockfd, int *clientsockfd, char *str, int source // Relay/send to all clients ("except" = 0 because this should send to all clients) // TODO - Is this really going to send the original string if we have messed it with it in processrawstring() and friends!? printf("bouncer-server: sending unprocessed server messasge \"%s\" to all clients, length %zd.\n", messages[i], strlen(messages[i])); - sendtoallclients(clientsockfd, fdmax, arr_clients, messages[i], EXCEPT_NONE); + sendtoallclients(clientsockfd, fdmax, arr_clients, messages[i], EXCEPT_NONE, arr_authed); break; case SOURCE_CLIENT: // If message(s) were from a real IRC client // Send to server printf("bouncer-client: sending unprocessed client messasge \"%s\" to the server, length %zd.\n", messages[i], strlen(messages[i])); - sendtoserver(serversockfd, messages[i], strlen(messages[i])); + sendtoserver(serversockfd, messages[i], strlen(messages[i]), sourcefd, arr_clients, arr_authed); printf("bouncer-client: sending unprocessed client messasge \"%s\" to all other clients, length %zd.\n", messages[i], strlen(messages[i])); // send the same thing to all *other* clients (all except for source fd) - sendtoallclients(clientsockfd, fdmax, arr_clients, messages[i], sourcefd); + sendtoallclients(clientsockfd, fdmax, arr_clients, messages[i], sourcefd, arr_authed); break; default: fprintf(stderr, "Unexpected raw IRC string source for unprocessed messasge \"%s\", length %zd.!\n", messages[i], strlen(messages[i])); @@ -869,7 +942,8 @@ void dochat(int *serversockfd, int *clientsockfd) { int servernumbytes; // Number of bytes received from remote server char outgoingmsg[MAXDATASIZE]; // String to send to server int outgoingmsgrc; // Return code from getstdin() for outgoing message - int arr_clients[MAXCLIENTS]; // Array of all clients - 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) + int arr_clients[MAXCLIENTS]; // Array of all client FDs - 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) + int arr_authed[MAXCLIENTS]; // Array of client authentication statuses - 0 means not authenticated, 1 means authenticated. Element numbers match those of arr_clients. int num_clients = 0; // Current number of clients int fdmax; // highest numbered socket fd @@ -884,9 +958,10 @@ void dochat(int *serversockfd, int *clientsockfd) { fd_set rfds; // set of read fds to monitor with select() - 0: stdin, 1: stdout, 2: stderr, 3 and higher: sockets (at time of writing, 3: real IRC server, 4: client listener, 5 and higher: clients) - // set all the clients to be "not connected" + // Set all the clients to be "not connected" and "not authenticated" for (int i = 0; i < MAXCLIENTS; i++) { arr_clients[i] = 0; + arr_authed[i] = 0; } // <============================================= @@ -914,12 +989,14 @@ void dochat(int *serversockfd, int *clientsockfd) { // Send our NICK snprintf(outgoingmsg, MAXDATASIZE, "NICK %s", ircdstrings.ircnick); // TODO - Check for success (with return code) - sendtoserver(serversockfd, outgoingmsg, strlen(outgoingmsg)); + // sourcefd = 0 as this is a trusted message + sendtoserver(serversockfd, outgoingmsg, strlen(outgoingmsg), 0, arr_clients, arr_authed); // Send our USER snprintf(outgoingmsg, MAXDATASIZE, "USER %s 8 * : %s", ircdstrings.ircusername, ircdstrings.ircrealname); // TODO - Check for success (with return code) // TODO - Send a more intelligent/correct USER string - sendtoserver(serversockfd, outgoingmsg, strlen(outgoingmsg)); + // sourcefd = 0 as this is a trusted message + sendtoserver(serversockfd, outgoingmsg, strlen(outgoingmsg), 0, arr_clients, arr_authed); // Struct of channels we're in struct channel *channels; @@ -973,7 +1050,7 @@ void dochat(int *serversockfd, int *clientsockfd) { // Try to process received string (which should contain one or more server responses/commands) // TODO - What if there were two server respones/commands and only one didn't need relaying? - if (!processrawstring(serversockfd, clientsockfd, serverbuf, SOURCE_SERVER, fdmax, arr_clients, EXCEPT_NONE, &ircdstrings, channels)) { + if (!processrawstring(serversockfd, clientsockfd, serverbuf, SOURCE_SERVER, fdmax, arr_clients, EXCEPT_NONE, &ircdstrings, channels, arr_authed)) { fprintf(stderr, "Error: bouncer-server failed to process raw string.\n"); exit(1); } @@ -1013,7 +1090,8 @@ void dochat(int *serversockfd, int *clientsockfd) { continue; } - sendtoserver(serversockfd, outgoingmsg, strlen(outgoingmsg)); + // sourcefd = 0 as this is a trusted message + sendtoserver(serversockfd, outgoingmsg, strlen(outgoingmsg), 0, arr_clients, arr_authed); } // go through all the remaining sockets to see if there's anything from the client sockets (either new connections or existing clients sending messages) @@ -1049,6 +1127,8 @@ void dochat(int *serversockfd, int *clientsockfd) { for (int j = 0; j < MAXCLIENTS; j++) { if (arr_clients[j] == 0) { arr_clients[j] = newfd; + // Ensure its authentication status is set to 0 + arr_authed[j] = 0; break; } } @@ -1069,7 +1149,7 @@ void dochat(int *serversockfd, int *clientsockfd) { perror("recv"); } // Disconnect the client - disconnectclient(i, arr_clients); + disconnectclient(i, arr_clients, arr_authed); FD_CLR(i, &rfds); // remove from master set - TODO is this needed at the moment since we just add everything from *clientsockfd to fdmax to rfds // TODO - Handle the "remove the client" loop not finding the old fd num_clients--; // Track total number of clients @@ -1086,7 +1166,7 @@ void dochat(int *serversockfd, int *clientsockfd) { // Try to process received string (which should contain one or more client responses/commands) // TODO - What if there were two server respones/commands and only one didn't need relaying? - if (!processrawstring(serversockfd, clientsockfd, clientbuf, SOURCE_CLIENT, fdmax, arr_clients, i, &ircdstrings, channels)) { + if (!processrawstring(serversockfd, clientsockfd, clientbuf, SOURCE_CLIENT, fdmax, arr_clients, i, &ircdstrings, channels, arr_authed)) { fprintf(stderr, "Error: bouncer-client failed to process raw string.\n"); exit(1); } diff --git a/blabouncer.conf b/blabouncer.conf index 5b68918..5be29ca 100644 --- a/blabouncer.conf +++ b/blabouncer.conf @@ -10,3 +10,6 @@ realname = "Mr Bla Bouncer" # How many seconds of relay log should be sent to connecting clients relayseconds = "7200" + +# Connect password clients must provided to connect +password = "bananas" @@ -1,6 +1,6 @@ #include "config.h" -// TODO - Multiple functions here (at least readnames() and relayseconds() have the file opening code, rewrite. +// TODO - Multiple functions here (at least readnames(), relayseconds() and checkpassword()) have the file opening code, rewrite. // TODO - Can isconf() and getconf() just be merged into one function? @@ -136,5 +136,50 @@ int confrelayseconds() { } } + fclose(fp); return seconds; } + +// Check the password provided in the string 'str' against what is in +// the config file. +// Return 0 for password mismatch, or 1 for password match. +int checkpassword(char *password) { + FILE *fp; + char str[MAXCHAR]; + char* filename = "blabouncer.conf"; + + fp = fopen(filename, "r"); + + if (fp == NULL) { + printf("error: could not open configuration file '%s'.\n", filename); + exit(1); + } + + while (fgets(str, MAXCHAR, fp) != NULL) { + long int len; + if ((len = isconf(str, "password"))) { + getconf(str, len); + printf("confpassword is: '%s', length '%ld'.\n", str, strlen(str)); + // Ensure password are the same length + if (strlen(str) != strlen(password)) { + printf("Password length mismatch!\n"); + fclose(fp); + return 0; + } + // Ensure passwords match + if (strncmp(str, password, strlen(password)) == 0) { + printf("confpassword matches password.\n"); + fclose(fp); + return 1; + } else { + printf("confpassword does NOT match password!\n"); + fclose(fp); + return 0; + } + } + } + + fclose(fp); + printf("No password read from configuration file, quitting.\n"); + exit(1); +} @@ -11,4 +11,6 @@ int readnames(char *nick, char *username, char *realname); int confrelayseconds(); +int checkpassword(char *password); + #endif @@ -166,6 +166,7 @@ int relaylines(int seconds) { int timestamp = gettimestamp(str); if (timestamp < 1) { printf("Error reading timestamp from replay log file.\n"); + fclose(fp); return -1; } @@ -221,6 +222,7 @@ int readrelayline(int seconds, int linenum, char *str) { strncpy(str, line, strlen(line)); str[strlen(line)] = '\0'; + fclose(fp); return 1; } count++; @@ -228,6 +230,7 @@ int readrelayline(int seconds, int linenum, char *str) { } // If we got here something went wrong + fclose(fp); return 0; } |