]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Harden stripDomainSuffix() logic. 17152/head
authorMiod Vallat <miod.vallat@powerdns.com>
Thu, 16 Apr 2026 14:28:14 +0000 (16:28 +0200)
committerMiod Vallat <miod.vallat@powerdns.com>
Fri, 17 Apr 2026 06:28:00 +0000 (08:28 +0200)
Signed-off-by: Miod Vallat <miod.vallat@powerdns.com>
modules/bindbackend/bindbackend2.cc

index f5b99bc2fe61f8a7743b0bf379cb3f4c59e7cb5a..ef40f7b331bde342baa2faefac17dd7a6ee3b669 100644 (file)
@@ -290,23 +290,28 @@ bool Bind2Backend::abortTransaction()
 /** does domain end on suffix? Is smart about "wwwds9a.nl" "ds9a.nl" not matching */
 static bool endsOn(const string& domain, const string& suffix)
 {
-  if (suffix.empty() || pdns_iequals(domain, suffix)) {
-    return true;
-  }
-
   if (domain.size() <= suffix.size()) {
     return false;
   }
 
   string::size_type dpos = domain.size() - suffix.size() - 1;
-  string::size_type spos = 0;
-
   if (domain[dpos++] != '.') {
     return false;
   }
+  // That dot might have been escaped. So we now need to count how many '\'
+  // characters we can find in a row before it; if their number is odd, the
+  // dot is escaped and we are not a proper suffix.
+  size_t slashes{0};
+  while (dpos >= 2 + slashes && domain.at(dpos - 2 - slashes) == '\\') {
+    ++slashes;
+  }
+  if ((slashes % 2) != 0) {
+    return false;
+  }
 
+  string::size_type spos = 0;
   for (; dpos < domain.size(); ++dpos, ++spos) {
-    if (dns_tolower(domain[dpos]) != dns_tolower(suffix[spos])) {
+    if (!pdns_iequals_ch(domain[dpos], suffix[spos])) {
       return false;
     }
   }
@@ -319,15 +324,16 @@ static void stripDomainSuffix(string* qname, const ZoneName& zonename)
 {
   std::string domain = zonename.operator const DNSName&().toString();
 
+  if (domain.empty()) {
+    return;
+  }
+  if (pdns_iequals(*qname, domain)) {
+    *qname = "@";
+    return;
+  }
   if (endsOn(*qname, domain)) {
-    if (toLower(*qname) == toLower(domain)) {
-      *qname = "@";
-    }
-    else {
-      if ((*qname)[qname->size() - domain.size() - 1] == '.') {
-        qname->resize(qname->size() - domain.size() - 1);
-      }
-    }
+    auto prefix = qname->size() - domain.size();
+    qname->resize(prefix - 1); // also strip dot
   }
 }