From f55160af3f25fff17d3af4dde50a606c2c78f79b Mon Sep 17 00:00:00 2001 From: Luke Bratch Date: Sat, 9 Nov 2024 23:50:46 +0000 Subject: Make NOTICE alerts about client (dis)connection and authentication events optional. New configuration options added: - alertconnect - alertauthfail - alertauthsuccess - alertunautheddisconnect - alertautheddisconnect --- functions.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 9 deletions(-) (limited to 'functions.c') 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; -- cgit v1.2.3