+def check_ds_delegation(resolver, zone, args):
+ retval = 0
+ try:
+ dses = dict()
+ result = resolver.resolve(zone, RR_TYPE_DS, secure=True)
+
+ for entry in result.data.data:
+ tag, algo, digest = struct.unpack("!HBB", entry[:4])
+ value = entry[4:]
+ dses[tag] = DSRecord(tag, algo, digest, value)
+
+ dnskeys = dict()
+ result = resolver.resolve(zone, RR_TYPE_DNSKEY, secure=True)
+
+ for entry in result.data.data:
+ flags, protocol, algorithm = struct.unpack("!HBB", entry[:4])
+ value = entry[4:]
+ digest = sha256()
+ for label in zone.split('.'):
+ digest.update(struct.pack('b', len(label)))
+ digest.update(label)
+ digest.update(struct.pack('b', 0))
+ digest.update(entry)
+ if flags & 0x1 == 1 and (flags >> 7) & 0x1 == 0:
+ dnskeys[_keytag(entry)] = DNSKEYRecord(flags, protocol, algorithm, value,digest.digest())
+
+ for key in dnskeys:
+ dnskey = dnskeys[key]
+ if not key in dses:
+ logging.warn("No DS record found for %s", dnskey)
+ retval = max(retval, 1)
+
+ else:
+ ds = dses[key]
+ if ds.digest != dnskey.digest:
+ logging.error("DS and DNSKEY do not match: %s %s", ds, dnskey)
+ retval = 2
+
+ for ds in dses:
+ if not ds in dnskeys:
+ logging.warn("Unused DS record: %s", dses[ds])
+ retval = max(retval, 1)
+
+ return retval
+
+ except ResolverException as e:
+ logging.exception("check_ds_delegation: %s", e.message)
+
+