X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Fmod-blacklist.c;h=61d0adf5072f973d10065af23ae4bffa273863ce;hb=HEAD;hp=7ae95260cced1326a9eea7244f3d13d807082508;hpb=94ff95155752d6dafa5628bb973ebae8df3558fc;p=srvx.git diff --git a/src/mod-blacklist.c b/src/mod-blacklist.c index 7ae9526..61d0adf 100644 --- a/src/mod-blacklist.c +++ b/src/mod-blacklist.c @@ -32,6 +32,7 @@ struct dnsbl_zone { const char *reason; unsigned int duration; unsigned int mask; + unsigned int debug : 1; char zone[1]; }; @@ -46,9 +47,17 @@ static dict_t blacklist_hosts; /* maps IPs or hostnames to reasons from blacklis static dict_t blacklist_reasons; /* maps strings to themselves (poor man's data sharing) */ static struct { + struct userNode *debug_bot; + struct chanNode *debug_channel; unsigned long gline_duration; } conf; +#if defined(GCC_VARMACROS) +# define blacklist_debug(ARGS...) do { if (conf.debug_bot && conf.debug_channel) send_channel_message(conf.debug_channel, conf.debug_bot, ARGS); } while (0) +#elif defined(C99_VARMACROS) +# define blacklist_debug(...) do { if (conf.debug_bot && conf.debug_channel) send_channel_message(conf.debug_channel, conf.debug_bot, __VA_ARGS__); } while (0) +#endif + static void do_expandos(char *output, unsigned int out_len, const char *input, ...) { @@ -68,7 +77,7 @@ do_expandos(char *output, unsigned int out_len, const char *input, ...) dlen = strlen(datum); for (found = output; (found = strstr(output, key)) != NULL; found += dlen) { rlen = strlen(found + klen); - if ((dlen > klen) && (found + dlen + rlen - output > out_len)) + if ((dlen > klen) && ((unsigned)(found + dlen + rlen - output) > out_len)) rlen = output + out_len - found - dlen; memmove(found + dlen, found + klen, rlen); memcpy(found, datum, dlen + 1); @@ -133,19 +142,26 @@ dnsbl_hit(struct sar_request *req, struct dns_header *hdr, struct dns_rr *rr, un message = "client is blacklisted"; } - /* Expand elements of the message as necessary. */ - do_expandos(reason, sizeof(reason), message, "%txt%", (txt ? txt : "(no-txt)"), "%ip%", data->client_ip, NULL); + /* Prepend "AUTO " prefix so the g-lined are put in a different snomask */ + strcpy(reason, "AUTO "); - /* Now generate the G-line. */ - target[0] = '*'; - target[1] = '@'; - strcpy(target + 2, data->client_ip); - gline_add(self->name, target, zone->duration, reason, now, now, 1); + /* Expand elements of the message as necessary. */ + do_expandos(reason + 5, sizeof(reason) - 5, message, "%txt%", (txt ? txt : "(no-txt)"), "%ip%", data->client_ip, NULL); + + if (zone->debug) { + blacklist_debug("DNSBL match: [%s] %s (%s)", zone->zone, data->client_ip, reason); + } else { + /* Now generate the G-line. */ + target[0] = '*'; + target[1] = '@'; + strcpy(target + 2, data->client_ip); + gline_add(self->name, target, zone->duration, reason, now, now, 0, 1); + } } free(txt); } -static int +static void blacklist_check_user(struct userNode *user) { static const char *hexdigits = "0123456789abcdef"; @@ -157,9 +173,13 @@ blacklist_check_user(struct userNode *user) char ip[IRC_NTOP_MAX_SIZE]; char dnsbl_target[128]; + /* Users added during burst should not be checked. */ + if (user->uplink->burst) + return; + /* Users with bogus IPs are probably service bots. */ if (!irc_in_addr_is_valid(user->ip)) - return 0; + return; /* Check local file-based blacklist. */ irc_ntop(ip, sizeof(ip), &user->ip); @@ -173,7 +193,8 @@ blacklist_check_user(struct userNode *user) target[0] = '*'; target[1] = '@'; strcpy(target + 2, host); - gline_add(self->name, target, conf.gline_duration, reason, now, now, 1); + /* We do not prepend AUTO here so it can be done in the blacklist file. */ + gline_add(self->name, target, conf.gline_duration, reason, now, now, 0, 1); } /* Figure out the base part of a DNS blacklist hostname. */ @@ -188,7 +209,7 @@ blacklist_check_user(struct userNode *user) } dnsbl_len = 48; } else { - return 0; + return; } /* Start a lookup for the appropriate hostname in each DNSBL. */ @@ -203,10 +224,9 @@ blacklist_check_user(struct userNode *user) if (req) { data = (struct dnsbl_data*)(req + 1); strcpy(data->client_ip, ip); - strcpy(data->zone_name, zone); + strcpy(data->zone_name, zone); } } - return 0; } static void @@ -278,7 +298,7 @@ blacklist_conf_read(void) dict_delete(blacklist_zones); blacklist_zones = dict_new(); - dict_set_free_data(blacklist_zones, free); + dict_set_free_data(blacklist_zones, dnsbl_zone_free); dict_delete(blacklist_hosts); blacklist_hosts = dict_new(); @@ -286,12 +306,27 @@ blacklist_conf_read(void) dict_delete(blacklist_reasons); blacklist_reasons = dict_new(); - dict_set_free_keys(blacklist_reasons, dnsbl_zone_free); + dict_set_free_keys(blacklist_reasons, free); node = conf_get_data("modules/blacklist", RECDB_OBJECT); if (node == NULL) return; + str1 = database_get_data(node, "debug_bot", RECDB_QSTRING); + if (str1) + conf.debug_bot = GetUserH(str1); + + str1 = database_get_data(node, "debug_channel", RECDB_QSTRING); + if (conf.debug_bot && str1) { + str2 = database_get_data(node, "debug_channel_modes", RECDB_QSTRING); + if (!str2) + str2 = "+tinms"; + conf.debug_channel = AddChannel(str1, now, str2, NULL); + AddChannelUser(conf.debug_bot, conf.debug_channel)->modes |= MODE_CHANOP; + } else { + conf.debug_channel = NULL; + } + str1 = database_get_data(node, "file", RECDB_QSTRING); str2 = database_get_data(node, "file_reason", RECDB_QSTRING); blacklist_load_file(str1, str2); @@ -324,6 +359,8 @@ blacklist_conf_read(void) zone->duration = str1 ? ParseInterval(str1) : 3600; str1 = database_get_data(dnsbl, "mask", RECDB_QSTRING); zone->mask = str1 ? strtoul(str1, NULL, 0) : ~0u; + str1 = database_get_data(dnsbl, "debug", RECDB_QSTRING); + zone->debug = str1 ? enabled_string(str1) : 0; zone->reasons.used = 0; zone->reasons.size = 0; zone->reasons.list = NULL;