From: Evan Hunt Date: Wed, 11 Apr 2012 06:30:53 +0000 (-0700) Subject: First pass at DS check tool X-Git-Tag: v9.10.0a1~1062^2^2~16 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=cbd38b4caaaac4832e21f4e7ca29dedb546651a9;p=thirdparty%2Fbind9.git First pass at DS check tool Currently hard-coded to check for 'isc.org'; later this will be a command line argument. --- diff --git a/contrib/dnssec/checkds.py b/contrib/dnssec/checkds.py new file mode 100644 index 00000000000..d4b5b086231 --- /dev/null +++ b/contrib/dnssec/checkds.py @@ -0,0 +1,200 @@ +#!/usr/bin/python +import argparse +import pprint +import os + +class DSRR: + hashalgs = {1: 'SHA-1', 2: 'SHA-256', 3: 'GOST'} + rrname='' + rrclass='IN' + rrtype='DS' + keyid=None + keyalg=None + hashalg=None + digest='' + ttl=0 + + def __init__(self, rrtext): + if not rrtext: + return + + fields = rrtext.split() + if len(fields) < 7: + return + + self.rrname = fields[0].lower() + fields = fields[1:] + if fields[0].upper() in ['IN','CH','HS']: + self.rrclass = fields[0].upper() + fields = fields[1:] + else: + self.ttl = int(fields[0]) + self.rrclass = fields[1].upper() + fields = fields[2:] + + if fields[0].upper() != 'DS': + raise Exception + + self.rrtype = 'DS' + self.keyid = int(fields[1]) + self.keyalg = int(fields[2]) + self.hashalg = int(fields[3]) + self.digest = ''.join(fields[4:]).upper() + + def __repr__(self): + return('%s %s %s %d %d %d %s' % + (self.rrname, self.rrclass, self.rrtype, self.keyid, + self.keyalg, self.hashalg, self.digest)) + + def __eq__(self, other): + return self.__repr__() == other.__repr__() + +class DLVRR: + hashalgs = {1: 'SHA-1', 2: 'SHA-256', 3: 'GOST'} + parent='' + dlvname='' + rrname='IN' + rrclass='IN' + rrtype='DLV' + keyid=None + keyalg=None + hashalg=None + digest='' + ttl=0 + + def __init__(self, rrtext, dlvname = 'dlv.isc.org'): + if not rrtext: + return + + fields = rrtext.split() + if len(fields) < 7: + return + + self.dlvname = dlvname.lower() + parent = fields[0].lower().strip('.').split('.') + parent.reverse() + dlv = dlvname.split('.') + dlv.reverse() + while len(dlv) != 0 and len(parent) != 0 and parent[0] == dlv[0]: + parent = parent[1:] + dlv = dlv[1:] + if len(dlv) != 0: + raise Exception + parent.reverse() + self.parent = '.'.join(parent) + self.rrname = self.parent + '.' + self.dlvname + + fields = fields[1:] + if fields[0].upper() in ['IN','CH','HS']: + self.rrclass = fields[0].upper() + fields = fields[1:] + else: + self.ttl = int(fields[0]) + self.rrclass = fields[1].upper() + fields = fields[2:] + + if fields[0].upper() != 'DLV': + raise Exception + + self.rrtype = 'DLV' + self.keyid = int(fields[1]) + self.keyalg = int(fields[2]) + self.hashalg = int(fields[3]) + self.digest = ''.join(fields[4:]).upper() + + def __repr__(self): + return('%s %s %s %d %d %d %s' % + (self.rrname, self.rrclass, self.rrtype, + self.keyid, self.keyalg, self.hashalg, self.digest)) + + def __eq__(self, other): + return self.__repr__() == other.__repr__() + +###################################################################### +# Main +###################################################################### +def main(): + zone='isc.org' + zone = zone.strip('.') + + lookaside='dlv.isc.org' + lookaside = lookaside .strip('.') + + # + # Fetch DS records from DNS + # + dslist=[] + fp=os.popen("/usr/local/bin/dig +noall +answer -t ds " + zone) + for line in fp: + dslist.append(DSRR(line)) + dslist = sorted(dslist, key=lambda ds: (ds.keyid, ds.keyalg, ds.hashalg)) + fp.close() + + # + # Fetch DNSKEY records from DNS and generate DS records from them + # + dsklist=[] + fp=os.popen("/usr/local/bin/dig +noall +answer -t dnskey " + zone + + " | /usr/local/sbin/dnssec-dsfromkey -f - " + zone) + for line in fp: + dsklist.append(DSRR(line)) + fp.close() + + # + # Compare real DS values to generated values + # + found = False + for ds in dsklist: + if ds in dslist: + print ("DS for KSK %s/%03d/%05d (%s) found in parent" % + (ds.rrname.strip('.'), ds.keyalg, + ds.keyid, DSRR.hashalgs[ds.hashalg])) + found = True + + if not found: + print ("No DS records found covering %s/DNSKEY" % zone) + + if found or not lookaside: + exit(0 if found else 1) + + # + # Fetch DLV records from DNS + # + dlvlist=[] + fp=os.popen("/usr/local/bin/dig +noall +answer -t dlv " + + zone + '.' + lookaside) + for line in fp: + dlvlist.append(DLVRR(line)) + dlvlist = sorted(dlvlist, + key=lambda dlv: (dlv.keyid, dlv.keyalg, dlv.hashalg)) + fp.close() + + # + # Fetch DNSKEY records from DNS and generate DLV records from them + # + dlvklist=[] + fp=os.popen("/usr/local/bin/dig +noall +answer -t dnskey " + zone + + " | /usr/local/sbin/dnssec-dsfromkey -f - -l " + + lookaside + ' ' + zone) + for line in fp: + dlvklist.append(DLVRR(line)) + fp.close() + + # + # Compare real DLV values to generated values + # + for dlv in dlvklist: + if dlv in dlvlist: + print ("DLV for KSK %s/%03d/%05d (%s) found in %s" % + (dlv.parent, dlv.keyalg, dlv.keyid, + DLVRR.hashalgs[dlv.hashalg], dlv.dlvname)) + found = True + + if not found: + print ("No DLV records found covering %s/DNSKEY" % zone) + + exit(0 if found else 1) + + +if __name__ == "__main__": + main()