X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_dnsbl.cpp;h=37819c05ce0b0b5239e6e0a34d24a3fd5cf72b73;hb=d4685e02b55229e0ca5068b839c87b5a80180f33;hp=89fecf6968aa15bc419c7f52c15d037aaa031d7e;hpb=c6e40d36b42a7ebf832c3a57d2816a47ee9c9a76;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp index 89fecf696..37819c05c 100644 --- a/src/modules/m_dnsbl.cpp +++ b/src/modules/m_dnsbl.cpp @@ -1,11 +1,16 @@ /* * InspIRCd -- Internet Relay Chat Daemon * + * Copyright (C) 2018-2020 Matt Schatz + * Copyright (C) 2018-2019 linuxdaemon + * Copyright (C) 2013, 2016-2020 Sadie Powell + * Copyright (C) 2013, 2015-2016 Adam + * Copyright (C) 2012-2016 Attila Molnar + * Copyright (C) 2012, 2018 Robby * Copyright (C) 2009-2010 Daniel De Graaf - * Copyright (C) 2006-2008 Robin Burchell - * Copyright (C) 2007 Craig Edwards - * Copyright (C) 2006-2007 Dennis Friis - * Copyright (C) 2007 John Brooks + * Copyright (C) 2007, 2010 Craig Edwards + * Copyright (C) 2007 Dennis Friis + * Copyright (C) 2006-2009 Robin Burchell * * This file is part of InspIRCd. InspIRCd is free software: you can * redistribute it and/or modify it under the terms of the GNU General Public @@ -47,15 +52,21 @@ class DNSBLConfEntry : public refcountbase */ class DNSBLResolver : public DNS::Request { + private: + irc::sockets::sockaddrs theirsa; std::string theiruid; LocalStringExt& nameExt; LocalIntExt& countExt; reference ConfEntry; public: - DNSBLResolver(DNS::Manager *mgr, Module *me, LocalStringExt& match, LocalIntExt& ctr, const std::string &hostname, LocalUser* u, reference conf) - : DNS::Request(mgr, me, hostname, DNS::QUERY_A, true), theiruid(u->uuid), nameExt(match), countExt(ctr), ConfEntry(conf) + : DNS::Request(mgr, me, hostname, DNS::QUERY_A, true) + , theirsa(u->client_sa) + , theiruid(u->uuid) + , nameExt(match) + , countExt(ctr) + , ConfEntry(conf) { } @@ -63,8 +74,8 @@ class DNSBLResolver : public DNS::Request void OnLookupComplete(const DNS::Query *r) CXX11_OVERRIDE { /* Check the user still exists */ - LocalUser* them = (LocalUser*)ServerInstance->FindUUID(theiruid); - if (!them) + 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); @@ -147,9 +158,9 @@ class DNSBLResolver : public DNS::Request "*", them->GetIPString()); if (ServerInstance->XLines->AddLine(kl,NULL)) { - std::string timestr = InspIRCd::TimeString(kl->expiry); - ServerInstance->SNO->WriteGlobalSno('x',"K:line added due to DNSBL match on *@%s to expire on %s: %s", - them->GetIPString().c_str(), timestr.c_str(), reason.c_str()); + ServerInstance->SNO->WriteToSnoMask('x', "K-line added due to DNSBL match on *@%s to expire in %s (on %s): %s", + them->GetIPString().c_str(), InspIRCd::DurationString(kl->duration).c_str(), + InspIRCd::TimeString(kl->expiry).c_str(), reason.c_str()); ServerInstance->XLines->ApplyLines(); } else @@ -165,9 +176,9 @@ class DNSBLResolver : public DNS::Request "*", them->GetIPString()); if (ServerInstance->XLines->AddLine(gl,NULL)) { - std::string timestr = InspIRCd::TimeString(gl->expiry); - ServerInstance->SNO->WriteGlobalSno('x',"G:line added due to DNSBL match on *@%s to expire on %s: %s", - them->GetIPString().c_str(), timestr.c_str(), reason.c_str()); + ServerInstance->SNO->WriteToSnoMask('x', "G-line added due to DNSBL match on *@%s to expire in %s (on %s): %s", + them->GetIPString().c_str(), InspIRCd::DurationString(gl->duration).c_str(), + InspIRCd::TimeString(gl->expiry).c_str(), reason.c_str()); ServerInstance->XLines->ApplyLines(); } else @@ -183,9 +194,9 @@ class DNSBLResolver : public DNS::Request them->GetIPString()); if (ServerInstance->XLines->AddLine(zl,NULL)) { - std::string timestr = InspIRCd::TimeString(zl->expiry); - ServerInstance->SNO->WriteGlobalSno('x',"Z:line added due to DNSBL match on %s to expire on %s: %s", - them->GetIPString().c_str(), timestr.c_str(), reason.c_str()); + ServerInstance->SNO->WriteToSnoMask('x', "Z-line added due to DNSBL match on %s to expire in %s (on %s): %s", + them->GetIPString().c_str(), InspIRCd::DurationString(zl->duration).c_str(), + InspIRCd::TimeString(zl->expiry).c_str(), reason.c_str()); ServerInstance->XLines->ApplyLines(); } else @@ -200,7 +211,8 @@ class DNSBLResolver : public DNS::Request break; } - ServerInstance->SNO->WriteGlobalSno('d', "Connecting user %s%s detected as being on a DNS blacklist (%s) with result %d", them->nick.empty() ? "" : "", them->GetFullRealHost().c_str(), ConfEntry->domain.c_str(), (ConfEntry->type==DNSBLConfEntry::A_BITMASK) ? bitmask : record); + 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); } else ConfEntry->stats_misses++; @@ -208,8 +220,8 @@ class DNSBLResolver : public DNS::Request void OnError(const DNS::Query *q) CXX11_OVERRIDE { - LocalUser* them = (LocalUser*)ServerInstance->FindUUID(theiruid); - if (!them) + LocalUser* them = IS_LOCAL(ServerInstance->FindUUID(theiruid)); + if (!them || them->client_sa != theirsa) return; int i = countExt.get(them); @@ -217,13 +229,21 @@ class DNSBLResolver : public DNS::Request countExt.set(them, i - 1); if (q->error == DNS::ERROR_NO_RECORDS || q->error == DNS::ERROR_DOMAIN_NOT_FOUND) + { ConfEntry->stats_misses++; + 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()); } }; +typedef std::vector > DNSBLConfList; + class ModuleDNSBL : public Module, public Stats::EventListener { - std::vector > DNSBLConfEntries; + DNSBLConfList DNSBLConfEntries; dynamic_reference DNS; LocalStringExt nameExt; LocalIntExt countExt; @@ -233,17 +253,16 @@ class ModuleDNSBL : public Module, public Stats::EventListener */ DNSBLConfEntry::EnumBanaction str2banaction(const std::string &action) { - if(action.compare("KILL")==0) + if (stdalgo::string::equalsci(action, "kill")) return DNSBLConfEntry::I_KILL; - if(action.compare("KLINE")==0) + if (stdalgo::string::equalsci(action, "kline")) return DNSBLConfEntry::I_KLINE; - if(action.compare("ZLINE")==0) + if (stdalgo::string::equalsci(action, "zline")) return DNSBLConfEntry::I_ZLINE; - if(action.compare("GLINE")==0) + if (stdalgo::string::equalsci(action, "gline")) return DNSBLConfEntry::I_GLINE; - if(action.compare("MARK")==0) + if (stdalgo::string::equalsci(action, "mark")) return DNSBLConfEntry::I_MARK; - return DNSBLConfEntry::I_UNKNOWN; } public: @@ -260,16 +279,22 @@ class ModuleDNSBL : public Module, public Stats::EventListener ServerInstance->SNO->EnableSnomask('d', "DNSBL"); } + void Prioritize() CXX11_OVERRIDE + { + Module* corexline = ServerInstance->Modules->Find("core_xline"); + ServerInstance->Modules->SetPriority(this, I_OnSetUserIP, PRIORITY_AFTER, corexline); + } + Version GetVersion() CXX11_OVERRIDE { - return Version("Provides handling of DNS blacklists", VF_VENDOR); + return Version("Allows the server administrator to check the IP address of connecting users against a DNSBL.", VF_VENDOR); } /** Fill our conf vector with data */ void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE { - DNSBLConfEntries.clear(); + DNSBLConfList newentries; ConfigTagList dnsbls = ServerInstance->Config->ConfTags("dnsbl"); for(ConfigIter i = dnsbls.first; i != dnsbls.second; ++i) @@ -280,7 +305,7 @@ class ModuleDNSBL : public Module, public Stats::EventListener e->name = tag->getString("name"); e->ident = tag->getString("ident"); e->host = tag->getString("host"); - e->reason = tag->getString("reason"); + e->reason = tag->getString("reason", "Your IP has been blacklisted.", 1); e->domain = tag->getString("domain"); if (stdalgo::string::equalsci(tag->getString("type"), "bitmask")) @@ -306,42 +331,33 @@ class ModuleDNSBL : public Module, public Stats::EventListener /* yeah, logic here is a little messy */ if ((e->bitmask <= 0) && (DNSBLConfEntry::A_BITMASK == e->type)) { - std::string location = tag->getTagLocation(); - ServerInstance->SNO->WriteGlobalSno('d', "DNSBL(%s): invalid bitmask", location.c_str()); + throw ModuleException("Invalid at " + tag->getTagLocation()); } else if (e->name.empty()) { - std::string location = tag->getTagLocation(); - ServerInstance->SNO->WriteGlobalSno('d', "DNSBL(%s): Invalid name", location.c_str()); + throw ModuleException("Empty at " + tag->getTagLocation()); } else if (e->domain.empty()) { - std::string location = tag->getTagLocation(); - ServerInstance->SNO->WriteGlobalSno('d', "DNSBL(%s): Invalid domain", location.c_str()); + throw ModuleException("Empty at " + tag->getTagLocation()); } else if (e->banaction == DNSBLConfEntry::I_UNKNOWN) { - std::string location = tag->getTagLocation(); - ServerInstance->SNO->WriteGlobalSno('d', "DNSBL(%s): Invalid banaction", location.c_str()); + throw ModuleException("Unknown at " + tag->getTagLocation()); } else { - if (e->reason.empty()) - { - std::string location = tag->getTagLocation(); - ServerInstance->SNO->WriteGlobalSno('d', "DNSBL(%s): empty reason, using defaults", location.c_str()); - e->reason = "Your IP has been blacklisted."; - } - /* add it, all is ok */ - DNSBLConfEntries.push_back(e); + newentries.push_back(e); } } + + DNSBLConfEntries.swap(newentries); } 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. @@ -354,7 +370,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) @@ -377,6 +396,7 @@ class ModuleDNSBL : public Module, public Stats::EventListener reversedip.push_back(*it); reversedip.push_back('.'); } + reversedip.erase(reversedip.length() - 1, 1); } else return; @@ -413,11 +433,23 @@ class ModuleDNSBL : public Module, public Stats::EventListener std::string dnsbl; if (!myclass->config->readString("dnsbl", dnsbl)) return MOD_RES_PASSTHRU; + std::string* match = nameExt.get(user); - std::string myname = match ? *match : ""; - if (dnsbl == myname) - return MOD_RES_PASSTHRU; - return MOD_RES_DENY; + if (!match) + { + ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "The %s connect class is not suitable as it requires a DNSBL mark", + myclass->GetName().c_str()); + return MOD_RES_DENY; + } + + if (!InspIRCd::Match(*match, dnsbl)) + { + ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "The %s connect class is not suitable as the DNSBL mark (%s) does not match %s", + myclass->GetName().c_str(), match->c_str(), dnsbl.c_str()); + return MOD_RES_DENY; + } + + return MOD_RES_PASSTHRU; } ModResult OnCheckReady(LocalUser *user) CXX11_OVERRIDE