]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: Add `ReadTrustAnchorsFromFile` function
authorPieter Lexis <pieter.lexis@powerdns.com>
Fri, 12 Oct 2018 13:35:16 +0000 (15:35 +0200)
committerPieter Lexis <pieter.lexis@powerdns.com>
Sat, 13 Oct 2018 15:15:14 +0000 (17:15 +0200)
This allows the recursor to read the output file from `unbound-anchor`
and use these kind of files for trust anchors. This will enable
distributions to ship DNSSEC anchors with their system and use them.

pdns/rec-lua-conf.cc
pdns/recursordist/docs/dnssec.rst
pdns/recursordist/docs/lua-config/dnssec.rst
regression-tests.recursor-dnssec/recursortests.py
regression-tests.recursor-dnssec/root.keys [new file with mode: 0644]
regression-tests.recursor-dnssec/test_NTA.py
regression-tests.recursor-dnssec/test_ReadTrustAnchorsFromFile.py [new file with mode: 0644]

index 3b5284dde1330e166e4139ea9fd2ea0dd04bcc38..76e12228368bb78f7d39d5e685be99e850b40f10 100644 (file)
@@ -15,6 +15,9 @@
 #include "validate.hh"
 #include "validate-recursor.hh"
 #include "root-dnssec.hh"
+#include "dnssecinfra.hh"
+#include "dnsseckeeper.hh"
+#include "zoneparser-tng.hh"
 
 GlobalStateHolder<LuaConfigItems> g_luaconfs; 
 
@@ -408,6 +411,39 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de
         lci.negAnchors.clear();
     });
 
