authd: fix crash/restart breaking DNSBL lookups (#394)

authd child processes are only told about configured DNSBLs when the
configuration is being parsed.

This is bad, because when authd crashes or is killed, IRCd will restart
it, but will not tell it about any configured DNSBLs until IRCd is next
rehashed.

We already have a dictionary that stores configured DNSBLs (for hit
statistics for `STATS n'), so store the additional needed fields in
that structure, and loop over that dictionary's entries when authd is
restarted, sending the fields just as if the configuration were being
reloaded.

Reported-By: @Unit193
This commit is contained in:
Aaron Jones 2023-01-11 01:28:32 +00:00 committed by GitHub
parent 32d37a1660
commit fbc97166a6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 20 deletions

View file

@ -30,9 +30,11 @@
#include "rb_dictionary.h" #include "rb_dictionary.h"
#include "client.h" #include "client.h"
struct DNSBLEntryStats struct DNSBLEntry
{ {
char *host; char *host;
char *reason;
char *filters;
uint8_t iptype; uint8_t iptype;
unsigned int hits; unsigned int hits;
}; };

View file

@ -348,6 +348,15 @@ configure_authd(void)
} }
else else
opm_check_enable(false); opm_check_enable(false);
/* Configure DNSBLs */
rb_dictionary_iter iter;
struct DNSBLEntry *entry;
RB_DICTIONARY_FOREACH(entry, &iter, dnsbl_stats)
{
rb_helper_write(authd_helper, "O rbl %s %hhu %s :%s", entry->host,
entry->iptype, entry->filters, entry->reason);
}
} }
static void static void
@ -584,7 +593,7 @@ void
add_dnsbl_entry(const char *host, const char *reason, uint8_t iptype, rb_dlink_list *filters) add_dnsbl_entry(const char *host, const char *reason, uint8_t iptype, rb_dlink_list *filters)
{ {
rb_dlink_node *ptr; rb_dlink_node *ptr;
struct DNSBLEntryStats *stats = rb_malloc(sizeof(*stats)); struct DNSBLEntry *entry = rb_malloc(sizeof(*entry));
char filterbuf[BUFSIZE] = "*"; char filterbuf[BUFSIZE] = "*";
size_t s = 0; size_t s = 0;
@ -610,11 +619,13 @@ add_dnsbl_entry(const char *host, const char *reason, uint8_t iptype, rb_dlink_l
if(s) if(s)
filterbuf[s - 1] = '\0'; filterbuf[s - 1] = '\0';
stats->host = rb_strdup(host); entry->host = rb_strdup(host);
stats->iptype = iptype; entry->reason = rb_strdup(reason);
stats->hits = 0; entry->filters = rb_strdup(filterbuf);
rb_dictionary_add(dnsbl_stats, stats->host, stats); entry->iptype = iptype;
entry->hits = 0;
rb_dictionary_add(dnsbl_stats, entry->host, entry);
rb_helper_write(authd_helper, "O rbl %s %hhu %s :%s", host, iptype, filterbuf, reason); rb_helper_write(authd_helper, "O rbl %s %hhu %s :%s", host, iptype, filterbuf, reason);
} }
@ -622,12 +633,15 @@ add_dnsbl_entry(const char *host, const char *reason, uint8_t iptype, rb_dlink_l
void void
del_dnsbl_entry(const char *host) del_dnsbl_entry(const char *host)
{ {
struct DNSBLEntryStats *stats = rb_dictionary_retrieve(dnsbl_stats, host); struct DNSBLEntry *entry = rb_dictionary_retrieve(dnsbl_stats, host);
if(stats != NULL)
if(entry != NULL)
{ {
rb_dictionary_delete(dnsbl_stats, host); rb_dictionary_delete(dnsbl_stats, entry->host);
rb_free(stats->host); rb_free(entry->host);
rb_free(stats); rb_free(entry->reason);
rb_free(entry->filters);
rb_free(entry);
} }
rb_helper_write(authd_helper, "O rbl_del %s", host); rb_helper_write(authd_helper, "O rbl_del %s", host);
@ -636,10 +650,12 @@ del_dnsbl_entry(const char *host)
static void static void
dnsbl_delete_elem(rb_dictionary_element *delem, void *unused) dnsbl_delete_elem(rb_dictionary_element *delem, void *unused)
{ {
struct DNSBLEntryStats *stats = delem->data; struct DNSBLEntry *entry = delem->data;
rb_free(stats->host); rb_free(entry->host);
rb_free(stats); rb_free(entry->reason);
rb_free(entry->filters);
rb_free(entry);
} }
/* Delete all the DNSBL entries. */ /* Delete all the DNSBL entries. */

View file

@ -215,12 +215,12 @@ authd_check(struct Client *client_p, struct Client *source_p)
{ {
case 'B': /* DNSBL */ case 'B': /* DNSBL */
{ {
struct DNSBLEntryStats *stats; struct DNSBLEntry *entry;
char *dnsbl_name = source_p->preClient->auth.data; char *dnsbl_name = source_p->preClient->auth.data;
if(dnsbl_stats != NULL) if(dnsbl_stats != NULL)
if((stats = rb_dictionary_retrieve(dnsbl_stats, dnsbl_name)) != NULL) if((entry = rb_dictionary_retrieve(dnsbl_stats, dnsbl_name)) != NULL)
stats->hits++; entry->hits++;
if(IsExemptKline(source_p) || IsConfExemptDNSBL(aconf)) if(IsExemptKline(source_p) || IsConfExemptDNSBL(aconf))
{ {

View file

@ -727,16 +727,16 @@ static void
stats_dnsbl(struct Client *source_p) stats_dnsbl(struct Client *source_p)
{ {
rb_dictionary_iter iter; rb_dictionary_iter iter;
struct DNSBLEntryStats *stats; struct DNSBLEntry *entry;
if(dnsbl_stats == NULL) if(dnsbl_stats == NULL)
return; return;
RB_DICTIONARY_FOREACH(stats, &iter, dnsbl_stats) RB_DICTIONARY_FOREACH(entry, &iter, dnsbl_stats)
{ {
/* use RPL_STATSDEBUG for now -- jilles */ /* use RPL_STATSDEBUG for now -- jilles */
sendto_one_numeric(source_p, RPL_STATSDEBUG, "n :%d %s", sendto_one_numeric(source_p, RPL_STATSDEBUG, "n :%d %s",
stats->hits, (const char *)iter.cur->key); entry->hits, entry->host);
} }
} }