]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: backport CVE-2024-25583 to rel/rec-4.8.8-branch 14110/head rec-4.8.8
authorOtto Moerbeek <otto@drijf.net>
Tue, 9 Apr 2024 09:55:32 +0000 (11:55 +0200)
committerOtto Moerbeek <otto@drijf.net>
Tue, 9 Apr 2024 09:55:32 +0000 (11:55 +0200)
A name can be present already when building the cname chain.

pdns/recursordist/test-syncres_cc1.cc
pdns/syncres.cc

index e218e86c43749b67ee97ca21396b5c5504095158..b9b6e670c66110ce7a2964e042eda3de43afc9e9 100644 (file)
@@ -1579,6 +1579,54 @@ BOOST_AUTO_TEST_CASE(test_cname_loop)
   }
 }
 
+BOOST_AUTO_TEST_CASE(test_cname_loop_forwarder)
+{
+  std::unique_ptr<SyncRes> resolver;
+  initSR(resolver);
+
+  primeHints();
+
+  size_t count = 0;
+  const DNSName target("cname.powerdns.com.");
+  const DNSName cname1("cname1.cname.powerdns.com.");
+  const DNSName cname2("cname2.cname.powerdns.com.");
+
+  SyncRes::AuthDomain ad;
+  const std::vector<ComboAddress> forwardedNSs{ComboAddress("192.0.2.42:53")};
+  ad.d_rdForward = true;
+  ad.d_servers = forwardedNSs;
+  (*SyncRes::t_sstorage.domainmap)[target] = ad;
+
+  resolver->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
+    count++;
+
+    if (isRootServer(address)) {
+
+      setLWResult(res, 0, false, false, true);
+      addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
+      addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
+      return LWResult::Result::Success;
+    }
+    if (address == ComboAddress("192.0.2.42:53")) {
+
+      if (domain == target) {
+        setLWResult(res, 0, true, false, false);
+        addRecordToLW(res, domain, QType::CNAME, cname1.toString());
+        addRecordToLW(res, cname1, QType::CNAME, cname2.toString());
+        addRecordToLW(res, cname2, QType::CNAME, domain.toString());
+        return LWResult::Result::Success;
+      }
+
+      return LWResult::Result::Success;
+    }
+
+    return LWResult::Result::Timeout;
+  });
+
+  vector<DNSRecord> ret;
+  BOOST_REQUIRE_THROW(resolver->beginResolve(target, QType(QType::A), QClass::IN, ret), ImmediateServFailException);
+}
+
 BOOST_AUTO_TEST_CASE(test_cname_long_loop)
 {
   std::unique_ptr<SyncRes> sr;
index 5eaaedbb37663acb577d07f1c3def28a3122aea3..e893b74462006b627c99835cc6991166104437a6 100644 (file)
@@ -4317,7 +4317,10 @@ RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, LWResult& lwr
         break;
       }
       initial = cnameIt->second;
-      wildcardCandidates.emplace(initial, false);
+      if (!wildcardCandidates.emplace(initial, false).second) {
+        // CNAME loop
+        break;
+      }
     }
   }