]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/coremods/core_hostname_lookup.cpp
Rename `<bind:ssl>` to `<bind:sslprofile>`.
[user/henk/code/inspircd.git] / src / coremods / core_hostname_lookup.cpp
index 2a8426be9c133523bacf1edd0d2d99218ad4e30e..91d817765a17cafb44629b7a11e46d6bdf490c57 100644 (file)
@@ -1,7 +1,10 @@
 /*
  * InspIRCd -- Internet Relay Chat Daemon
  *
- *   Copyright (C) 2013-2016 Adam <Adam@anope.org>
+ *   Copyright (C) 2020 Matt Schatz <genius3000@g3k.solutions>
+ *   Copyright (C) 2013-2015 Attila Molnar <attilamolnar@hush.com>
+ *   Copyright (C) 2013, 2017-2020 Sadie Powell <sadie@witchery.services>
+ *   Copyright (C) 2013, 2016 Adam <Adam@anope.org>
  *
  * 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
 namespace
 {
        LocalIntExt* dl;
-       LocalStringExt* ph;
 }
 
 /** Derived from Resolver, and performs user forward/reverse lookups.
  */
 class UserResolver : public DNS::Request
 {
+ private:
        /** UUID we are looking up */
        const std::string uuid;
 
-       /** True if the lookup is forward, false if is a reverse lookup
-        */
-       const bool fwd;
+       /** Handles errors which happen during DNS resolution. */
+       static void HandleError(LocalUser* user, const std::string& message)
+       {
+               user->WriteNotice("*** " + message + "; using your IP address (" + user->GetIPString() + ") instead.");
+
+               bool display_is_real = user->GetDisplayedHost() == user->GetRealHost();
+               user->ChangeRealHost(user->GetIPString(), display_is_real);
+
+               dl->unset(user);
+       }
 
  public:
        /** Create a resolver.
@@ -48,7 +58,6 @@ class UserResolver : public DNS::Request
        UserResolver(DNS::Manager* mgr, Module* me, LocalUser* user, const std::string& to_resolve, DNS::QueryType qt)
                : DNS::Request(mgr, me, to_resolve, qt)
                , uuid(user->uuid)
-               , fwd(qt == DNS::QUERY_A || qt == DNS::QUERY_AAAA)
        {
        }
 
@@ -56,9 +65,9 @@ class UserResolver : public DNS::Request
         * if a previous result has already come back.
         * @param r The finished query
         */
-       void OnLookupComplete(const DNS::Query* r)
+       void OnLookupComplete(const DNS::Query* r) CXX11_OVERRIDE
        {
-               LocalUser* bound_user = (LocalUser*)ServerInstance->FindUUID(uuid);
+               LocalUser* bound_user = IS_LOCAL(ServerInstance->FindUUID(uuid));
                if (!bound_user)
                {
                        ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Resolution finished for user '%s' who is gone", uuid.c_str());
@@ -68,19 +77,19 @@ class UserResolver : public DNS::Request
                const DNS::ResourceRecord* ans_record = r->FindAnswerOfType(this->question.type);
                if (ans_record == NULL)
                {
-                       OnError(r);
+                       HandleError(bound_user, "Could not resolve your hostname: No " + this->manager->GetTypeStr(this->question.type) + " records found");
                        return;
                }
 
-               ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "DNS result for %s: '%s' -> '%s'", uuid.c_str(), ans_record->name.c_str(), ans_record->rdata.c_str());
+               ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "DNS %s result for %s: '%s' -> '%s'%s",
+                       this->manager->GetTypeStr(question.type).c_str(), uuid.c_str(),
+                       ans_record->name.c_str(), ans_record->rdata.c_str(),
+                       r->cached ? " (cached)" : "");
 
-               if (!fwd)
+               if (this->question.type == DNS::QUERY_PTR)
                {
-                       // first half of resolution is done. We now need to verify that the host matches.
-                       ph->set(bound_user, ans_record->rdata);
-
                        UserResolver* res_forward;
-                       if (bound_user->client_sa.sa.sa_family == AF_INET6)
+                       if (bound_user->client_sa.family() == AF_INET6)
                        {
                                /* IPV6 forward lookup */
                                res_forward = new UserResolver(this->manager, this->creator, bound_user, ans_record->rdata, DNS::QUERY_AAAA);
@@ -99,17 +108,16 @@ class UserResolver : public DNS::Request
                                delete res_forward;
                                ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Error in resolver: " + e.GetReason());
 
-                               bound_user->WriteNotice("*** There was an internal error resolving your host, using your IP address (" + bound_user->GetIPString() + ") instead.");
-                               dl->set(bound_user, 0);
+                               HandleError(bound_user, "There was an internal error resolving your host");
                        }
                }
-               else
+               else if (this->question.type == DNS::QUERY_A || this->question.type == DNS::QUERY_AAAA)
                {
                        /* Both lookups completed */
 
                        irc::sockets::sockaddrs* user_ip = &bound_user->client_sa;
                        bool rev_match = false;
-                       if (user_ip->sa.sa_family == AF_INET6)
+                       if (user_ip->family() == AF_INET6)
                        {
                                struct in6_addr res_bin;
                                if (inet_pton(AF_INET6, ans_record->rdata.c_str(), &res_bin))
@@ -126,37 +134,16 @@ class UserResolver : public DNS::Request
                                }
                        }
 
-                       dl->set(bound_user, 0);
-
                        if (rev_match)
                        {
-                               std::string* hostname = ph->get(bound_user);
-
-                               if (hostname == NULL)
-                               {
-                                       ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "ERROR: User has no hostname attached when doing a forward lookup");
-                                       bound_user->WriteNotice("*** There was an internal error resolving your host, using your IP address (" + bound_user->GetIPString() + ") instead.");
-                                       return;
-                               }
-                               else if (hostname->length() <= ServerInstance->Config->Limits.MaxHost)
-                               {
-                                       /* Hostnames starting with : are not a good thing (tm) */
-                                       if ((*hostname)[0] == ':')
-                                               hostname->insert(0, "0");
-
-                                       bound_user->WriteNotice("*** Found your hostname (" + *hostname + (r->cached ? ") -- cached" : ")"));
-                                       bound_user->ChangeRealHost(hostname->substr(ServerInstance->Config->Limits.MaxHost), true);
-                               }
-                               else
-                               {
-                                       bound_user->WriteNotice("*** Your hostname is longer than the maximum of " + ConvToStr(ServerInstance->Config->Limits.MaxHost) + " characters, using your IP address (" + bound_user->GetIPString() + ") instead.");
-                               }
-
-                               ph->unset(bound_user);
+                               bound_user->WriteNotice("*** Found your hostname (" + this->question.name + (r->cached ? ") -- cached" : ")"));
+                               bool display_is_real = bound_user->GetDisplayedHost() == bound_user->GetRealHost();
+                               bound_user->ChangeRealHost(this->question.name, display_is_real);
+                               dl->unset(bound_user);
                        }
                        else
                        {
-                               bound_user->WriteNotice("*** Your hostname does not match up with your IP address. Sorry, using your IP address (" + bound_user->GetIPString() + ") instead.");
+                               HandleError(bound_user, "Your hostname does not match up with your IP address");
                        }
                }
        }
