X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_dnsbl.cpp;h=d07b268f7bf4a4db4f9bdc48318fba97e7353c82;hb=d556a4f8740b65e635ff7d2b976faaedbdac51d4;hp=4c217fc3e10772e9474372826a731d8f04e58515;hpb=731511fe154052890633a207b7f2aabe889ab40d;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp index 4c217fc3e..d07b268f7 100644 --- a/src/modules/m_dnsbl.cpp +++ b/src/modules/m_dnsbl.cpp @@ -1,18 +1,30 @@ -/* - * Formerly written and maintained by satmd. - * This version written and maintained by w00t. +/* +------------------------------------+ + * | Inspire Internet Relay Chat Daemon | + * +------------------------------------+ + * + * InspIRCd: (C) 2002-2007 InspIRCd Development Team + * See: http://www.inspircd.org/wiki/index.php/Credits + * + * This program is free but copyrighted software; see + * the file COPYING for details. + * + * --------------------------------------------------- */ -#include -#include -#include -#include -#include + #include "inspircd.h" +#include "xline.h" #include "dns.h" #include "users.h" #include "channels.h" #include "modules.h" +#ifndef WINDOWS +#include +#include +#include +#include +#endif + /* $ModDesc: Provides handling of DNS blacklists */ /* Class holding data for a single entry */ @@ -24,7 +36,9 @@ class DNSBLConfEntry EnumBanaction banaction; long duration; int bitmask; - DNSBLConfEntry(): duration(86400),bitmask(0) {} + unsigned long stats_hits, stats_misses; + DNSBLConfEntry(): duration(86400),bitmask(0),stats_hits(0), stats_misses(0) {} + ~DNSBLConfEntry() { } }; @@ -36,82 +50,81 @@ class DNSBLResolver : public Resolver userrec* them; DNSBLConfEntry *ConfEntry; - public: - DNSBLResolver(Module *me, InspIRCd *ServerInstance, const std::string &hostname, userrec* u, int userfd, DNSBLConfEntry *conf) - : Resolver(ServerInstance, hostname, DNS_QUERY_A, me) + public: + + DNSBLResolver(Module *me, InspIRCd *ServerInstance, const std::string &hostname, userrec* u, int userfd, DNSBLConfEntry *conf, bool &cached) + : Resolver(ServerInstance, hostname, DNS_QUERY_A, cached, me) { theirfd = userfd; them = u; ConfEntry = conf; } - virtual void OnLookupComplete(const std::string &result) + virtual void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached) { /* Check the user still exists */ if ((them) && (them == ServerInstance->SE->GetRef(theirfd))) { - ServerInstance->Log(DEBUG, "m_dnsbl: %s got a result from dnsbl %s", them->nick, ConfEntry->name.c_str()); - // Now we calculate the bitmask: 256*(256*(256*a+b)+c)+d if(result.length()) { - unsigned int bitmask=0; - unsigned int octetpos=0; - std::string tmp = result; - - while(tmp.length()>0) - { - std::string octet; - unsigned int lastdot = tmp.rfind("."); - - if (lastdot == std::string::npos) - { - octet=tmp; - tmp.clear(); - } - else - { - octet=tmp.substr(lastdot+1,tmp.length()-lastdot+1); - tmp.resize(lastdot); - } + unsigned int bitmask = 0; + bool show = false; + in_addr resultip; - bitmask += (256 ^ octetpos) * atoi(octet.c_str()); - octetpos += 1; - } + /* Convert the result to an in_addr (we can gaurantee we got ipv4) + * Whoever did the loop that was here before, I AM CONFISCATING + * YOUR CRACKPIPE. you know who you are. -- Brain + */ + inet_aton(result.c_str(), &resultip); + bitmask = resultip.s_addr >> 24; /* Last octet (network byte order */ bitmask &= ConfEntry->bitmask; if (bitmask != 0) { std::string reason = ConfEntry->reason; - - while (int pos = reason.find("%ip%") != std::string::npos) + std::string::size_type x = reason.find("%ip%"); + while (x != std::string::npos) { - reason.replace(pos, 4, them->GetIPString()); + reason.erase(x, 4); + reason.insert(x, them->GetIPString()); + x = reason.find("%ip%"); } - ServerInstance->WriteOpers("*** Connecting user %s detected as being on a DNS blacklist (%s) with result %d", them->GetFullRealHost(), ConfEntry->name.c_str(), bitmask); + ConfEntry->stats_hits++; switch (ConfEntry->banaction) { case DNSBLConfEntry::I_KILL: { - them->QuitUser(ServerInstance, them, std::string("Killed (") + reason + ")"); + userrec::QuitUser(ServerInstance, them, std::string("Killed (") + reason + ")"); break; } case DNSBLConfEntry::I_KLINE: { - ServerInstance->AddKLine(ConfEntry->duration, ServerInstance->Config->ServerName, reason, std::string("*@") + them->GetIPString()); + std::string ban = std::string("*@") + them->GetIPString(); + if (show) + ServerInstance->XLines->apply_lines(APPLY_KLINES); + show = ServerInstance->XLines->add_kline(ConfEntry->duration, ServerInstance->Config->ServerName, reason.c_str(), ban.c_str()); + FOREACH_MOD(I_OnAddKLine,OnAddKLine(ConfEntry->duration, NULL, reason, ban)); break; } case DNSBLConfEntry::I_GLINE: { - ServerInstance->AddGLine(ConfEntry->duration, ServerInstance->Config->ServerName, reason, std::string("*@") + them->GetIPString()); + std::string ban = std::string("*@") + them->GetIPString(); + show = ServerInstance->XLines->add_gline(ConfEntry->duration, ServerInstance->Config->ServerName, reason.c_str(), ban.c_str()); + if (show) + ServerInstance->XLines->apply_lines(APPLY_GLINES); + FOREACH_MOD(I_OnAddGLine,OnAddGLine(ConfEntry->duration, NULL, reason, ban)); break; } case DNSBLConfEntry::I_ZLINE: { - ServerInstance->AddZLine(ConfEntry->duration, ServerInstance->Config->ServerName, reason, them->GetIPString()); + show = ServerInstance->XLines->add_zline(ConfEntry->duration, ServerInstance->Config->ServerName, reason.c_str(), them->GetIPString()); + if (show) + ServerInstance->XLines->apply_lines(APPLY_ZLINES); + FOREACH_MOD(I_OnAddZLine,OnAddZLine(ConfEntry->duration, NULL, reason, them->GetIPString())); break; } case DNSBLConfEntry::I_UNKNOWN: @@ -120,26 +133,24 @@ class DNSBLResolver : public Resolver } break; } + + if (show) + { + ServerInstance->WriteOpers("*** Connecting user %s detected as being on a DNS blacklist (%s) with result %d", them->GetFullRealHost(), ConfEntry->name.c_str(), bitmask); + } } + else + ConfEntry->stats_misses++; } + else + ConfEntry->stats_misses++; } } virtual void OnError(ResolverError e, const std::string &errormessage) { - /* - this just means they don't appear in the respective dnsbl - if ((them) && (them == ServerInstance->SE->GetRef(theirfd))) - { - } - */ - /* Check the user still exists */ - if ((them) && (them == ServerInstance->SE->GetRef(theirfd))) - { - ServerInstance->Log(DEBUG, "m_dnsbl: %s got an error while resolving for dnsbl %s", them->nick, ConfEntry->name.c_str()); - } } - + virtual ~DNSBLResolver() { } @@ -149,7 +160,7 @@ class ModuleDNSBL : public Module { private: std::vector DNSBLConfEntries; - + /* * Convert a string to EnumBanaction */ @@ -163,36 +174,46 @@ class ModuleDNSBL : public Module return DNSBLConfEntry::I_ZLINE; if(action.compare("GLINE")==0) return DNSBLConfEntry::I_GLINE; - + return DNSBLConfEntry::I_UNKNOWN; } public: - ModuleDNSBL(InspIRCd *Me) : Module::Module(Me) + ModuleDNSBL(InspIRCd *Me) : Module(Me) { ReadConf(); } - + virtual ~ModuleDNSBL() { + ClearEntries(); } - + virtual Version GetVersion() { - return Version(2, 0, 0, 0, 0, API_VERSION); + return Version(2, 0, 0, 1, VF_VENDOR, API_VERSION); } void Implements(char* List) { - List[I_OnRehash] = List[I_OnUserRegister] = 1; + List[I_OnRehash] = List[I_OnUserRegister] = List[I_OnStats] = 1; } - /* - * Fill our conf vector with data - */ + /** Clear entries and free the mem it was using + */ + void ClearEntries() + { + std::vector::iterator i; + for (std::vector::iterator i = DNSBLConfEntries.begin(); i != DNSBLConfEntries.end(); i++) + delete *i; + DNSBLConfEntries.clear(); + } + + /** Fill our conf vector with data + */ virtual void ReadConf() { ConfigReader *MyConf = new ConfigReader(ServerInstance); - DNSBLConfEntries.clear(); + ClearEntries(); for (int i=0; i< MyConf->Enumerate("dnsbl"); i++) { @@ -202,7 +223,7 @@ class ModuleDNSBL : public Module e->reason = MyConf->ReadValue("dnsbl", "reason", i); e->domain = MyConf->ReadValue("dnsbl", "domain", i); e->banaction = str2banaction(MyConf->ReadValue("dnsbl", "action", i)); - e->duration = ServerInstance->Duration(MyConf->ReadValue("dnsbl", "duration", i).c_str()); + e->duration = ServerInstance->Duration(MyConf->ReadValue("dnsbl", "duration", i)); e->bitmask = MyConf->ReadInteger("dnsbl", "bitmask", i, false); /* yeah, logic here is a little messy */ @@ -210,11 +231,11 @@ class ModuleDNSBL : public Module { ServerInstance->WriteOpers("*** DNSBL(#%d): invalid bitmask",i); } - else if (e->name == "") + else if (e->name.empty()) { ServerInstance->WriteOpers("*** DNSBL(#%d): Invalid name",i); } - else if (e->domain == "") + else if (e->domain.empty()) { ServerInstance->WriteOpers("*** DNSBL(#%d): Invalid domain",i); } @@ -224,7 +245,7 @@ class ModuleDNSBL : public Module } else { - if (e->reason == "") + if (e->reason.empty()) { ServerInstance->WriteOpers("*** DNSBL(#%d): empty reason, using defaults",i); e->reason = "Your IP has been blacklisted."; @@ -232,8 +253,7 @@ class ModuleDNSBL : public Module /* add it, all is ok */ DNSBLConfEntries.push_back(e); - delete MyConf; - return; + continue; } /* delete and drop it, error somewhere */ @@ -242,18 +262,15 @@ class ModuleDNSBL : public Module delete MyConf; } - - - virtual void OnRehash(const std::string ¶meter) + + virtual void OnRehash(userrec* user, const std::string ¶meter) { ReadConf(); } - /* - * We will check each user that connects *locally* (userrec::fd>0) - */ virtual int OnUserRegister(userrec* user) { + /* only do lookups on local users */ if (IS_LOCAL(user)) { /* following code taken from bopm, reverses an IP address. */ @@ -261,13 +278,30 @@ class ModuleDNSBL : public Module unsigned char a, b, c, d; char reversedipbuf[128]; std::string reversedip; + bool success = false; if (!inet_aton(user->GetIPString(), &in)) { - ServerInstance->WriteOpers("Invalid IP address in m_dnsbl! Bailing check"); - return 0; +#ifdef IPV6 + /* We could have an ipv6 address here */ + std::string x = user->GetIPString(); + /* Is it a 4in6 address? (Compensate for this kernel kludge that people love) */ + if (x.find("0::ffff:") == 0) + { + x.erase(x.begin(), x.begin() + 8); + if (inet_aton(x.c_str(), &in)) + success = true; + } +#endif + } + else + { + success = true; } + if (!success) + return 0; + d = (unsigned char) (in.s_addr >> 24) & 0xFF; c = (unsigned char) (in.s_addr >> 16) & 0xFF; b = (unsigned char) (in.s_addr >> 8) & 0xFF; @@ -276,72 +310,44 @@ class ModuleDNSBL : public Module snprintf(reversedipbuf, 128, "%d.%d.%d.%d", d, c, b, a); reversedip = std::string(reversedipbuf); -/* - this is satmd's old code - std::string reversedip; - std::string userip = user->GetIPString(); - std::string tempip = userip; - - // reversedip will created in there - while (tempip.length()>0) - { - unsigned int lastdot=tempip.rfind("."); - if (lastdot == std::string::npos) - { - reversedip+=tempip; - tempip.clear(); - } - else - { - reversedip += tempip.substr(lastdot+1,tempip.length()-lastdot+1); - reversedip += "."; - tempip.resize(lastdot); - } - } -*/ - // For each DNSBL, we will run through this lookup for (std::vector::iterator i = DNSBLConfEntries.begin(); i != DNSBLConfEntries.end(); i++) { // Fill hostname with a dnsbl style host (d.c.b.a.domain.tld) - std::string hostname=reversedip+"."+ (*i)->domain; - - ServerInstance->Log(DEBUG, "m_dnsbl: sending %s for resolution", hostname.c_str()); + std::string hostname = reversedip + "." + (*i)->domain; /* now we'd need to fire off lookups for `hostname'. */ - DNSBLResolver *r = new DNSBLResolver(this, ServerInstance, hostname, user, user->GetFd(), *i); - ServerInstance->AddResolver(r); + bool cached; + DNSBLResolver *r = new DNSBLResolver(this, ServerInstance, hostname, user, user->GetFd(), *i, cached); + ServerInstance->AddResolver(r, cached); } } /* don't do anything with this hot potato */ return 0; } -}; - -// stuff down here is the module-factory stuff. - -class ModuleDNSBLFactory : public ModuleFactory -{ - public: - ModuleDNSBLFactory() - { - } - - ~ModuleDNSBLFactory() - { - } - virtual Module *CreateModule(InspIRCd *Me) + virtual int OnStats(char symbol, userrec* user, string_list &results) { - return new ModuleDNSBL(Me); + if (symbol != 'd') + return 0; + + unsigned long total_hits = 0, total_misses = 0; + + for (std::vector::iterator i = DNSBLConfEntries.begin(); i != DNSBLConfEntries.end(); i++) + { + total_hits += (*i)->stats_hits; + total_misses += (*i)->stats_misses; + + results.push_back(std::string(ServerInstance->Config->ServerName) + " 304 " + user->nick + " :DNSBLSTATS DNSbl \"" + (*i)->name + "\" had " + + ConvToStr((*i)->stats_hits) + " hits and " + ConvToStr((*i)->stats_misses) + " misses"); + } + + results.push_back(std::string(ServerInstance->Config->ServerName) + " 304 " + user->nick + " :DNSBLSTATS Total hits: " + ConvToStr(total_hits)); + results.push_back(std::string(ServerInstance->Config->ServerName) + " 304 " + user->nick + " :DNSBLSTATS Total misses: " + ConvToStr(total_misses)); + + return 0; } - }; - -extern "C" void * init_module( void ) -{ - return new ModuleDNSBLFactory; -} - +MODULE_INIT(ModuleDNSBL)