--- /dev/null
+import dns
+from recursortests import RecursorTest
+import os
+
+class BasicDNSSEC(RecursorTest):
+ __test__ = False
+ _config_template = """dnssec=validate"""
+
+ @classmethod
+ def setUp(cls):
+ confdir = os.path.join('configs', cls._confdir)
+ cls.wipeRecursorCache(confdir)
+
+ @classmethod
+ def sendQuery(self, name, rdtype):
+ """Helper function that creates the query"""
+ msg = dns.message.make_query(name, rdtype, want_dnssec=True)
+ msg.flags |= dns.flags.AD
+
+ return self.sendUDPQuery(msg)
+
+ def testSecureAnswer(self):
+ res = self.sendQuery('ns.secure.example.', 'A')
+ expected = dns.rrset.from_text('ns.secure.example.', 0, dns.rdataclass.IN, 'A', '{prefix}.10'.format(prefix=self._PREFIX))
+
+ self.assertRcodeEqual(res, dns.rcode.NOERROR)
+ self.assertMatchingRRSIGInAnswer(res, expected)
+ self.assertMessageIsAuthenticated(res)
+
+ def testInsecureAnswer(self):
+ res = self.sendQuery('node1.insecure.example.', 'A')
+
+ self.assertNoRRSIGsInAnswer(res)
+ self.assertRcodeEqual(res, dns.rcode.NOERROR)
+
+ def testBogusAnswer(self):
+ res = self.sendQuery('ted.bogus.example.', 'A')
+
+ self.assertRcodeEqual(res, dns.rcode.SERVFAIL)
+ self.assertAnswerEmpty(res)
+
+ def testSecureNXDOMAIN(self):
+ res = self.sendQuery('nxdomain.secure.example.', 'A')
+
+ self.assertRcodeEqual(res, dns.rcode.NXDOMAIN)
+
+ def testInsecureNXDOMAIN(self):
+ res = self.sendQuery('nxdomain.insecure.example.', 'A')
+
+ self.assertRcodeEqual(res, dns.rcode.NXDOMAIN)
+
+ def testBogusNXDOMAIN(self):
+ res = self.sendQuery('nxdomain.bogus.example.', 'A')
+
+ self.assertRcodeEqual(res, dns.rcode.SERVFAIL)
+
+ def testSecureOptoutAnswer(self):
+ res = self.sendQuery('node1.secure.optout.example.', 'A')
+ expected = dns.rrset.from_text('node1.secure.optout.example.', 0, dns.rdataclass.IN, 'A', '192.0.2.8')
+
+ self.assertRcodeEqual(res, dns.rcode.NOERROR)
+ self.assertMatchingRRSIGInAnswer(res, expected)
+ self.assertMessageIsAuthenticated(res)
+
+ def testInsecureOptoutAnswer(self):
+ res = self.sendQuery('node1.insecure.optout.example.', 'A')
+
+ self.assertRcodeEqual(res, dns.rcode.NOERROR)
+ self.assertNoRRSIGsInAnswer(res)
insecure.example. 3600 IN NS ns.insecure.example.
ns.insecure.example. 3600 IN A {prefix}.13
+
+optout.example. 3600 IN NS ns1.optout.example.
+optout.example. 3600 IN DS 59332 13 1 e664f886ae1b5df03d918bc1217d22afc29925b9
+ns1.optout.example. 3600 IN A {prefix}.14
""",
'secure.example': """
secure.example. 3600 IN SOA {soa}
ns1.insecure.example. 3600 IN A {prefix}.13
node1.insecure.example. 3600 IN A 192.0.2.6
+ """,
+ 'optout.example': """
+optout.example. 3600 IN SOA {soa}
+optout.example. 3600 IN NS ns1.optout.example.
+ns1.optout.example. 3600 IN A {prefix}.14
+
+insecure.optout.example. 3600 IN NS ns1.insecure.optout.example.
+ns1.insecure.optout.example. 3600 IN A {prefix}.15
+
+secure.optout.example. 3600 IN NS ns1.secure.optout.example.
+secure.optout.example. 3600 IN DS 64215 13 1 b88284d7a8d8605c398e8942262f97b9a5a31787
+ns1.secure.optout.example. 3600 IN A {prefix}.15
+ """,
+ 'insecure.optout.example': """
+insecure.optout.example. 3600 IN SOA {soa}
+insecure.optout.example. 3600 IN NS ns1.insecure.optout.example.
+ns1.insecure.optout.example. 3600 IN A {prefix}.15
+
+node1.insecure.optout.example. 3600 IN A 192.0.2.7
+ """,
+ 'secure.optout.example': """
+secure.optout.example. 3600 IN SOA {soa}
+secure.optout.example. 3600 IN NS ns1.secure.optout.example.
+ns1.secure.optout.example. 3600 IN A {prefix}.15
+
+node1.secure.optout.example. 3600 IN A 192.0.2.8
"""
}
Algorithm: 13 (ECDSAP256SHA256)
PrivateKey: f5jV7Q8kd5hDpMWObsuQ6SQda0ftf+JrO3uZwEg6nVw=
""",
+
+ 'optout.example': """
+Private-key-format: v1.2
+Algorithm: 13 (ECDSAP256SHA256)
+PrivateKey: efmq9G+J4Y2iPnIBRwJiy6Z/nIHSzpsCy/7XHhlS19A=
+ """,
+
+ 'secure.optout.example': """
+Private-key-format: v1.2
+Algorithm: 13 (ECDSAP256SHA256)
+PrivateKey: xcNUxt1Knj14A00lKQFDboluiJyM2f7FxpgsQaQ3AQ4=
+ """
}
# This dict is keyed with the suffix of the IP address and its value
'10': ['example'],
'11': ['example'],
'12': ['bogus.example'],
- '13': ['insecure.example']
+ '13': ['insecure.example'],
+ '14': ['optout.example'],
+ '15': ['insecure.optout.example', 'secure.optout.example']
}
_auth_cmd = ['authbind',
cls.generateAuthConfig(authconfdir)
cls.generateAuthNamedConf(authconfdir, zones)
- for zonename, content in cls._zones.items():
- cls.generateAuthZone(authconfdir, zonename, content)
- if cls._zone_keys.get(zonename, None):
- cls.secureZone(authconfdir, zonename, cls._zone_keys.get(zonename))
+ for zone in zones:
+ cls.generateAuthZone(authconfdir,
+ zone,
+ cls._zones[zone])
+ if cls._zone_keys.get(zone, None):
+ cls.secureZone(authconfdir, zone, cls._zone_keys.get(zone))
@classmethod
def startAllAuth(cls, confdir):
@classmethod
def startAuth(cls, confdir, ipaddress):
print("Launching pdns_server..")
- authcmd = cls._auth_cmd
+ authcmd = list(cls._auth_cmd)
authcmd.append('--config-dir=%s' % confdir)
authcmd.append('--local-address=%s' % ipaddress)
print(' '.join(authcmd))
--- /dev/null
+from basicDNSSEC import BasicDNSSEC
+import unittest
+
+class basicNSEC(BasicDNSSEC):
+ __test__ = True
+ _confdir = 'basicNSEC'
--- /dev/null
+from basicDNSSEC import BasicDNSSEC
+import os
+import subprocess
+
+class basicNSEC3(BasicDNSSEC):
+ __test__ = True
+ _confdir = 'basicNSEC3'
+
+ @classmethod
+ def secureZone(cls, confdir, zonename, key=None):
+ zone = '.' if zonename == 'ROOT' else zonename
+ if not key:
+ pdnsutilCmd = [os.environ['PDNSUTIL'],
+ '--config-dir=%s' % confdir,
+ 'secure-zone',
+ zone]
+ else:
+ keyfile = os.path.join(confdir, 'dnssec.key')
+ with open(keyfile, 'w') as fdKeyfile:
+ fdKeyfile.write(key)
+
+ pdnsutilCmd = [os.environ['PDNSUTIL'],
+ '--config-dir=%s' % confdir,
+ 'import-zone-key',
+ zone,
+ keyfile,
+ 'active',
+ 'ksk']
+
+ print ' '.join(pdnsutilCmd)
+ try:
+ subprocess.check_output(pdnsutilCmd, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ print e.output
+ raise
+
+ params = "1 0 100 AABBCCDDEEFF112233"
+
+ if zone == "optout.example":
+ params = "1 1 100 AABBCCDDEEFF112233"
+
+ pdnsutilCmd = [os.environ['PDNSUTIL'],
+ '--config-dir=%s' % confdir,
+ 'set-nsec3',
+ zone,
+ params]
+
+ print ' '.join(pdnsutilCmd)
+ try:
+ subprocess.check_output(pdnsutilCmd, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ print e.output
+ raise