]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: Add negativetrustanchor.server CH TXT query
authorPieter Lexis <pieter.lexis@powerdns.com>
Mon, 2 Oct 2017 12:32:37 +0000 (14:32 +0200)
committerPieter Lexis <pieter.lexis@powerdns.com>
Mon, 2 Oct 2017 12:34:30 +0000 (14:34 +0200)
pdns/recursordist/docs/dnssec.rst
pdns/recursordist/docs/settings.rst
pdns/syncres.cc
regression-tests.recursor-dnssec/test_TrustAnchors.py

index 028cdaaee059314d3c4f4b7bbcd34b95b23a2779..b09b33979f7ed97eaac75b88c8fb14d3c530afd3 100644 (file)
@@ -134,6 +134,9 @@ Negative trust anchors (defined in :rfc:`7646`) can be used to temporarily disab
 This can be done when e.g. a TLD or high-traffic zone goes bogus.
 Note that it is good practice to verify that this is indeed the case and not because of malicious actions.
 
+Current trust anchors can be queried from the recursor by sending a query for "negativetrustanchor.server CH TXT".
+This query will (if :ref:`setting-allow-trust-anchor-query` is enabled) return a TXT record per negative trust-anchor in the format ``"DOMAIN [REASON]"``.
+
 To configure a negative trust anchor, use the ``addNTA()`` function in the :ref:`setting-lua-config-file` and restart the recursor.
 This function requires the name of the zone and an optional reason:
 
index 5a9aeac718fa3f4939b8d63037738e817cfe6c31..d0d3b50e6a27c49daeb2fe277757ece5b3c5e4ac 100644 (file)
@@ -63,7 +63,7 @@ Useful for mitigating ANY reflection attacks.
 -  Boolean
 -  Default: yes
 
-Allow ``trustanchor.server CH TXT`` queries to view the configured :doc:`DNSSEC <dnssec>` trust anchors.
+Allow ``trustanchor.server CH TXT`` and ``negativetrustanchor.server CH TXT`` queries to view the configured :doc:`DNSSEC <dnssec>` (negative) trust anchors.
 
 .. _setting-api-config-dir:
 
index 6888ec90410df9d345171e484d996a5549bac5f6..a09f9d6a3c9a769aaaf3bdad5a592ff3225d21dd 100644 (file)
@@ -160,11 +160,13 @@ int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qcl
  * - version.pdns. CH TXT
  * - id.server. CH TXT
  * - trustanchor.server CH TXT
+ * - negativetrustanchor.server CH TXT
  */
 bool SyncRes::doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t qclass, vector<DNSRecord> &ret)
 {
   static const DNSName arpa("1.0.0.127.in-addr.arpa."), ip6_arpa("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."),
-    localhost("localhost."), versionbind("version.bind."), idserver("id.server."), versionpdns("version.pdns."), trustanchorserver("trustanchor.server.");
+    localhost("localhost."), versionbind("version.bind."), idserver("id.server."), versionpdns("version.pdns."), trustanchorserver("trustanchor.server."),
+    negativetrustanchorserver("negativetrustanchor.server.");
 
   bool handled = false;
   vector<pair<QType::typeenum, string> > answers;
@@ -215,6 +217,23 @@ bool SyncRes::doSpecialNamesResolve(const DNSName &qname, const QType &qtype, co
     }
   }
 
+  if (qname == negativetrustanchorserver && qclass == QClass::CHAOS &&
+      ::arg().mustDo("allow-trust-anchor-query")) {
+    handled = true;
+    if (qtype == QType::TXT || qtype == QType::ANY) {
+      auto luaLocal = g_luaconfs.getLocal();
+      for (auto const &negAnchor : luaLocal->negAnchors) {
+        ostringstream ans;
+        ans<<"\"";
+        ans<<negAnchor.first.toString(); // Explicit toString to have a trailing dot
+        if (negAnchor.second.length())
+          ans<<" "<<negAnchor.second;
+        ans << "\"";
+        answers.push_back({QType::TXT, ans.str()});
+      }
+    }
+  }
+
   if (handled && !answers.empty()) {
     ret.clear();
     d_wasOutOfBand=true;
index bb761ef3e56d8ca2d6f5e2c0aee7ccba8d33698d..094a36051cd650bc2f622b2ba952efcd373f761b 100644 (file)
@@ -12,6 +12,8 @@ class testTrustAnchorsEnabled(RecursorTest):
     _root_DS = None
     _lua_config_file = """
 addDS("powerdns.com", "44030 8 1 B763646757DF621DD1204AD3BFA0675B49BE3279")
+addNTA("example")
+addNTA("example.com", "some reason")
 """
 
     def testTrustanchorDotServer(self):
@@ -25,6 +27,17 @@ addDS("powerdns.com", "44030 8 1 B763646757DF621DD1204AD3BFA0675B49BE3279")
         self.assertRcodeEqual(result, dns.rcode.NOERROR)
         self.assertRRsetInAnswer(result, expected)
 
+    def testNegativerustanchorDotServer(self):
+        expected = dns.rrset.from_text_list(
+            'negativetrustanchor.server.', 86400, dns.rdataclass.CH, 'TXT',
+            ['"example."', '"example.com. some reason"'])
+        query = dns.message.make_query('negativetrustanchor.server', 'TXT',
+                                       dns.rdataclass.CH)
+        result = self.sendUDPQuery(query)
+
+        self.assertRcodeEqual(result, dns.rcode.NOERROR)
+        self.assertRRsetInAnswer(result, expected)
+
 
 class testTrustAnchorsDisabled(RecursorTest):
     """This test will do a query for "trustanchor.server CH TXT" and hopes to get
@@ -44,3 +57,10 @@ class testTrustAnchorsDisabled(RecursorTest):
         result = self.sendUDPQuery(query)
 
         self.assertRcodeEqual(result, dns.rcode.SERVFAIL)
+
+    def testNegativerustanchorDotServer(self):
+        query = dns.message.make_query('negativetrustanchor.server', 'TXT',
+                                       dns.rdataclass.CH)
+        result = self.sendUDPQuery(query)
+
+        self.assertRcodeEqual(result, dns.rcode.SERVFAIL)