summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Bratch <luke@bratch.co.uk>2025-08-08 22:15:43 +0100
committerLuke Bratch <luke@bratch.co.uk>2025-08-08 22:15:43 +0100
commitcdc21500174966ecf2ca1eedb73eb5aa4d2f344c (patch)
tree1e5a0ffc13ed4af4b229c6361b9cdfead5e4e769
parent53d4843b8d64b4fb928c3790956ccefb4d9e0756 (diff)
Disconnect zombie clients after a while (if they haven't authenticated after AUTHTIMEOUT seconds).
-rw-r--r--TODO12
-rw-r--r--blabouncer.c21
-rw-r--r--functions.c1
-rw-r--r--structures.h2
4 files changed, 36 insertions, 0 deletions
diff --git a/TODO b/TODO
index 36db60c..22ffb73 100644
--- a/TODO
+++ b/TODO
@@ -55,3 +55,15 @@ QUIT not logged in all channels a person was in? (e.g. Joey Mon 1 Apr 20:49:14
Ability to check for updates (and optional at startup?).
Absurd CPU usage and duration doing "/BLABOUNCER REPLAY 24:0" approx. 14/09/2024 17:35.
+
+User has quit not always listed in all channel log files? (e.g. lebhome 12/11/2024 22:49:37)
+
+Custom OpenSSL protocols/ciphers?
+
+NickServ HELP with SA receiving full message in one go? e.g. oper 05/01/2025 10:06:22. Blabouncer or Anope or UnrealIRCD or something else?
+
+/NAMES doesn't show names in client.
+
+Allow specifying time zone for timestamps in config.
+
+Include error messages in response to failed STDIN in STDOUT/STDERR.
diff --git a/blabouncer.c b/blabouncer.c
index 00d339e..64b6f36 100644
--- a/blabouncer.c
+++ b/blabouncer.c
@@ -412,6 +412,7 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {
clients[i].pendingcap = 0;
clients[i].clientcode[0] = '\0';
clients[i].remoteip[0] = '\0';
+ clients[i].connecttime = 0;
}
// Struct of various strings from and for the real IRCd (such as the greeting strings, the real IRCd's name,
@@ -502,6 +503,23 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {
}
}
+ // Always check for client timeouts (clients who have been unauthed for AUTHTIMEOUT seconds) to stop the clients array getting filled up
+ int disconnected = 0;
+ for (int i = 0; i < MAXCLIENTS; i++) {
+ if (clients[i].fd > 0 && !clients[i].authed) {
+ if (time(NULL) > clients[i].connecttime + AUTHTIMEOUT) {
+ debugprint(DEBUG_SOME, "dochat(): auth timed out for client fd '%d', disconnecting!\n", clients[i].fd);
+ disconnectclient(clients[i].fd, clients, &ircdstate, settings, clientcodes);
+ // We disconnected a client, make a note to continue later...
+ disconnected = 1;
+ }
+ }
+ }
+ // If we disconnected someone, active client fds might have changed, start the loop again
+ if (disconnected) {
+ continue;
+ }
+
debugprint(DEBUG_FULL, "pselect()ing...\n");
// Check to see if any fd in the fd_set is waiting or a signal happened - blocks here until one one of those things happens
// (pselect() to do signal handling in addition to fd monitoring)
@@ -858,6 +876,9 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {
// Record the remote IP address of this client in the clients array
strncpy(clients[j].remoteip, remoteip, INET6_ADDRSTRLEN);
+ // Record the connect time
+ clients[j].connecttime = time(NULL);
+
// If using TLS then...
if (settings->clienttls) {
// ...set as OpenSSL FD and SSL_accept it
diff --git a/functions.c b/functions.c
index c3e9c94..6eddc35 100644
--- a/functions.c
+++ b/functions.c
@@ -663,6 +663,7 @@ int disconnectclient(int fd, struct client *clients, struct ircdstate *ircdstate
clients[i].pendingcap = 0;
clients[i].clientcode[0] = '\0';
clients[i].remoteip[0] = '\0';
+ clients[i].connecttime = 0;
if (settings->clienttls) {
// Finish up with OpenSSL if using client TLS
SSL_free(clients[i].ssl);
diff --git a/structures.h b/structures.h
index b2585bd..60292ed 100644
--- a/structures.h
+++ b/structures.h
@@ -31,6 +31,7 @@
#define MAXCLIENTCODES 64 // Max number of client codes to track
#define MAXCONFARR 40 // Max number of entries that a configuration array can have
#define MAXCHANNICKS 8192 // Maximum number of nicks to track per channel
+#define AUTHTIMEOUT 130 // How many seconds to give clients to authenticate, checked at most every SELECTTIMEOUT seconds
struct ircdstate {
char greeting001[MAXDATASIZE];
@@ -108,6 +109,7 @@ struct client {
int pendingcap; // Whether the client is still negotiating IRCv3 CAPabilities. 0 = no, 1 = yes, -1 = just finished (so register them as if they had just sent USER).
char clientcode[CLIENTCODELEN]; // This client's client code
char remoteip[INET6_ADDRSTRLEN]; // Client's remote IP address (assume up to IPv6 size)
+ int connecttime; // The time the client connected
};
// Structure of client codes. Used to track the last time a client identifying as a given client connected to handle auto replay for a known client.