From fbc97166a6e455f5cccf173abca3b9baedee4066 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Wed, 11 Jan 2023 01:28:32 +0000 Subject: [PATCH] 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 --- include/authproc.h | 4 +++- ircd/authproc.c | 42 +++++++++++++++++++++++++++++------------- ircd/s_user.c | 6 +++--- modules/m_stats.c | 6 +++--- 4 files changed, 38 insertions(+), 20 deletions(-) diff --git a/include/authproc.h b/include/authproc.h index 311cf948..66ad3964 100644 --- a/include/authproc.h +++ b/include/authproc.h @@ -30,9 +30,11 @@ #include "rb_dictionary.h" #include "client.h" -struct DNSBLEntryStats +struct DNSBLEntry { char *host; + char *reason; + char *filters; uint8_t iptype; unsigned int hits; }; diff --git a/ircd/authproc.c b/ircd/authproc.c index 9d252197..79fa4cb7 100644 --- a/ircd/authproc.c +++ b/ircd/authproc.c @@ -348,6 +348,15 @@ configure_authd(void) } else 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 @@ -584,7 +593,7 @@ void add_dnsbl_entry(const char *host, const char *reason, uint8_t iptype, rb_dlink_list *filters) { rb_dlink_node *ptr; - struct DNSBLEntryStats *stats = rb_malloc(sizeof(*stats)); + struct DNSBLEntry *entry = rb_malloc(sizeof(*entry)); char filterbuf[BUFSIZE] = "*"; 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) filterbuf[s - 1] = '\0'; - stats->host = rb_strdup(host); - stats->iptype = iptype; - stats->hits = 0; - rb_dictionary_add(dnsbl_stats, stats->host, stats); + entry->host = rb_strdup(host); + entry->reason = rb_strdup(reason); + entry->filters = rb_strdup(filterbuf); + 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); } @@ -622,12 +633,15 @@ add_dnsbl_entry(const char *host, const char *reason, uint8_t iptype, rb_dlink_l void del_dnsbl_entry(const char *host) { - struct DNSBLEntryStats *stats = rb_dictionary_retrieve(dnsbl_stats, host); - if(stats != NULL) + struct DNSBLEntry *entry = rb_dictionary_retrieve(dnsbl_stats, host); + + if(entry != NULL) { - rb_dictionary_delete(dnsbl_stats, host); - rb_free(stats->host); - rb_free(stats); + rb_dictionary_delete(dnsbl_stats, entry->host); + rb_free(entry->host); + rb_free(entry->reason); + rb_free(entry->filters); + rb_free(entry); } rb_helper_write(authd_helper, "O rbl_del %s", host); @@ -636,10 +650,12 @@ del_dnsbl_entry(const char *host) static void 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(stats); + rb_free(entry->host); + rb_free(entry->reason); + rb_free(entry->filters); + rb_free(entry); } /* Delete all the DNSBL entries. */ diff --git a/ircd/s_user.c b/ircd/s_user.c index 8a664624..48acff5b 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -215,12 +215,12 @@ authd_check(struct Client *client_p, struct Client *source_p) { case 'B': /* DNSBL */ { - struct DNSBLEntryStats *stats; + struct DNSBLEntry *entry; char *dnsbl_name = source_p->preClient->auth.data; if(dnsbl_stats != NULL) - if((stats = rb_dictionary_retrieve(dnsbl_stats, dnsbl_name)) != NULL) - stats->hits++; + if((entry = rb_dictionary_retrieve(dnsbl_stats, dnsbl_name)) != NULL) + entry->hits++; if(IsExemptKline(source_p) || IsConfExemptDNSBL(aconf)) { diff --git a/modules/m_stats.c b/modules/m_stats.c index 9530b26d..751c9446 100644 --- a/modules/m_stats.c +++ b/modules/m_stats.c @@ -727,16 +727,16 @@ static void stats_dnsbl(struct Client *source_p) { rb_dictionary_iter iter; - struct DNSBLEntryStats *stats; + struct DNSBLEntry *entry; if(dnsbl_stats == NULL) return; - RB_DICTIONARY_FOREACH(stats, &iter, dnsbl_stats) + RB_DICTIONARY_FOREACH(entry, &iter, dnsbl_stats) { /* use RPL_STATSDEBUG for now -- jilles */ sendto_one_numeric(source_p, RPL_STATSDEBUG, "n :%d %s", - stats->hits, (const char *)iter.cur->key); + entry->hits, entry->host); } }