summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Bratch <luke@bratch.co.uk>2019-05-18 18:58:41 +0100
committerLuke Bratch <luke@bratch.co.uk>2019-05-18 18:58:41 +0100
commit95ff740e8238799cd70d829053704b9c366fc59f (patch)
tree3a4fc4d4b6c290f7f18753ee8ed05ef7244db347
parent5ebe08c1afaee5b9570899f16c3c79b6832532d2 (diff)
Alert other clients when clients connect, disconnect, authenticate, or fail to authenticate.
-rw-r--r--blabouncer.c102
1 files changed, 68 insertions, 34 deletions
diff --git a/blabouncer.c b/blabouncer.c
index 23042c4..287176b 100644
--- a/blabouncer.c
+++ b/blabouncer.c
@@ -10,7 +10,6 @@
// - Check authentication before even getting to the send functions to save unnecessary processing
// - Configurable auto channels
// - Comma separated channel list in JOINs/PARTs
-// - Alert when clients connect/authenticate/disconnect
// - Perhaps rename clients.ssl and server_ssl since they may not even be OpenSSL sockets
// - Is it possible to replay JOINs/PARTs accurately?
@@ -162,36 +161,6 @@ int sendtoclient(int fd, char *strsrc, struct client *clients, struct settings *
return 1;
}
-// Disconnect the client fd "fd" by close()ing it and remove
-// it from the array of clients.
-// Also set its authentication and registration statuses to 0.
-// Also set the pending statuses to 0
-int disconnectclient(int fd, struct client *clients) {
- printf("disconnectclient(): disconnecting client fd '%d'\n", fd);
- // Remove the client from the clients array
- for (int i = 0; i < MAXCLIENTS; i++) {
- if (clients[i].fd == fd) {
- printf("found and clearing fd %d from clients[%d]\n", fd, i);
- clients[i].fd = 0;
- clients[i].authed = 0;
- clients[i].registered = 0;
- clients[i].pendingchannelmode = 0;
- clients[i].pendingban = 0;
- clients[i].pendingwho = 0;
- clients[i].pendinglist = 0;
- // Finish up with OpenSSL
- SSL_free(clients[i].ssl);
- // Close the socket
- close(fd);
- return 1;
- }
- }
-
- // If we got here, we didn't find and clear the client
- // TODO - Do something with a failed return code
- return 0;
-}
-
// 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.
@@ -291,6 +260,46 @@ int sendtoserver(SSL *server_ssl, char *strsrc, int str_len, int clientfd, struc
return 1;
}
+// Disconnect the client fd "fd" by close()ing it and remove
+// it from the array of clients.
+// Also set its authentication and registration statuses to 0.
+// Also set the pending statuses to 0
+int disconnectclient(int fd, struct client *clients, struct ircdstrings *ircdstrings, struct settings *settings) {
+ printf("disconnectclient(): disconnecting client fd '%d'\n", fd);
+
+ // Alert other clients about the disconnection
+ char alertmsg[MAXDATASIZE];
+ if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: client with fd %d has disconnected.", ircdstrings->ircnick, fd)) {
+ fprintf(stderr, "Error while preparing authentication failure NOTICE!\n");
+ exit(1);
+ }
+ // "except" 0 since we trust this message
+ sendtoallclients(clients, alertmsg, 0, settings);
+
+ // Remove the client from the clients array
+ for (int i = 0; i < MAXCLIENTS; i++) {
+ if (clients[i].fd == fd) {
+ printf("found and clearing fd %d from clients[%d]\n", fd, i);
+ clients[i].fd = 0;
+ clients[i].authed = 0;
+ clients[i].registered = 0;
+ clients[i].pendingchannelmode = 0;
+ clients[i].pendingban = 0;
+ clients[i].pendingwho = 0;
+ clients[i].pendinglist = 0;
+ // Finish up with OpenSSL
+ SSL_free(clients[i].ssl);
+ // Close the socket
+ close(fd);
+ return 1;
+ }
+ }
+
+ // If we got here, we didn't find and clear the client
+ // TODO - Do something with a failed return code
+ return 0;
+}
+
int createchannel(struct channel *channels, char *name, char *topic, char *topicwho, char *topicwhen, char *modes, char *namestype) {
printf("createchannel(): given \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", and \"%s\".\n", name, topic, topicwho, topicwhen, modes, namestype);
@@ -955,11 +964,27 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli
// Found client in array, set to authenticated
clients[i].authed = 1;
printf("Found and authenticated fd in arr_authed.\n");
+ // Alert other clients about the successful authentication
+ char alertmsg[MAXDATASIZE];
+ if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: new client with fd %d has successfully authenticated.", ircdstrings->ircnick, sourcefd)) {
+ fprintf(stderr, "Error while preparing authentication success NOTICE!\n");
+ exit(1);
+ }
+ // "except" 0 since we trust this message
+ sendtoallclients(clients, alertmsg, 0, settings);
}
}
} else {
printf("Password rejected, disconnecting fd %d.\n", sourcefd);
- disconnectclient(sourcefd, clients);
+ disconnectclient(sourcefd, clients, ircdstrings, settings);
+ // Alert other clients about the failed authentication
+ char alertmsg[MAXDATASIZE];
+ if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: new client with fd %d has failed to authenticate.", ircdstrings->ircnick, sourcefd)) {
+ fprintf(stderr, "Error while preparing authentication failure NOTICE!\n");
+ exit(1);
+ }
+ // "except" 0 since we trust this message
+ sendtoallclients(clients, alertmsg, 0, settings);
}
free(strcopyPtr);
@@ -1167,7 +1192,7 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli
// A client has QUIT, so disconnect (close) them and don't do anything else for now - TODO: Let another clients know with a NOTICE or something
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]));
- disconnectclient(sourcefd, clients);
+ disconnectclient(sourcefd, clients, ircdstrings, settings);
free(strcopyPtr);
return 1;
}
@@ -1660,6 +1685,15 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {
}
// TODO - Handle the "find a free element" loop not finding a free element
printf("bouncer-client: new connection from %s on socket %d\n", inet_ntop(remoteaddr.ss_family, get_in_addr((struct sockaddr*)&remoteaddr), remoteIP, INET6_ADDRSTRLEN), newfd);
+ // Alert other clients about the new connection
+ char alertmsg[MAXDATASIZE];
+ if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: new client connected from %s with fd %d.", ircdstrings.ircnick,
+ inet_ntop(remoteaddr.ss_family, get_in_addr((struct sockaddr*)&remoteaddr), remoteIP, INET6_ADDRSTRLEN), newfd)) {
+ fprintf(stderr, "Error while preparing new client connection NOTICE!\n");
+ exit(1);
+ }
+ // "except" 0 since we trust this message
+ sendtoallclients(clients, alertmsg, 0, settings);
printf("bouncer-client: total client connections: %d\n", numclients(clients));
}
} else {
@@ -1674,7 +1708,7 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {
perror("recv");
}
// Disconnect the client
- disconnectclient(i, clients);
+ disconnectclient(i, clients, &ircdstrings, settings);
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
printf("bouncer-client: total client connections: %d\n", numclients(clients));