X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_dnsbl.cpp;h=57a780ff2d1685c53fa13154ee6f679bec48b934;hb=7cfeb971666b3a6709fe61bd01478697e6433f50;hp=4873e23220929920c42556d1edbd02464f83438e;hpb=116244f190e8146395d40fb5a43af6b9bb1f6d1f;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp index 4873e2322..57a780ff2 100644 --- a/src/modules/m_dnsbl.cpp +++ b/src/modules/m_dnsbl.cpp @@ -3,7 +3,7 @@ * * Copyright (C) 2018-2020 Matt Schatz * Copyright (C) 2018-2019 linuxdaemon - * Copyright (C) 2013, 2016-2020 Sadie Powell + * Copyright (C) 2013, 2017-2021 Sadie Powell * Copyright (C) 2013, 2015-2016 Adam * Copyright (C) 2012-2016 Attila Molnar * Copyright (C) 2012, 2018 Robby @@ -43,8 +43,16 @@ class DNSBLConfEntry : public refcountbase unsigned long duration; unsigned int bitmask; unsigned char records[256]; - unsigned long stats_hits, stats_misses; - DNSBLConfEntry(): type(A_BITMASK),duration(86400),bitmask(0),stats_hits(0), stats_misses(0) {} + unsigned long stats_hits, stats_misses, stats_errors; + DNSBLConfEntry() + : type(A_BITMASK) + , duration(86400) + , bitmask(0) + , stats_hits(0) + , stats_misses(0) + , stats_errors(0) + { + } }; @@ -76,16 +84,7 @@ class DNSBLResolver : public DNS::Request /* Check the user still exists */ LocalUser* them = IS_LOCAL(ServerInstance->FindUUID(theiruid)); if (!them || them->client_sa != theirsa) - return; - - const DNS::ResourceRecord* const ans_record = r->FindAnswerOfType(DNS::QUERY_A); - if (!ans_record) - return; - - // All replies should be in 127.0.0.0/8 - if (ans_record->rdata.compare(0, 4, "127.") != 0) { - ServerInstance->SNO->WriteGlobalSno('d', "DNSBL: %s returned address outside of acceptable subnet 127.0.0.0/8: %s", ConfEntry->domain.c_str(), ans_record->rdata.c_str()); ConfEntry->stats_misses++; return; } @@ -94,25 +93,51 @@ class DNSBLResolver : public DNS::Request if (i) countExt.set(them, i - 1); - // Now we calculate the bitmask: 256*(256*(256*a+b)+c)+d + // The DNSBL reply must contain an A result. + const DNS::ResourceRecord* const ans_record = r->FindAnswerOfType(DNS::QUERY_A); + if (!ans_record) + { + ConfEntry->stats_errors++; + ServerInstance->SNO->WriteGlobalSno('d', "%s returned an result with no IPv4 address.", + ConfEntry->name.c_str()); + return; + } - unsigned int bitmask = 0, record = 0; - bool match = false; + // The DNSBL reply must be a valid IPv4 address. in_addr resultip; + if (inet_pton(AF_INET, ans_record->rdata.c_str(), &resultip) != 1) + { + ConfEntry->stats_errors++; + ServerInstance->SNO->WriteGlobalSno('d', "%s returned an invalid IPv4 address: %s", + ConfEntry->name.c_str(), ans_record->rdata.c_str()); + return; + } - inet_pton(AF_INET, ans_record->rdata.c_str(), &resultip); + // The DNSBL reply should be in the 127.0.0.0/8 range. + if ((resultip.s_addr & 0xFF) != 127) + { + ConfEntry->stats_errors++; + ServerInstance->SNO->WriteGlobalSno('d', "%s returned an IPv4 address which is outside of the 127.0.0.0/8 subnet: %s", + ConfEntry->name.c_str(), ans_record->rdata.c_str()); + return; + } + bool match = false; + unsigned int result = 0; switch (ConfEntry->type) { case DNSBLConfEntry::A_BITMASK: - bitmask = resultip.s_addr >> 24; /* Last octet (network byte order) */ - bitmask &= ConfEntry->bitmask; - match = (bitmask != 0); - break; + { + result = (resultip.s_addr >> 24) & ConfEntry->bitmask; + match = (result != 0); + break; + } case DNSBLConfEntry::A_RECORD: - record = resultip.s_addr >> 24; /* Last octet */ - match = (ConfEntry->records[record] == 1); - break; + { + result = resultip.s_addr >> 24; + match = (ConfEntry->records[result] == 1); + break; + } } if (match) @@ -212,7 +237,7 @@ class DNSBLResolver : public DNS::Request } ServerInstance->SNO->WriteGlobalSno('d', "Connecting user %s (%s) detected as being on the '%s' DNS blacklist with result %d", - them->GetFullRealHost().c_str(), them->GetIPString().c_str(), ConfEntry->name.c_str(), (ConfEntry->type==DNSBLConfEntry::A_BITMASK) ? bitmask : record); + them->GetFullRealHost().c_str(), them->GetIPString().c_str(), ConfEntry->name.c_str(), result); } else ConfEntry->stats_misses++; @@ -220,6 +245,20 @@ class DNSBLResolver : public DNS::Request void OnError(const DNS::Query *q) CXX11_OVERRIDE { + bool is_miss = true; + switch (q->error) + { + case DNS::ERROR_NO_RECORDS: + case DNS::ERROR_DOMAIN_NOT_FOUND: + ConfEntry->stats_misses++; + break; + + default: + ConfEntry->stats_errors++; + is_miss = false; + break; + } + LocalUser* them = IS_LOCAL(ServerInstance->FindUUID(theiruid)); if (!them || them->client_sa != theirsa) return; @@ -228,11 +267,8 @@ class DNSBLResolver : public DNS::Request if (i) countExt.set(them, i - 1); - if (q->error == DNS::ERROR_NO_RECORDS || q->error == DNS::ERROR_DOMAIN_NOT_FOUND) - { - ConfEntry->stats_misses++; + if (is_miss) return; - } ServerInstance->SNO->WriteGlobalSno('d', "An error occurred whilst checking whether %s (%s) is on the '%s' DNS blacklist: %s", them->GetFullRealHost().c_str(), them->GetIPString().c_str(), ConfEntry->name.c_str(), this->manager->GetErrorStr(q->error).c_str()); @@ -357,7 +393,7 @@ class ModuleDNSBL : public Module, public Stats::EventListener void OnSetUserIP(LocalUser* user) CXX11_OVERRIDE { - if ((user->exempt) || !DNS) + if (user->exempt || user->quitting || !DNS) return; // Clients can't be in a DNSBL if they aren't connected via IPv4 or IPv6. @@ -370,7 +406,10 @@ class ModuleDNSBL : public Module, public Stats::EventListener return; } else + { ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "User has no connect class in OnSetUserIP"); + return; + } std::string reversedip; if (user->client_sa.family() == AF_INET) @@ -461,20 +500,22 @@ class ModuleDNSBL : public Module, public Stats::EventListener if (stats.GetSymbol() != 'd') return MOD_RES_PASSTHRU; - unsigned long total_hits = 0, total_misses = 0; - + unsigned long total_hits = 0; + unsigned long total_misses = 0; + unsigned long total_errors = 0; for (std::vector >::const_iterator i = DNSBLConfEntries.begin(); i != DNSBLConfEntries.end(); ++i) { total_hits += (*i)->stats_hits; total_misses += (*i)->stats_misses; + total_errors += (*i)->stats_errors; - stats.AddRow(304, "DNSBLSTATS DNSbl \"" + (*i)->name + "\" had " + - ConvToStr((*i)->stats_hits) + " hits and " + ConvToStr((*i)->stats_misses) + " misses"); + stats.AddRow(304, InspIRCd::Format("DNSBLSTATS \"%s\" had %lu hits, %lu misses, and %lu errors", + (*i)->name.c_str(), (*i)->stats_hits, (*i)->stats_misses, (*i)->stats_errors)); } stats.AddRow(304, "DNSBLSTATS Total hits: " + ConvToStr(total_hits)); stats.AddRow(304, "DNSBLSTATS Total misses: " + ConvToStr(total_misses)); - + stats.AddRow(304, "DNSBLSTATS Total errors: " + ConvToStr(total_errors)); return MOD_RES_PASSTHRU; } };