@@ -164,40 +151,38 @@ class UserResolver : public DNS::Request
        /** Called on failed lookup
         * @param query The errored query
         */
-       void OnError(const DNS::Query* query)
+       void OnError(const DNS::Query* query) CXX11_OVERRIDE
        {
-               LocalUser* bound_user = (LocalUser*)ServerInstance->FindUUID(uuid);
+               LocalUser* bound_user = IS_LOCAL(ServerInstance->FindUUID(uuid));
                if (bound_user)
-               {
-                       bound_user->WriteNotice("*** Could not resolve your hostname: " + this->manager->GetErrorStr(query->error) + "; using your IP address (" + bound_user->GetIPString() + ") instead.");
-                       dl->set(bound_user, 0);
-               }
+                       HandleError(bound_user, "Could not resolve your hostname: " + this->manager->GetErrorStr(query->error));
        }
 };
 
 class ModuleHostnameLookup : public Module
 {
+ private:
        LocalIntExt dnsLookup;
-       LocalStringExt ptrHosts;
        dynamic_reference<DNS::Manager> DNS;
 
  public:
        ModuleHostnameLookup()
                : dnsLookup("dnsLookup", ExtensionItem::EXT_USER, this)
-               , ptrHosts("ptrHosts", ExtensionItem::EXT_USER, this)
                , DNS(this, "DNS")
        {
                dl = &dnsLookup;
-               ph = &ptrHosts;
        }
 
-       void OnUserInit(LocalUser *user) CXX11_OVERRIDE
+       void OnSetUserIP(LocalUser* user) CXX11_OVERRIDE
        {
-               if (!DNS || !user->MyClass->resolvehostnames)
-               {
-                       user->WriteNotice("*** Skipping host resolution (disabled by server administrator)");
+               // If core_dns is not loaded or hostname resolution is disabled for the user's
+               // connect class then the logic in this function does not apply.
+               if (!DNS || user->quitting || !user->MyClass->resolvehostnames)
+                       return;
+
+               // Clients can't have a DNS hostname if they aren't connected via IPv4 or IPv6.
+               if (user->client_sa.family() != AF_INET && user->client_sa.family() != AF_INET6)
                        return;
-               }
 
                user->WriteNotice("*** Looking up your hostname...");