f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt#!/usr/bin/python
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt############################################################################
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt#
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# Permission to use, copy, modify, and/or distribute this software for any
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# purpose with or without fee is hereby granted, provided that the above
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# copyright notice and this permission notice appear in all copies.
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt#
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# PERFORMANCE OF THIS SOFTWARE.
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt############################################################################
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# kasp2policy.py
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# This translates the Keys section of a KASP XML file into a dnssec.policy
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# file that can be used by dnssec-keymgr.
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt############################################################################
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Huntfrom xml.etree import cElementTree as ET
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Huntfrom collections import defaultdict
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Huntfrom isc import dnskey
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Huntimport ply.yacc as yacc
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Huntimport ply.lex as lex
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Huntimport re
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt############################################################################
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# Translate KASP duration values into seconds
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt############################################################################
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Huntclass kasptime:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt class ktlex:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt tokens = ( 'P', 'T', 'Y', 'M', 'D', 'H', 'S', 'NUM' )
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt t_P = r'(?i)P'
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt t_T = r'(?i)T'
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt t_Y = r'(?i)Y'
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt t_M = r'(?i)M'
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt t_D = r'(?i)D'
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt t_H = r'(?i)H'
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt t_S = r'(?i)S'
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def t_NUM(self, t):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt r'\d+'
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt t.value = int(t.value)
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt return t
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def t_error(self, t):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("Illegal character '%s'" % t.value[0])
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt t.lexer.skip(1)
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def __init__(self):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt self.lexer = lex.lex(object=self)
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def __init__(self):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt self.lexer = self.ktlex()
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt self.tokens = self.lexer.tokens
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt self.parser = yacc.yacc(debug=False, write_tables=False, module=self)
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def parse(self, text):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt self.lexer.lexer.lineno = 0
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt return self.parser.parse(text)
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def p_ktime_4(self, p):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt "ktime : P periods T times"
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt p[0] = p[2] + p[4]
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def p_ktime_3(self, p):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt "ktime : P T times"
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt p[0] = p[3]
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def p_ktime_2(self, p):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt "ktime : P periods"
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt p[0] = p[2]
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def p_periods_1(self, p):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt "periods : period"
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt p[0] = p[1]
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def p_periods_2(self, p):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt "periods : periods period"
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt p[0] = p[1] + p[2]
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def p_times_1(self, p):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt "times : time"
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt p[0] = p[1]
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def p_times_2(self, p):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt "times : times time"
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt p[0] = p[1] + p[2]
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def p_period(self, p):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt '''period : NUM Y
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt | NUM M
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt | NUM D'''
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if p[2].lower() == 'y':
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt p[0] = int(p[1]) * 31536000
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt elif p[2].lower() == 'm':
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt p[0] = int(p[1]) * 2592000
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt elif p[2].lower() == 'd':
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt p[0] += int(p[1]) * 86400
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def p_time(self, p):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt '''time : NUM H
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt | NUM M
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt | NUM S'''
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if p[2].lower() == 'h':
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt p[0] = int(p[1]) * 3600
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt elif p[2].lower() == 'm':
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt p[0] = int(p[1]) * 60
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt elif p[2].lower() == 's':
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt p[0] = int(p[1])
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def p_error(self, p):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("Syntax error")
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt############################################################################
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# Load the contents of a KASP XML file as a python dictionary
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt############################################################################
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Huntclass kasp():
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt @staticmethod
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def _todict(t):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt d = {t.tag: {} if t.attrib else None}
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt children = list(t)
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if children:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt dd = defaultdict(list)
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt for dc in map(kasp._todict, children):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt for k, v in dc.iteritems():
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt dd[k].append(v)
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt d = {t.tag:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt {k:v[0] if len(v) == 1 else v for k, v in dd.iteritems()}}
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if t.attrib:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt d[t.tag].update(('@' + k, v) for k, v in t.attrib.iteritems())
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if t.text:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt text = t.text.strip()
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if children or t.attrib:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if text:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt d[t.tag]['#text'] = text
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt else:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt d[t.tag] = text
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt return d
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def __init__(self, filename):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt self._dict = kasp._todict(ET.parse(filename).getroot())
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def __getitem__(self, key):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt return self._dict[key]
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def __len__(self):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt return len(self._dict)
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def __iter__(self):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt return self._dict.__iter__()
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt def __repr__(self):
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt return repr(self._dict)
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt############################################################################
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt# Load the contents of a KASP XML file as a python dictionary
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt############################################################################
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Huntif __name__ == "__main__":
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt from pprint import *
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt import sys
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if len(sys.argv) < 2:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("Usage: kasp2policy <filename>")
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt exit(1)
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt try:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt kinfo = kasp(sys.argv[1])
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt except:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("%s: unable to load KASP file '%s'" % (sys.argv[0], sys.argv[1]))
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt exit(1)
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt kt = kasptime()
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt first = True
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt for p in kinfo['KASP']['Policy']:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if not p['@name'] or not p['Keys']: continue
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if not first:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("")
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt first = False
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if p['Description']:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt d = p['Description'].strip()
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("# %s" % re.sub(r"\n\s*", "\n# ", d))
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("policy %s {" % p['@name'])
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt ksk = p['Keys']['KSK']
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt zsk = p['Keys']['ZSK']
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt kalg = ksk['Algorithm']
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt zalg = zsk['Algorithm']
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt algnum = kalg['#text'] or zalg['#text']
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if algnum:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("\talgorithm %s;" % dnskey.algstr(int(algnum)))
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if p['Keys']['TTL']:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("\tkeyttl %d;" % kt.parse(p['Keys']['TTL']))
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if kalg['@length']:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("\tkey-size ksk %d;" % int(kalg['@length']))
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if zalg['@length']:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("\tkey-size zsk %d;" % int(zalg['@length']))
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if ksk['Lifetime']:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("\troll-period ksk %d;" % kt.parse(ksk['Lifetime']))
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if zsk['Lifetime']:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("\troll-period zsk %d;" % kt.parse(zsk['Lifetime']))
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if ksk['Standby']:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("\tstandby ksk %d;" % int(ksk['Standby']))
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt if zsk['Standby']:
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("\tstandby zsk %d;" % int(zsk['Standby']))
f6096b958c8b58c4709860d7c4dcdde5deeacb7aEvan Hunt print("};")