ns1.islandofsecurity.example. 3600 IN A {prefix}.9
node1.islandofsecurity.example. 3600 IN A 192.0.2.20
- """
+ """,
+ 'undelegated.secure.example': """
+undelegated.secure.example. 3600 IN SOA {soa}
+undelegated.secure.example. 3600 IN NS ns1.undelegated.secure.example.
+
+node1.undelegated.secure.example. 3600 IN A 192.0.2.21
+ """,
+ 'undelegated.insecure.example': """
+undelegated.insecure.example. 3600 IN SOA {soa}
+undelegated.insecure.example. 3600 IN NS ns1.undelegated.insecure.example.
+
+node1.undelegated.insecure.example. 3600 IN A 192.0.2.22
+ """,
}
# The private keys for the zones (note that DS records should go into
'9': ['secure.example', 'islandofsecurity.example'],
'10': ['example'],
'11': ['example'],
- '12': ['bogus.example'],
+ '12': ['bogus.example', 'undelegated.secure.example', 'undelegated.insecure.example'],
'13': ['insecure.example', 'insecure.sub2.secure.example'],
'14': ['optout.example'],
'15': ['insecure.optout.example', 'secure.optout.example']
import dns
import socket
import copy
+import os
from recursortests import RecursorTest
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
class testInterop(RecursorTest):
_confdir = 'Interop'
- _config_template = """dnssec=validate"""
+ _config_template = """dnssec=validate
+packetcache-ttl=0 # explicitly disable packetcache
+forward-zones=undelegated.secure.example=%s.12
+forward-zones+=undelegated.insecure.example=%s.12
+ """ % (os.environ['PREFIX'], os.environ['PREFIX'])
def testFORMERR(self):
"""
self.assertMessageHasFlags(res, ['QR', 'RA', 'RD'], ['DO'])
self.assertRRsetInAnswer(res, expected)
+ def testUndelegatedForwardedZoneExisting(self):
+ """
+ #4369. Ensure we SERVFAIL when forwarding to undelegated zones for a name that exists
+ """
+
+ query = dns.message.make_query('node1.undelegated.secure.example.', 'A')
+ query.flags |= dns.flags.AD
+
+ # twice, so we hit the record cache
+ self.sendUDPQuery(query)
+ res = self.sendUDPQuery(query)
+
+ self.assertRcodeEqual(res, dns.rcode.SERVFAIL)
+ self.assertMessageHasFlags(res, ['QR', 'RA', 'RD'], ['DO'])
+
+ def testUndelegatedForwardedZoneNXDOMAIN(self):
+ """
+ #4369. Ensure we SERVFAIL when forwarding to undelegated zones for a name that does not exist
+ """
+
+ query = dns.message.make_query('node2.undelegated.secure.example.', 'A')
+ query.flags |= dns.flags.AD
+
+ # twice, so we hit the negative record cache
+ self.sendUDPQuery(query)
+ res = self.sendUDPQuery(query)
+
+ self.assertRcodeEqual(res, dns.rcode.SERVFAIL)
+ self.assertMessageHasFlags(res, ['QR', 'RA', 'RD'], ['DO'])
+
+ def testUndelegatedForwardedInsecureZoneExisting(self):
+ """
+ #4369. Ensure we answer when forwarding to an undelegated zone in an insecure zone for a name that exists
+ """
+
+ expected = dns.rrset.from_text('node1.undelegated.insecure.example.', 0, dns.rdataclass.IN, 'A', '192.0.2.22')
+ query = dns.message.make_query('node1.undelegated.insecure.example.', 'A')
+ query.flags |= dns.flags.AD
+
+ # twice, so we hit the record cache
+ self.sendUDPQuery(query)
+ res = self.sendUDPQuery(query)
+
+ self.assertRcodeEqual(res, dns.rcode.NOERROR)
+ self.assertMessageHasFlags(res, ['QR', 'RA', 'RD'], ['DO'])
+ self.assertRRsetInAnswer(res, expected)
+
+ def testUndelegatedForwardedInsecureZoneNXDOMAIN(self):
+ """
+ #4369. Ensure we answer when forwarding to an undelegated zone in an insecure zone for a name that does not exist
+ """
+
+ query = dns.message.make_query('node2.undelegated.insecure.example.', 'A')
+ query.flags |= dns.flags.AD
+
+ # twice, so we hit the negative record cache
+ self.sendUDPQuery(query)
+ res = self.sendUDPQuery(query)
+
+ self.assertRcodeEqual(res, dns.rcode.NXDOMAIN)
+ self.assertMessageHasFlags(res, ['QR', 'RA', 'RD'], ['DO'])
+
+
@classmethod
def startResponders(cls):
print("Launching responders..")