]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
First pass at DS check tool
authorEvan Hunt <each@isc.org>
Wed, 11 Apr 2012 06:30:53 +0000 (23:30 -0700)
committerMark Andrews <marka@isc.org>
Thu, 28 Jun 2012 06:44:00 +0000 (16:44 +1000)
Currently hard-coded to check for 'isc.org'; later this will
be a command line argument.

contrib/dnssec/checkds.py [new file with mode: 0644]

diff --git a/contrib/dnssec/checkds.py b/contrib/dnssec/checkds.py
new file mode 100644 (file)
index 0000000..d4b5b08
--- /dev/null
@@ -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()