#include "inspircd.h"
#include "xline.h"
-
-/* $ModDesc: Change user's hosts connecting from known CGI:IRC hosts */
+#include "modules/dns.h"
enum CGItype { PASS, IDENT, PASSFIRST, IDENTFIRST, WEBIRC };
{
realhost.set(user, user->host);
realip.set(user, user->GetIPString());
+
+ bool host_ok = (parameters[2].length() < 64);
+ const std::string& newhost = (host_ok ? parameters[2] : parameters[3]);
+
if (notify)
- ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s detected as using CGI:IRC (%s), changing real host to %s from %s", user->nick.c_str(), user->host.c_str(), parameters[2].c_str(), user->host.c_str());
+ ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s detected as using CGI:IRC (%s), changing real host to %s from %s", user->nick.c_str(), user->host.c_str(), newhost.c_str(), user->host.c_str());
// Check if we're happy with the provided hostname. If it's problematic then make sure we won't set a host later, just the IP
- if (parameters[2].length() < 64)
+ if (host_ok)
webirc_hostname.set(user, parameters[2]);
else
webirc_hostname.unset(user);
/** Resolver for CGI:IRC hostnames encoded in ident/GECOS
*/
-class CGIResolver : public Resolver
+class CGIResolver : public DNS::Request
{
std::string typ;
std::string theiruid;
LocalIntExt& waiting;
bool notify;
public:
- CGIResolver(Module* me, bool NotifyOpers, const std::string &source, LocalUser* u,
- const std::string &type, bool &cached, LocalIntExt& ext)
- : Resolver(source, DNS_QUERY_PTR4, cached, me), typ(type), theiruid(u->uuid),
+ CGIResolver(DNS::Manager *mgr, Module* me, bool NotifyOpers, const std::string &source, LocalUser* u,
+ const std::string &ttype, LocalIntExt& ext)
+ : DNS::Request(mgr, me, source, DNS::QUERY_PTR), typ(ttype), theiruid(u->uuid),
waiting(ext), notify(NotifyOpers)
{
}
- virtual void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached)
+ void OnLookupComplete(const DNS::Query *r) CXX11_OVERRIDE
{
/* Check the user still exists */
User* them = ServerInstance->FindUUID(theiruid);
- if (them)
+ if ((them) && (!them->quitting))
{
- if (notify)
- ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s detected as using CGI:IRC (%s), changing real host to %s from %s", them->nick.c_str(), them->host.c_str(), result.c_str(), typ.c_str());
+ LocalUser* lu = IS_LOCAL(them);
+ if (!lu)
+ return;
- if (result.length() > 64)
+ const DNS::ResourceRecord &ans_record = r->answers[0];
+ if (ans_record.rdata.empty() || ans_record.rdata.length() > 64)
return;
- them->host = result;
- them->dhost = result;
+
+ if (notify)
+ ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s detected as using CGI:IRC (%s), changing real host to %s from %s", them->nick.c_str(), them->host.c_str(), ans_record.rdata.c_str(), typ.c_str());
+
+ them->host = them->dhost = ans_record.rdata;
them->InvalidateCache();
- them->CheckLines(true);
+ lu->CheckLines(true);
}
}
- virtual void OnError(ResolverError e, const std::string &errormessage)
+ void OnError(const DNS::Query *r) CXX11_OVERRIDE
{
+ if (!notify)
+ return;
+
User* them = ServerInstance->FindUUID(theiruid);
- if (them)
+ if ((them) && (!them->quitting))
{
- if (notify)
- ServerInstance->SNO->WriteToSnoMask('a', "Connecting user %s detected as using CGI:IRC (%s), but their host can't be resolved from their %s!", them->nick.c_str(), them->host.c_str(), typ.c_str());
+ ServerInstance->SNO->WriteToSnoMask('a', "Connecting user %s detected as using CGI:IRC (%s), but their host can't be resolved from their %s!", them->nick.c_str(), them->host.c_str(), typ.c_str());
}
}
- virtual ~CGIResolver()
+ ~CGIResolver()
{
User* them = ServerInstance->FindUUID(theiruid);
if (!them)
{
CommandWebirc cmd;
LocalIntExt waiting;
+ dynamic_reference<DNS::Manager> DNS;
- static void RecheckElineAndClass(LocalUser* user)
+ static void RecheckClass(LocalUser* user)
{
- user->exempt = (ServerInstance->XLines->MatchesLine("E", user) != NULL);
+ user->MyClass = NULL;
user->SetClass();
user->CheckClass();
}
ChangeIP(user, newip);
user->host = user->dhost = user->GetIPString();
user->InvalidateCache();
- RecheckElineAndClass(user);
- // Don't create the resolver if the core couldn't put the user in a connect class
- if (user->quitting)
+ RecheckClass(user);
+
+ // Don't create the resolver if the core couldn't put the user in a connect class or when dns is disabled
+ if (user->quitting || !DNS || !user->MyClass->resolvehostnames)
return;
+ CGIResolver* r = new CGIResolver(*this->DNS, this, cmd.notify, newip, user, (was_pass ? "PASS" : "IDENT"), waiting);
try
{
- bool cached;
- CGIResolver* r = new CGIResolver(this, cmd.notify, newip, user, (was_pass ? "PASS" : "IDENT"), cached, waiting);
- ServerInstance->AddResolver(r, cached);
waiting.set(user, waiting.get(user) + 1);
+ this->DNS->Process(r);
}
- catch (...)
+ catch (DNS::Exception &ex)
{
+ int count = waiting.get(user);
+ if (count)
+ waiting.set(user, count - 1);
+ delete r;
if (cmd.notify)
- ServerInstance->SNO->WriteToSnoMask('a', "Connecting user %s detected as using CGI:IRC (%s), but I could not resolve their hostname!", user->nick.c_str(), user->host.c_str());
+ ServerInstance->SNO->WriteToSnoMask('a', "Connecting user %s detected as using CGI:IRC (%s), but I could not resolve their hostname; %s", user->nick.c_str(), user->host.c_str(), ex.GetReason());
}
}
public:
- ModuleCgiIRC() : cmd(this), waiting("cgiirc-delay", this)
+ ModuleCgiIRC()
+ : cmd(this)
+ , waiting("cgiirc-delay", this)
+ , DNS(this, "DNS")
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
- ServerInstance->AddCommand(&cmd);
- ServerInstance->Extensions.Register(&cmd.realhost);
- ServerInstance->Extensions.Register(&cmd.realip);
- ServerInstance->Extensions.Register(&cmd.webirc_hostname);
- ServerInstance->Extensions.Register(&cmd.webirc_ip);
- ServerInstance->Extensions.Register(&waiting);
-
- Implementation eventlist[] = { I_OnRehash, I_OnUserRegister, I_OnCheckReady };
- ServerInstance->Modules->Attach(eventlist, this, 3);
+ ServiceProvider* providerlist[] = { &cmd, &cmd.realhost, &cmd.realip, &cmd.webirc_hostname, &cmd.webirc_ip, &waiting };
+ ServerInstance->Modules->AddServices(providerlist, sizeof(providerlist)/sizeof(ServiceProvider*));
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
cmd.Hosts.clear();
{
if (type == "webirc" && password.empty())
{
- ServerInstance->Logs->Log("CONFIG",DEFAULT, "m_cgiirc: Missing password in config: %s", hostmask.c_str());
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "m_cgiirc: Missing password in config: %s", hostmask.c_str());
}
else
{
else
{
cgitype = PASS;
- ServerInstance->Logs->Log("CONFIG",DEFAULT, "m_cgiirc.so: Invalid <cgihost:type> value in config: %s, setting it to \"pass\"", type.c_str());
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "Invalid <cgihost:type> value in config: %s, setting it to \"pass\"", type.c_str());
}
cmd.Hosts.push_back(CGIhost(hostmask, cgitype, password));
}
else
{
- ServerInstance->Logs->Log("CONFIG",DEFAULT, "m_cgiirc.so: Invalid <cgihost:mask> value in config: %s", hostmask.c_str());
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "Invalid <cgihost:mask> value in config: %s", hostmask.c_str());
continue;
}
}
}
- ModResult OnCheckReady(LocalUser *user)
+ ModResult OnCheckReady(LocalUser *user) CXX11_OVERRIDE
{
if (waiting.get(user))
return MOD_RES_DENY;
std::string* webirc_hostname = cmd.webirc_hostname.get(user);
user->host = user->dhost = (webirc_hostname ? *webirc_hostname : user->GetIPString());
- RecheckElineAndClass(user);
+ RecheckClass(user);
if (user->quitting)
return MOD_RES_DENY;
return MOD_RES_PASSTHRU;
}
- ModResult OnUserRegister(LocalUser* user)
+ ModResult OnUserRegister(LocalUser* user) CXX11_OVERRIDE
{
for(CGIHostlist::iterator iter = cmd.Hosts.begin(); iter != cmd.Hosts.end(); iter++)
{
return true;
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Change user's hosts connecting from known CGI:IRC hosts",VF_VENDOR);
}