+  Lua.writeFunction("readTrustAnchorsFromFile", [&lci](const std::string& fname) {
+      warnIfDNSSECDisabled("Warning: reading Trust Anchors from file (readTrustAnchorsFromFile), but dnssec is set to 'off'!");
+      auto zp = ZoneParserTNG(fname);
+      DNSResourceRecord rr;
+      DNSRecord dr;
+      try {
+        while(zp.get(rr)) {
+          dr = DNSRecord(rr);
+          if (rr.qtype == QType::DS) {
+            auto dsr = getRR<DSRecordContent>(dr);
+            if (dsr == nullptr) {
+              throw PDNSException("Unable to parse DS record '" + rr.qname.toString() + " " + rr.getZoneRepresentation() + "'");
+            }
+            lci.dsAnchors[rr.qname].insert(*dsr);
+          }
+          if (rr.qtype == QType::DNSKEY) {
+            auto dnskeyr = getRR<DNSKEYRecordContent>(dr);
+            if (dnskeyr == nullptr) {
+              throw PDNSException("Unable to parse DNSKEY record '" + rr.qname.toString() + " " + rr.getZoneRepresentation() +"'");
+            }
+            auto dsr = makeDSFromDNSKey(rr.qname, *dnskeyr, DNSSECKeeper::SHA256);
+            lci.dsAnchors[rr.qname].insert(dsr);
+          }
+        }
+      }
+      catch (const std::exception &e) {
+        throw PDNSException("Error while reading Trust Anchors from file (readTrustAnchorsFromFile) '" + fname + "': " + e.what());
+      }
+      catch (...) {
+        throw PDNSException("Error while reading Trust Anchors from file (readTrustAnchorsFromFile) '" + fname + "'");
+      }
+    });
+
 #if HAVE_PROTOBUF
   Lua.writeFunction("setProtobufMasks", [&lci](const uint8_t maskV4, uint8_t maskV6) {
       lci.protobufMaskV4 = maskV4;
index 2e6d456c6fd3518c36d575f7ddba7ff33bf8b3fd..b5bd5b9a41d2668b54d9b9e475d2c31f91e80f01 100644 (file)
@@ -100,6 +100,20 @@ For PowerDNS Recursor 4.1.x and below, use the :func:`addDS` function instead.
 
 Now (re)start the recursor to load these trust anchors.
 
+Reading trust anchors from files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Since version 4.2.0 of the PowerDNS Recursor, it is also possible to read the Trust Anchors from a BIND-style zonefile.
+Only the DS and DNSKEY records from this file are read.
+Debian and its derivatives ship the ``dns-root-data`` package that contains the DNSSEC root trust anchors in ``/usr/share/dns/root.key``.
+
+To only use the distribution-provided Trust Anchors, add the following to the :ref:`setting-lua-config-file`:
+
+.. sourcecode:: lua
+
+  clearTA() -- Remove built-in trust-anchors
+  readTrustAnchorsFromFile("/usr/share/dns/root.key") -- Use these keys
+
 Runtime Configuration of Trust Anchors
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 To change or add trust anchors at runtime, use the :doc:`manpages/rec_control.1` tool.
index 4061bde9506ce0ba7d718809f71d651e0576328c..17b189d339d358cc9a397ec1bac61f15e3b5cc60 100644 (file)
@@ -56,3 +56,12 @@ This page only documents the Lua functions for DNSSEC configuration
   not given, remove *all* negative trust anchors instead.
 
   :param str name: The name in the DNS tree from where this NTA should be removed
+
+.. function:: readTrustAnchorsFromFile(fname)
+
+  .. versionadded:: 4.2.0
+
+  Reads all DS and DNSKEY records from ``fname`` (a BIND zone file) and adds these to the Trust Anchors.
+  This function can be used to read distribution provided trust anchors, as for instance ``/usr/share/dns/root.key`` from Debian's ``dns-root-data`` package.
+
+  :param str fname: Path to a zone file with Trust Anchors
index 8bfafa05dba7574371910106e6174a3947833467..d2a286858f29d6279a944bc557f89df54ae14f07 100644 (file)
@@ -445,7 +445,7 @@ distributor-threads=1""".format(confdir=confdir,
                 luaconfpath = os.path.join(confdir, 'conffile.lua')
                 with open(luaconfpath, 'w') as luaconf:
                     if cls._root_DS:
-                        luaconf.write("addDS('.', '%s')\n" % cls._root_DS)
+                        luaconf.write("addTA('.', '%s')\n" % cls._root_DS)
                     if cls._lua_config_file:
                         luaconf.write(cls._lua_config_file)
                 conf.write("lua-config-file=%s\n" % luaconfpath)
diff --git a/regression-tests.recursor-dnssec/root.keys b/regression-tests.recursor-dnssec/root.keys
new file mode 100644 (file)
index 0000000..16763f9
--- /dev/null
@@ -0,0 +1,3 @@
+.              300     IN      DNSKEY  257 3 13 aPHAAOTdxA8XxiUo8YTOXPG7uRXPA4XFhcnJ/I13+f/0I/B0TobNDG0t aRjsp/rezR1o0DXh0fb4vvC+STbPog== ; Should be converted to DS
+.              3600    IN      DS      36914 13 2 C94ED457FF79AFE03804C26CE4FA832687DB92BC231AFF98617791FC 71A65870 ; Will be used as-is
+.              1200    IN      A       192.0.2.1 ; Should be ignored
index b21d7f6b6b5d061afb70d735ece09228792277b7..9b4e18dfd2c0ca0595b9dd88b110c052853fdf3c 100644 (file)
@@ -7,7 +7,7 @@ class testSimple(RecursorTest):
     _config_template = """dnssec=validate"""
     _lua_config_file = """addNTA("bogus.example")
 addNTA('secure.optout.example', 'Should be Insecure, even with DS configured')
-addDS('secure.optout.example', '64215 13 1 b88284d7a8d8605c398e8942262f97b9a5a31787')"""
+addTA('secure.optout.example', '64215 13 1 b88284d7a8d8605c398e8942262f97b9a5a31787')"""
 
     def testDirectNTA(self):
         """Ensure a direct query to a bogus name with an NTA is Insecure"""
diff --git a/regression-tests.recursor-dnssec/test_ReadTrustAnchorsFromFile.py b/regression-tests.recursor-dnssec/test_ReadTrustAnchorsFromFile.py
new file mode 100644 (file)
index 0000000..c150703
--- /dev/null
@@ -0,0 +1,30 @@
+import os
+import subprocess
+from recursortests import RecursorTest
+
+
+class testReadTrustAnchorsFronFile(RecursorTest):
+    _confdir = 'ReadTAsFromFile'
+
+    _config_template = """dnssec=validate"""
+    _lua_config_file = """clearTA()
+readTrustAnchorsFromFile('root.keys')"""
+
+    def testCorrectFile(self):
+        """Ensure the file is read correctly"""
+        rec_controlCmd = [os.environ['RECCONTROL'],
+                          '--config-dir=%s' % 'configs/' + self._confdir,
+                          'get-tas']
+        expected = """Configured Trust Anchors:
+.
+\t\t36914 13 2 c94ed457ff79afe03804c26ce4fa832687db92bc231aff98617791fc71a65870
+\t\t42924 13 2 b49e0aafd6e147742afb9eab0e76af0546357dc6c61bf67d7c745cf6f43f460e
+"""
+        try:
+            ret = subprocess.check_output(rec_controlCmd, stderr=subprocess.STDOUT)
+            self.assertEqual(ret, expected)
+
+        except subprocess.CalledProcessError as e:
+            print e.output
+            raise
+