summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README5
-rw-r--r--TODO8
-rw-r--r--blabouncer.c55
-rw-r--r--blabouncer.conf.example15
-rw-r--r--config.c17
-rw-r--r--functions.c86
-rw-r--r--message.c40
-rw-r--r--structures.h5
8 files changed, 194 insertions, 37 deletions
diff --git a/README b/README
index 5b217cf..3875fc2 100644
--- a/README
+++ b/README
@@ -37,6 +37,11 @@ These options can be changed by issuing a BLABOUNCER REHASH command or by sendin
- debug
- certfile
- keyfile
+ - alertconnect
+ - alertauthfail
+ - alertauthsuccess
+ - alertunautheddisconnect
+ - alertautheddisconnect
== Commands ==
diff --git a/TODO b/TODO
index a4c807b..28fdc13 100644
--- a/TODO
+++ b/TODO
@@ -51,3 +51,11 @@ Are WALLOPS logged & replayed?
QUIT not logged in all channels a person was in? (e.g. Joey Mon 1 Apr 20:49:14 BST 2024)
"/whois" with no nick - "No nickname given" goes to all clients - fixable?
+
+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.
+
+Send NOTICE about failed authentication before disconnecting.
+
+Failure to read configuration file suggestion that an upgrade may require new settings.
diff --git a/blabouncer.c b/blabouncer.c
index 75ce966..56c21a0 100644
--- a/blabouncer.c
+++ b/blabouncer.c
@@ -888,16 +888,18 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {
// TODO - Handle the "find a free element" loop not finding a free element
debugprint(DEBUG_FULL, "bouncer-client: new connection from %s on socket %d%s\n", remoteip, newfd, opensslfailmsg);
- // Alert other clients about the new connection
- char alertmsg[MAXDATASIZE];
- if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: new client connected from %s%s.", ircdstate.ircnick,
- remoteip, opensslfailmsg)) {
- fprintf(stderr, "Error while preparing new client connection NOTICE!\n");
- debugprint(DEBUG_CRIT, "Error while preparing new client connection NOTICE!\n");
- alertmsg[0] = '\0';
+ // Alert other clients about the new connection (if enabled)
+ if (settings->alertconnect) {
+ char alertmsg[MAXDATASIZE];
+ if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: new client connected from %s%s.", ircdstate.ircnick,
+ remoteip, opensslfailmsg)) {
+ fprintf(stderr, "Error while preparing new client connection NOTICE!\n");
+ debugprint(DEBUG_CRIT, "Error while preparing new client connection NOTICE!\n");
+ alertmsg[0] = '\0';
+ }
+ // "except" 0 since we trust this message
+ sendtoallclients(clients, alertmsg, 0, settings);
}
- // "except" 0 since we trust this message
- sendtoallclients(clients, alertmsg, 0, settings);
debugprint(DEBUG_FULL, "bouncer-client: total client connections: %d\n", numclients(clients));
}
// If using client TLS and still pending SSL_accept() then re-try SSL_accept() (it can't be real client data yet)
@@ -1224,6 +1226,41 @@ int main(int argc, char *argv[]) {
exit(1);
}
+ // Is alerting (NOTICE) upon a new connection enabled?
+ settings.alertconnect = getconfint("alertconnect", settings.conffile);
+ if (errno == ECONFINT) {
+ printf("main(): error getting 'alertconnect' from configuration file.\n");
+ exit(1);
+ }
+
+ // Is alerting (NOTICE) upon a failed authentication enabled?
+ settings.alertauthfail = getconfint("alertauthfail", settings.conffile);
+ if (errno == ECONFINT) {
+ printf("main(): error getting 'alertauthfail' from configuration file.\n");
+ exit(1);
+ }
+
+ // Is alerting (NOTICE) upon a successful authentication enabled?
+ settings.alertauthsuccess = getconfint("alertauthsuccess", settings.conffile);
+ if (errno == ECONFINT) {
+ printf("main(): error getting 'alertauthsuccess' from configuration file.\n");
+ exit(1);
+ }
+
+ // Is alerting (NOTICE) upon unauthenticated client disconnections enabled?
+ settings.alertunautheddisconnect = getconfint("alertunautheddisconnect", settings.conffile);
+ if (errno == ECONFINT) {
+ printf("main(): error getting 'alertunautheddisconnect' from configuration file.\n");
+ exit(1);
+ }
+
+ // Is alerting (NOTICE) upon authenticated client disconnections enabled?
+ settings.alertautheddisconnect = getconfint("alertautheddisconnect", settings.conffile);
+ if (errno == ECONFINT) {
+ printf("main(): error getting 'alertautheddisconnect' from configuration file.\n");
+ exit(1);
+ }
+
// How many debug logs should we keep?
settings.debugkeep = getconfint("debugkeep", settings.conffile);
if (errno == ECONFINT) {
diff --git a/blabouncer.conf.example b/blabouncer.conf.example
index d77689c..2281806 100644
--- a/blabouncer.conf.example
+++ b/blabouncer.conf.example
@@ -108,3 +108,18 @@ debug = "2"
# Number of debug logs to keep
debugkeep = "5"
+
+# Send NOTICE to all other clients upon new client connections ("1" for yes or "0" for no)
+alertconnect = "1"
+
+# Send NOTICE to all other clients upon clients failing to authenticate ("1" for yes or "0" for no)
+alertauthfail = "1"
+
+# Send NOTICE to all other clients upon clients succesfully authenticating ("1" for yes or "0" for no)
+alertauthsuccess = "1"
+
+# Send NOTICE to all other clients upon unauthenticated client disconnections ("1" for yes or "0" for no)
+alertunautheddisconnect = "1"
+
+# Send NOTICE to all other clients upon authenticated client disconnections ("1" for yes or "0" for no)
+alertautheddisconnect = "1"
diff --git a/config.c b/config.c
index d7ad856..b2868b1 100644
--- a/config.c
+++ b/config.c
@@ -419,7 +419,22 @@ int createconfigfile(char *filename) {
"debug = \"2\"\n"
"\n"
"# Number of debug logs to keep\n"
- "debugkeep = \"5\"\n";
+ "debugkeep = \"5\"\n"
+ "\n"
+ "# Send NOTICE to all other clients upon new client connections (\"1\" for yes or \"0\" for no)\n"
+ "alertconnect = \"1\"\n"
+ "\n"
+ "# Send NOTICE to all other clients upon clients failing to authenticate (\"1\" for yes or \"0\" for no)\n"
+ "alertauthfail = \"1\"\n"
+ "\n"
+ "# Send NOTICE to all other clients upon clients succesfully authenticating (\"1\" for yes or \"0\" for no)\n"
+ "alertauthsuccess = \"1\"\n"
+ "\n"
+ "# Send NOTICE to all other clients upon unauthenticated client disconnections (\"1\" for yes or \"0\" for no)\n"
+ "alertunautheddisconnect = \"1\"\n"
+ "\n"
+ "# Send NOTICE to all other clients upon authenticated client disconnections (\"1\" for yes or \"0\" for no)\n"
+ "alertautheddisconnect = \"1\"\n";
// Write complete string to file
if ((fprintf(fp, "%s", string)) < 0) {
diff --git a/functions.c b/functions.c
index d0c0341..c3e9c94 100644
--- a/functions.c
+++ b/functions.c
@@ -633,13 +633,10 @@ int disconnectclient(int fd, struct client *clients, struct ircdstate *ircdstate
}
debugprint(DEBUG_SOME, "disconnectclient(): disconnecting client %s with fd '%d'\n", clients[clientindex].remoteip, fd);
- // Alert other clients about the disconnection (don't send yet, we haven't removed from the clients array yet)
- char alertmsg[MAXDATASIZE];
- if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: client %s has disconnected.", ircdstate->ircnick, clients[clientindex].remoteip)) {
- fprintf(stderr, "Error while preparing authentication failure NOTICE!\n");
- debugprint(DEBUG_CRIT, "Error while preparing authentication failure NOTICE!\n");
- alertmsg[0] = '\0';
- }
+ // Record some properties of the disconnecting client before we remove it from the clients array
+ int discauthed = clients[clientindex].authed;
+ char *discremoteip = strdup(clients[clientindex].remoteip);
+
// Remove the client from the clients array
for (int i = 0; i < MAXCLIENTS; i++) {
if (clients[i].fd == fd) {
@@ -670,20 +667,46 @@ int disconnectclient(int fd, struct client *clients, struct ircdstate *ircdstate
// Finish up with OpenSSL if using client TLS
SSL_free(clients[i].ssl);
}
+
// Close the socket
close(fd);
- // Now clients array is cleared, inform all other clients (source "0" since we trust this message)
- sendtoallclients(clients, alertmsg, 0, settings);
+
// If there are now no clients connected, record the time
if (numclients(clients) == 0) {
ircdstate->clientsnonetime = time(NULL);
}
+
+ // Now clients array is cleared, inform all other clients about the disconnection (if enabled)
+ if (!discauthed && settings->alertunautheddisconnect) {
+ // Unauthenticated client disconnection alerts enabled and disconnecting client is not authenticated
+ char alertmsg[MAXDATASIZE];
+ if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: unauthenticated client %s has disconnected.", ircdstate->ircnick, discremoteip)) {
+ fprintf(stderr, "Error while preparing unauthenticated client disconnection NOTICE!\n");
+ debugprint(DEBUG_CRIT, "Error while preparing unauthenticated client disconnection NOTICE!\n");
+ alertmsg[0] = '\0';
+ }
+ // (source "0" since we trust this message)
+ sendtoallclients(clients, alertmsg, 0, settings);
+ } else if (discauthed && settings->alertautheddisconnect) {
+ // Authenticated client disconnection alerts enabled and disconnecting client is authenticated
+ char alertmsg[MAXDATASIZE];
+ if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: authenticated client %s has disconnected.", ircdstate->ircnick, discremoteip)) {
+ fprintf(stderr, "Error while preparing authenticated client disconnection NOTICE!\n");
+ debugprint(DEBUG_CRIT, "Error while preparing authenticated client disconnection NOTICE!\n");
+ alertmsg[0] = '\0';
+ }
+ // (source "0" since we trust this message)
+ sendtoallclients(clients, alertmsg, 0, settings);
+ }
+
+ free(discremoteip);
return 1;
}
}
// If we got here, we didn't find and clear the client
// TODO - Do something with a failed return code
+ free(discremoteip);
return 0;
}
@@ -1231,6 +1254,51 @@ int rehash(struct settings *settings, char *failuremsg, SSL_CTX *ctx) {
configure_openssl_context(ctx, settings->certfile, settings->keyfile);
}
+ // Is alerting (NOTICE) upon a new connection enabled?
+ int oldalertconnect = settings->alertconnect;
+ settings->alertconnect = getconfint("alertconnect", settings->conffile);
+ if (errno == ECONFINT) {
+ settings->alertconnect = oldalertconnect;
+ strcpy(failuremsg, "error getting 'alertconnect' from configuration file");
+ return 0;
+ }
+
+ // Is alerting (NOTICE) upon a failed authentication enabled?
+ int oldalertauthfail = settings->alertauthfail;
+ settings->alertauthfail = getconfint("alertauthfail", settings->conffile);
+ if (errno == ECONFINT) {
+ settings->alertauthfail = oldalertauthfail;
+ strcpy(failuremsg, "error getting 'alertauthfail' from configuration file");
+ return 0;
+ }
+
+ // Is alerting (NOTICE) upon a successful authentication enabled?
+ int oldalertauthsuccess = settings->alertauthsuccess;
+ settings->alertauthsuccess = getconfint("alertauthsuccess", settings->conffile);
+ if (errno == ECONFINT) {
+ settings->alertauthsuccess = oldalertauthsuccess;
+ strcpy(failuremsg, "error getting 'alertauthsuccess' from configuration file");
+ return 0;
+ }
+
+ // Is alerting (NOTICE) upon unauthenticated client disconnections enabled?
+ int oldalertunautheddisconnect = settings->alertunautheddisconnect;
+ settings->alertunautheddisconnect = getconfint("alertunautheddisconnect", settings->conffile);
+ if (errno == ECONFINT) {
+ settings->alertunautheddisconnect = oldalertunautheddisconnect;
+ strcpy(failuremsg, "error getting 'alertunautheddisconnect' from configuration file");
+ return 0;
+ }
+
+ // Is alerting (NOTICE) upon authenticated client disconnections enabled?
+ int oldalertautheddisconnect = settings->alertautheddisconnect;
+ settings->alertautheddisconnect = getconfint("alertautheddisconnect", settings->conffile);
+ if (errno == ECONFINT) {
+ settings->alertautheddisconnect = oldalertautheddisconnect;
+ strcpy(failuremsg, "error getting 'alertautheddisconnect' from configuration file");
+ return 0;
+ }
+
// All is good, no failure message, return 1.
failuremsg[0] = '\0';
return 1;
diff --git a/message.c b/message.c
index 6f4c9dd..7e5497e 100644
--- a/message.c
+++ b/message.c
@@ -905,16 +905,18 @@ int processclientmessage(SSL *server_ssl, char *str, struct client *clients, int
// Found client in array, set to authenticated
clients[i].authed = 1;
debugprint(DEBUG_FULL, "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 %s has successfully authenticated.", ircdstate->ircnick,
- clients[clientindex].remoteip)) {
- fprintf(stderr, "Error while preparing authentication success NOTICE!\n");
- debugprint(DEBUG_CRIT, "Error while preparing authentication success NOTICE!\n");
- alertmsg[0] = '\0';
+ // Alert other clients about the successful authentication (if enabled)
+ if (settings->alertauthsuccess) {
+ char alertmsg[MAXDATASIZE];
+ if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: new client %s has successfully authenticated.", ircdstate->ircnick,
+ clients[clientindex].remoteip)) {
+ fprintf(stderr, "Error while preparing authentication success NOTICE!\n");
+ debugprint(DEBUG_CRIT, "Error while preparing authentication success NOTICE!\n");
+ alertmsg[0] = '\0';
+ }
+ // "except" the current fd - we can use this as "except/sourcefd" since we set them as authed just above
+ sendtoallclients(clients, alertmsg, sourcefd, settings);
}
- // "except" the current fd - we can use this as "except/sourcefd" since we set them as authed just above
- sendtoallclients(clients, alertmsg, sourcefd, settings);
}
}
} else {
@@ -924,15 +926,17 @@ int processclientmessage(SSL *server_ssl, char *str, struct client *clients, int
strncpy(remoteip, clients[clientindex].remoteip, INET6_ADDRSTRLEN);
debugprint(DEBUG_SOME, "Password rejected, disconnecting client %s with fd %d.\n", remoteip, sourcefd);
disconnectclient(sourcefd, clients, ircdstate, settings, clientcodes);
- // Alert other clients about the failed authentication
- char alertmsg[MAXDATASIZE];
- if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: new client %s failed to authenticate.", ircdstate->ircnick, remoteip)) {
- fprintf(stderr, "Error while preparing authentication failure NOTICE!\n");
- debugprint(DEBUG_CRIT, "Error while preparing authentication failure NOTICE!\n");
- alertmsg[0] = '\0';
- }
- // "except" 0 since we trust this message
- sendtoallclients(clients, alertmsg, 0, settings);
+ // Alert other clients about the failed authentication (if enabled)
+ if (settings->alertauthfail) {
+ char alertmsg[MAXDATASIZE];
+ if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: new client %s failed to authenticate.", ircdstate->ircnick, remoteip)) {
+ fprintf(stderr, "Error while preparing authentication failure NOTICE!\n");
+ debugprint(DEBUG_CRIT, "Error while preparing authentication failure NOTICE!\n");
+ alertmsg[0] = '\0';
+ }
+ // "except" 0 since we trust this message
+ sendtoallclients(clients, alertmsg, 0, settings);
+ }
}
return 1;
diff --git a/structures.h b/structures.h
index d070638..b2585bd 100644
--- a/structures.h
+++ b/structures.h
@@ -83,6 +83,11 @@ struct settings {
int debugkeep;
int background; // Whether or not we're running in the background (detached from the terminal as a daemon)
int replaydates; // Whether or not to include datestamps when replaying the replay log
+ int alertconnect;
+ int alertauthfail;
+ int alertauthsuccess;
+ int alertunautheddisconnect;
+ int alertautheddisconnect;
};
// Structure of a connected client, their socket/file descriptors, their authentication status, and their OpenSSL structures