mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 05:57:52 +00:00
[master] add dnssec-coverage tool
3528. [func] New "dnssec-coverage" command scans the timing metadata for a set of DNSSEC keys and reports if a lapse in signing coverage has been scheduled inadvertently. (Note: This tool depends on python; it will not be built or installed on systems that do not have a python interpreter.) [RT #28098]
This commit is contained in:
parent
027591e157
commit
831f59eb43
7
CHANGES
7
CHANGES
@ -1,3 +1,10 @@
|
||||
3528. [func] New "dnssec-coverage" command scans the timing
|
||||
metadata for a set of DNSSEC keys and reports if a
|
||||
lapse in signing coverage has been scheduled
|
||||
inadvertently. (Note: This tool depends on python;
|
||||
it will not be built or installed on systems that
|
||||
do not have a python interpreter.) [RT #28098]
|
||||
|
||||
3527. [compat] Add a URI to allow applications to explicitly
|
||||
request a particular XML schema from the statistics
|
||||
channel, returning 404 if not supported. [RT #32481]
|
||||
|
2
bin/python/.gitignore
vendored
2
bin/python/.gitignore
vendored
@ -1,2 +1,4 @@
|
||||
dnssec-checkds
|
||||
dnssec-checkds.py
|
||||
dnssec-coverage
|
||||
dnssec-coverage.py
|
||||
|
@ -22,17 +22,19 @@ top_srcdir = @top_srcdir@
|
||||
|
||||
PYTHON = @PYTHON@
|
||||
|
||||
TARGETS = dnssec-checkds
|
||||
SRCS = dnssec-checkds.py
|
||||
TARGETS = dnssec-checkds dnssec-coverage
|
||||
SRCS = dnssec-checkds.py dnssec-coverage.py
|
||||
|
||||
MANPAGES = dnssec-checkds.8
|
||||
HTMLPAGES = dnssec-checkds.html
|
||||
MANPAGES = dnssec-checkds.8 dnssec-coverage.8
|
||||
HTMLPAGES = dnssec-checkds.html dnssec-coverage.html
|
||||
MANOBJS = ${MANPAGES} ${HTMLPAGES}
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
dnssec-checkds: dnssec-checkds.py
|
||||
|
||||
dnssec-coverage: dnssec-coverage.py
|
||||
|
||||
doc man:: ${MANOBJS}
|
||||
|
||||
docclean manclean maintainer-clean::
|
||||
@ -44,10 +46,12 @@ installdirs:
|
||||
|
||||
install:: ${TARGETS} installdirs
|
||||
${INSTALL_PROGRAM} dnssec-checkds@EXEEXT@ ${DESTDIR}${sbindir}
|
||||
${INSTALL_PROGRAM} dnssec-coverage@EXEEXT@ ${DESTDIR}${sbindir}
|
||||
${INSTALL_DATA} ${srcdir}/dnssec-checkds.8 ${DESTDIR}${mandir}/man8
|
||||
${INSTALL_DATA} ${srcdir}/dnssec-coverage.8 ${DESTDIR}${mandir}/man8
|
||||
|
||||
clean distclean::
|
||||
rm -f ${TARGETS}
|
||||
|
||||
distclean::
|
||||
rm -f dnssec-checkds.py
|
||||
rm -f dnssec-checkds.py dnssec-coverage.py
|
||||
|
228
bin/python/dnssec-coverage.docbook
Normal file
228
bin/python/dnssec-coverage.docbook
Normal file
@ -0,0 +1,228 @@
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY mdash "—">]>
|
||||
<!--
|
||||
- Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
|
||||
-
|
||||
- Permission to use, copy, modify, and/or distribute this software for any
|
||||
- purpose with or without fee is hereby granted, provided that the above
|
||||
- copyright notice and this permission notice appear in all copies.
|
||||
-
|
||||
- THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
- AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
- PERFORMANCE OF THIS SOFTWARE.
|
||||
-->
|
||||
|
||||
<refentry id="man.dnssec-coverage">
|
||||
<refentryinfo>
|
||||
<date>April 16, 2012</date>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle><application>dnssec-coverage</application></refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
<refmiscinfo>BIND9</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname><application>dnssec-coverage</application></refname>
|
||||
<refpurpose>checks future DNSKEY coverage for a zone</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<docinfo>
|
||||
<copyright>
|
||||
<year>2012</year>
|
||||
<holder>Internet Systems Consortium, Inc. ("ISC")</holder>
|
||||
</copyright>
|
||||
</docinfo>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>dnssec-coverage</command>
|
||||
<arg><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
|
||||
<arg><option>-f <replaceable class="parameter">file</replaceable></option></arg>
|
||||
<arg><option>-d <replaceable class="parameter">DNSKEY TTL</replaceable></option></arg>
|
||||
<arg><option>-m <replaceable class="parameter">max TTL</replaceable></option></arg>
|
||||
<arg><option>-r <replaceable class="parameter">interval</replaceable></option></arg>
|
||||
<arg><option>-c <replaceable class="parameter">compilezone path</replaceable></option></arg>
|
||||
<arg choice="opt">zone</arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>DESCRIPTION</title>
|
||||
<para><command>dnssec-coverage</command>
|
||||
verifies that the DNSSEC keys for a given zone or a set of zones
|
||||
have timing metadata set properly to ensure no future lapses in DNSSEC
|
||||
coverage.
|
||||
</para>
|
||||
<para>
|
||||
If <option>zone</option> is specified, then keys found in
|
||||
the key repository matching that zone are scanned, and an ordered
|
||||
list is generated of the events scheduled for that key (i.e.,
|
||||
publication, activation, inactivation, deletion). The list of
|
||||
events is walked in order of occurrence. Warnings are generated
|
||||
if any event is scheduled which could cause the zone to enter a
|
||||
state in which validation failures might occur: for example, if
|
||||
the number of published or active keys for a given algorithm drops
|
||||
to zero, or if a key is deleted from the zone too soon after a new
|
||||
key is rolled, and cached data signed by the prior key has not had
|
||||
time to expire from resolver caches.
|
||||
</para>
|
||||
<para>
|
||||
If <option>zone</option> is not specified, then all keys in the
|
||||
key repository will be scanned, and all zones for which there are
|
||||
keys will be analyzed. (Note: This method of reporting is only
|
||||
accurate if all the zones that have keys in a given repository
|
||||
share the same TTL parameters.)
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>OPTIONS</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>-f <replaceable class="parameter">file</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
If a <option>file</option> is specified, then the zone is
|
||||
read from that file; the largest TTL and the DNSKEY TTL are
|
||||
determined directly from the zone data, and the
|
||||
<option>-m</option> and <option>-d</option> options do
|
||||
not need to be specified on the command line.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-K <replaceable class="parameter">directory</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Sets the directory in which keys can be found. Defaults to the
|
||||
current working directory.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-m <replaceable class="parameter">maximum TTL</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Sets the value to be used as the maximum TTL for the zone or
|
||||
zones being analyzed when determining whether there is a
|
||||
possibility of validation failure. When a zone-signing key is
|
||||
deactivated, there must be enough time for the record in the
|
||||
zone with the longest TTL to have expired from resolver caches
|
||||
before that key can be purged from the DNSKEY RRset. If that
|
||||
condition does not apply, a warning will be generated.
|
||||
</para>
|
||||
<para>
|
||||
The length of the TTL can be set in seconds, or in larger units
|
||||
of time by adding a suffix: 'mi' for minutes, 'h' for hours,
|
||||
'd' for days, 'w' for weeks, 'mo' for months, 'y' for years.
|
||||
</para>
|
||||
<para>
|
||||
This option is mandatory unless the <option>-f</option> has
|
||||
been used to specify a zone file. (If <option>-f</option> has
|
||||
been specified, this option may still be used; it will overrde
|
||||
the value found in the file.)
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-d <replaceable class="parameter">DNSKEY TTL</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Sets the value to be used as the DNSKEY TTL for the zone or
|
||||
zones being analyzed when determining whether there is a
|
||||
possibility of validation failure. When a key is rolled (that
|
||||
is, replaced with a new key), there must be enough time
|
||||
for the old DNSKEY RRset to have expired from resolver caches
|
||||
before the new key is activated and begins generating
|
||||
signatures. If that condition does not apply, a warning
|
||||
will be generated.
|
||||
</para>
|
||||
<para>
|
||||
The length of the TTL can be set in seconds, or in larger units
|
||||
of time by adding a suffix: 'mi' for minutes, 'h' for hours,
|
||||
'd' for days, 'w' for weeks, 'mo' for months, 'y' for years.
|
||||
</para>
|
||||
<para>
|
||||
This option is mandatory unless the <option>-f</option> has
|
||||
been used to specify a zone file, or a default key TTL was
|
||||
set with the <option>-L</option> to
|
||||
<command>dnssec-keygen</command>. (If either of those is true,
|
||||
this option may still be used; it will overrde the value found
|
||||
in the zone or key file.)
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-r <replaceable class="parameter">resign interval</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Sets the value to be used as the resign interval for the zone
|
||||
or zones being analyzed when determining whether there is a
|
||||
possibility of validation failure. This value defaults to
|
||||
22.5 days, which is also the default in
|
||||
<command>named</command>. However, if it has been changed
|
||||
by the <option>sig-validity-interval</option> option in
|
||||
<filename>named.conf</filename>, then it should also be
|
||||
changed here.
|
||||
</para>
|
||||
<para>
|
||||
The length of the interval can be set in seconds, or in larger
|
||||
units of time by adding a suffix: 'mi' for minutes, 'h' for hours,
|
||||
'd' for days, 'w' for weeks, 'mo' for months, 'y' for years.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-c <replaceable class="parameter">compilezone path</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Specifies a path to a <command>named-compilezone</command> binary.
|
||||
Used for testing.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>SEE ALSO</title>
|
||||
<para>
|
||||
<citerefentry>
|
||||
<refentrytitle>dnssec-checkds</refentrytitle><manvolnum>8</manvolnum>
|
||||
</citerefentry>,
|
||||
<citerefentry>
|
||||
<refentrytitle>dnssec-dsfromkey</refentrytitle><manvolnum>8</manvolnum>
|
||||
</citerefentry>,
|
||||
<citerefentry>
|
||||
<refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
|
||||
</citerefentry>,
|
||||
<citerefentry>
|
||||
<refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>AUTHOR</title>
|
||||
<para><corpauthor>Internet Systems Consortium</corpauthor>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry><!--
|
||||
- Local variables:
|
||||
- mode: sgml
|
||||
- End:
|
||||
-->
|
737
bin/python/dnssec-coverage.py.in
Executable file
737
bin/python/dnssec-coverage.py.in
Executable file
@ -0,0 +1,737 @@
|
||||
#!@PYTHON@
|
||||
############################################################################
|
||||
# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
############################################################################
|
||||
import argparse
|
||||
import os
|
||||
import glob
|
||||
import sys
|
||||
import re
|
||||
import time
|
||||
import calendar
|
||||
from collections import defaultdict
|
||||
import pprint
|
||||
|
||||
prog='dnssec-coverage'
|
||||
|
||||
########################################################################
|
||||
# Class Event
|
||||
########################################################################
|
||||
class Event:
|
||||
""" A discrete key metadata event, e.g., Publish, Activate, Inactive,
|
||||
Delete. Stores the date of the event, and identifying information about
|
||||
the key to which the event will occur."""
|
||||
|
||||
def __init__(self, _what, _key):
|
||||
now = time.time()
|
||||
self.what = _what
|
||||
self.when = _key.metadata[_what]
|
||||
self.key = _key
|
||||
self.keyid = _key.keyid
|
||||
self.sep = _key.sep
|
||||
self.zone = _key.zone
|
||||
self.alg = _key.alg
|
||||
|
||||
def __repr__(self):
|
||||
return repr((self.when, self.what, self.keyid, self.sep,
|
||||
self.zone, self.alg))
|
||||
|
||||
def showtime(self):
|
||||
return time.strftime("%a %b %d %H:%M:%S UTC %Y", self.when)
|
||||
|
||||
def showkey(self):
|
||||
return self.key.showkey()
|
||||
|
||||
def showkeytype(self):
|
||||
return self.key.showkeytype()
|
||||
|
||||
########################################################################
|
||||
# Class Key
|
||||
########################################################################
|
||||
class Key:
|
||||
"""An individual DNSSEC key. Identified by path, zone, algorithm, keyid.
|
||||
Contains a dictionary of metadata events."""
|
||||
|
||||
def __init__(self, keyname):
|
||||
directory = os.path.dirname(keyname)
|
||||
key = os.path.basename(keyname)
|
||||
(zone, alg, keyid) = key.split('+')
|
||||
keyid = keyid.split('.')[0]
|
||||
key = [zone, alg, keyid]
|
||||
key_file = directory + os.sep + '+'.join(key) + ".key"
|
||||
private_file = directory + os.sep + '+'.join(key) + ".private"
|
||||
|
||||
self.zone = zone[1:-1]
|
||||
self.alg = int(alg)
|
||||
self.keyid = int(keyid)
|
||||
|
||||
kfp = file(key_file, "r")
|
||||
for line in kfp:
|
||||
if line[0] == ';':
|
||||
continue
|
||||
tokens = line.split()
|
||||
if not tokens:
|
||||
continue
|
||||
|
||||
if tokens[1].lower() in ('in', 'ch', 'hs'):
|
||||
septoken = 3
|
||||
self.ttl = args.keyttl
|
||||
if not self.ttl:
|
||||
vspace()
|
||||
print("WARNING: Unable to determine TTL for DNSKEY %s." %
|
||||
self.showkey())
|
||||
print("\t Using 1 day (86400 seconds); re-run with the -d "
|
||||
"option for more\n\t accurate results.")
|
||||
self.ttl = 86400
|
||||
else:
|
||||
septoken = 4
|
||||
self.ttl = int(tokens[1]) if not args.keyttl else args.keyttl
|
||||
|
||||
if (int(tokens[septoken]) & 0x1) == 1:
|
||||
self.sep = True
|
||||
else:
|
||||
self.sep = False
|
||||
kfp.close()
|
||||
|
||||
pfp = file(private_file, "rU")
|
||||
propDict = dict()
|
||||
for propLine in pfp:
|
||||
propDef = propLine.strip()
|
||||
if len(propDef) == 0:
|
||||
continue
|
||||
if propDef[0] in ('!', '#'):
|
||||
continue
|
||||
punctuation = [propDef.find(c) for c in ':= '] + [len(propDef)]
|
||||
found = min([ pos for pos in punctuation if pos != -1 ])
|
||||
name = propDef[:found].rstrip()
|
||||
value = propDef[found:].lstrip(":= ").rstrip()
|
||||
propDict[name] = value
|
||||
|
||||
if("Publish" in propDict):
|
||||
propDict["Publish"] = time.strptime(propDict["Publish"],
|
||||
"%Y%m%d%H%M%S")
|
||||
|
||||
if("Activate" in propDict):
|
||||
propDict["Activate"] = time.strptime(propDict["Activate"],
|
||||
"%Y%m%d%H%M%S")
|
||||
|
||||
if("Inactive" in propDict):
|
||||
propDict["Inactive"] = time.strptime(propDict["Inactive"],
|
||||
"%Y%m%d%H%M%S")
|
||||
|
||||
if("Delete" in propDict):
|
||||
propDict["Delete"] = time.strptime(propDict["Delete"],
|
||||
"%Y%m%d%H%M%S")
|
||||
|
||||
if("Revoke" in propDict):
|
||||
propDict["Revoke"] = time.strptime(propDict["Revoke"],
|
||||
"%Y%m%d%H%M%S")
|
||||
pfp.close()
|
||||
self.metadata = propDict
|
||||
|
||||
def showkey(self):
|
||||
return "%s/%03d/%05d" % (self.zone, self.alg, self.keyid);
|
||||
|
||||
def showkeytype(self):
|
||||
return ("KSK" if self.sep else "ZSK")
|
||||
|
||||
# ensure that the gap between Publish and Activate is big enough
|
||||
def check_prepub(self):
|
||||
now = time.time()
|
||||
|
||||
if (not "Activate" in self.metadata):
|
||||
debug_print("No Activate information in key: %s" % self.showkey())
|
||||
return False
|
||||
a = calendar.timegm(self.metadata["Activate"])
|
||||
|
||||
if (not "Publish" in self.metadata):
|
||||
debug_print("No Publish information in key: %s" % self.showkey())
|
||||
if a > now:
|
||||
vspace()
|
||||
print("WARNING: Key %s (%s) is scheduled for activation but \n"
|
||||
"\t not for publication." %
|
||||
(self.showkey(), self.showkeytype()))
|
||||
return False
|
||||
p = calendar.timegm(self.metadata["Publish"])
|
||||
|
||||
now = time.time()
|
||||
if p < now and a < now:
|
||||
return True
|
||||
|
||||
if p == a:
|
||||
vspace()
|
||||
print ("WARNING: %s (%s) is scheduled to be published and\n"
|
||||
"\t activated at the same time. This could result in a\n"
|
||||
"\t coverage gap if the zone was previously signed." %
|
||||
(self.showkey(), self.showkeytype()))
|
||||
print("\t Activation should be at least %s after publication."
|
||||
% duration(self.ttl))
|
||||
return True
|
||||
|
||||
if a < p:
|
||||
vspace()
|
||||
print("WARNING: Key %s (%s) is active before it is published" %
|
||||
(self.showkey(), self.showkeytype()))
|
||||
return False
|
||||
|
||||
if (a - p < self.ttl):
|
||||
vspace()
|
||||
print("WARNING: Key %s (%s) is activated too soon after\n"
|
||||
"\t publication; this could result in coverage gaps due to\n"
|
||||
"\t resolver caches containing old data."
|
||||
% (self.showkey(), self.showkeytype()))
|
||||
print("\t Activation should be at least %s after publication." %
|
||||
duration(self.ttl))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
# ensure that the gap between Inactive and Delete is big enough
|
||||
def check_postpub(self, timespan = None):
|
||||
if not timespan:
|
||||
timespan = self.ttl
|
||||
|
||||
now = time.time()
|
||||
|
||||
if (not "Delete" in self.metadata):
|
||||
debug_print("No Delete information in key: %s" % self.showkey())
|
||||
return False
|
||||
d = calendar.timegm(self.metadata["Delete"])
|
||||
|
||||
if (not "Inactive" in self.metadata):
|
||||
debug_print("No Inactive information in key: %s" % self.showkey())
|
||||
if d > now:
|
||||
vspace()
|
||||
print("WARNING: Key %s (%s) is scheduled for deletion but\n"
|
||||
"\t not for inactivation." %
|
||||
(self.showkey(), self.showkeytype()))
|
||||
return False
|
||||
i = calendar.timegm(self.metadata["Inactive"])
|
||||
|
||||
if d < now and i < now:
|
||||
return True
|
||||
|
||||
if (d < i):
|
||||
vspace()
|
||||
print("WARNING: Key %s (%s) is scheduled for deletion before\n"
|
||||
"\t inactivation." % (self.showkey(), self.showkeytype()))
|
||||
return False
|
||||
|
||||
if (d - i < timespan):
|
||||
vspace()
|
||||
print("WARNING: Key %s (%s) scheduled for deletion too soon after\n"
|
||||
"\t deactivation; this may result in coverage gaps due to\n"
|
||||
"\t resolver caches containing old data."
|
||||
% (self.showkey(), self.showkeytype()))
|
||||
print("\t Deletion should be at least %s after inactivation." %
|
||||
duration(timespan))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
########################################################################
|
||||
# class Zone
|
||||
########################################################################
|
||||
class Zone:
|
||||
"""Stores data about a specific zone"""
|
||||
|
||||
def __init__(self, _name, _keyttl = None, _maxttl = None):
|
||||
self.name = _name
|
||||
self.keyttl = _keyttl
|
||||
self.maxttl = _maxttl
|
||||
|
||||
def load(self, filename):
|
||||
if not args.compilezone:
|
||||
sys.stderr.write(prog + ': FATAL: "named-compilezone" not found\n')
|
||||
exit(1)
|
||||
|
||||
if not self.name:
|
||||
return
|
||||
|
||||
maxttl = keyttl = None
|
||||
|
||||
fp = os.popen("%s -o - %s %s 2> /dev/null" %
|
||||
(args.compilezone, self.name, filename))
|
||||
for line in fp:
|
||||
fields = line.split()
|
||||
if not maxttl or int(fields[1]) > maxttl:
|
||||
maxttl = int(fields[1])
|
||||
if fields[3] == "DNSKEY":
|
||||
keyttl = int(fields[1])
|
||||
fp.close()
|
||||
|
||||
self.keyttl = keyttl
|
||||
self.maxttl = maxttl
|
||||
|
||||
############################################################################
|
||||
# debug_print:
|
||||
############################################################################
|
||||
def debug_print(debugVar):
|
||||
"""pretty print a variable iff debug mode is enabled"""
|
||||
if not args.debug_mode:
|
||||
return
|
||||
if type(debugVar) == str:
|
||||
print("DEBUG: " + debugVar)
|
||||
else:
|
||||
print("DEBUG: " + pprint.pformat(debugVar))
|
||||
return
|
||||
|
||||
############################################################################
|
||||
# vspace:
|
||||
############################################################################
|
||||
_firstline = True
|
||||
def vspace():
|
||||
"""adds vertical space between two sections of output text if and only
|
||||
if this is *not* the first section being printed"""
|
||||
global _firstline
|
||||
if _firstline:
|
||||
_firstline = False
|
||||
else:
|
||||
print
|
||||
|
||||
############################################################################
|
||||
# vreset:
|
||||
############################################################################
|
||||
def vreset():
|
||||
"""reset vertical spacing"""
|
||||
global _firstline
|
||||
_firstline = True
|
||||
|
||||
############################################################################
|
||||
# getunit
|
||||
############################################################################
|
||||
def getunit(secs, size):
|
||||
"""given a number of seconds, and a number of seconds in a larger unit of
|
||||
time, calculate how many of the larger unit there are and return both
|
||||
that and a remainder value"""
|
||||
bigunit = secs // size
|
||||
if bigunit:
|
||||
secs %= size
|
||||
return (bigunit, secs)
|
||||
|
||||
############################################################################
|
||||
# addtime
|
||||
############################################################################
|
||||
def addtime(output, unit, t):
|
||||
"""add a formatted unit of time to an accumulating string"""
|
||||
if t:
|
||||
output += ("%s%d %s%s" %
|
||||
((", " if output else ""),
|
||||
t, unit, ("s" if t > 1 else "")))
|
||||
|
||||
return output
|
||||
|
||||
############################################################################
|
||||
# duration:
|
||||
############################################################################
|
||||
def duration(secs):
|
||||
"""given a length of time in seconds, print a formatted human duration
|
||||
in larger units of time
|
||||
"""
|
||||
# define units:
|
||||
minute = 60
|
||||
hour = minute * 60
|
||||
day = hour * 24
|
||||
month = day * 30
|
||||
year = day * 365
|
||||
|
||||
# calculate time in units:
|
||||
(years, secs) = getunit(secs, year)
|
||||
(months, secs) = getunit(secs, month)
|
||||
(days, secs) = getunit(secs, day)
|
||||
(hours, secs) = getunit(secs, hour)
|
||||
(minutes, secs) = getunit(secs, minute)
|
||||
|
||||
output = ''
|
||||
output = addtime(output, "year", years)
|
||||
output = addtime(output, "month", months)
|
||||
output = addtime(output, "day", days)
|
||||
output = addtime(output, "hour", hours)
|
||||
output = addtime(output, "minute", minutes)
|
||||
output = addtime(output, "second", secs)
|
||||
return output
|
||||
|
||||
############################################################################
|
||||
# parse_time
|
||||
############################################################################
|
||||
def parse_time(s):
|
||||
"""convert a formatted time (e.g., 1y, 6mo, 15mi, etc) into seconds"""
|
||||
s = s.strip()
|
||||
|
||||
# if s is an integer, we're done already
|
||||
try:
|
||||
n = int(s)
|
||||
return n
|
||||
except:
|
||||
pass
|
||||
|
||||
# try to parse as a number with a suffix indicating unit of time
|
||||
r = re.compile('([0-9][0-9]*)\s*([A-Za-z]*)')
|
||||
m = r.match(s)
|
||||
if not m:
|
||||
raise Exception("Cannot parse %s" % s)
|
||||
(n, unit) = m.groups()
|
||||
n = int(n)
|
||||
unit = unit.lower()
|
||||
if unit[0] == 'y':
|
||||
return n * 31536000
|
||||
elif unit[0] == 'm' and unit[1] == 'o':
|
||||
return n * 2592000
|
||||
elif unit[0] == 'w':
|
||||
return n * 604800
|
||||
elif unit[0] == 'd':
|
||||
return n * 86400
|
||||
elif unit[0] == 'h':
|
||||
return n * 3600
|
||||
elif unit[0] == 'm' and unit[1] == 'i':
|
||||
return n * 60
|
||||
elif unit[0] == 's':
|
||||
return n
|
||||
else:
|
||||
raise Exception("Invalid suffix %s" % unit)
|
||||
|
||||
############################################################################
|
||||
# algname:
|
||||
############################################################################
|
||||
def algname(alg):
|
||||
"""return the mnemonic for a DNSSEC algorithm"""
|
||||
names = (None, 'RSAMD5', 'DH', 'DSA', 'ECC', 'RSASHA1',
|
||||
'NSEC3DSA', 'NSEC3RSASHA1', 'RSASHA256', None,
|
||||
'RSASHA512', None, 'ECCGOST', 'ECDSAP256SHA256',
|
||||
'ECDSAP384SHA384')
|
||||
name = None
|
||||
if alg in range(len(names)):
|
||||
name = names[alg]
|
||||
return (name if name else str(alg))
|
||||
|
||||
############################################################################
|
||||
# list_events:
|
||||
############################################################################
|
||||
def list_events(eventgroup):
|
||||
"""print a list of the events in an eventgroup"""
|
||||
if not eventgroup:
|
||||
return
|
||||
print (" " + eventgroup[0].showtime() + ":")
|
||||
for event in eventgroup:
|
||||
print (" %s: %s (%s)" %
|
||||
(event.what, event.showkey(), event.showkeytype()))
|
||||
|
||||
############################################################################
|
||||
# process_events:
|
||||
############################################################################
|
||||
def process_events(eventgroup, active, published):
|
||||
"""go through the events in an event group in time-order, add to active
|
||||
list upon Activate event, add to published list upon Publish event,
|
||||
remove from active list upon Inactive event, and remove from published
|
||||
upon Delete event. Emit warnings when inconsistant states are reached"""
|
||||
for event in eventgroup:
|
||||
if event.what == "Activate":
|
||||
active.add(event.keyid)
|
||||
elif event.what == "Publish":
|
||||
published.add(event.keyid)
|
||||
elif event.what == "Inactive":
|
||||
if event.keyid not in active:
|
||||
vspace()
|
||||
print ("\tWARNING: %s (%s) scheduled to become inactive "
|
||||
"before it is active" %
|
||||
(event.showkey(), event.showkeytype()))
|
||||
else:
|
||||
active.remove(event.keyid)
|
||||
elif event.what == "Delete":
|
||||
if event.keyid in published:
|
||||
published.remove(event.keyid)
|
||||
else:
|
||||
vspace()
|
||||
print ("WARNING: key %s (%s) is scheduled for deletion before "
|
||||
"it is published, at %s" %
|
||||
(event.showkey(), event.showkeytype()))
|
||||
elif event.what == "Revoke":
|
||||
# We don't need to worry about the logic of this one;
|
||||
# just stop counting this key as either active or published
|
||||
if event.keyid in published:
|
||||
published.remove(event.keyid)
|
||||
if event.keyid in active:
|
||||
active.remove(event.keyid)
|
||||
|
||||
return (active, published)
|
||||
|
||||
############################################################################
|
||||
# check_events:
|
||||
############################################################################
|
||||
def check_events(eventsList, ksk):
|
||||
"""create lists of events happening at the same time, check for
|
||||
inconsistancies"""
|
||||
active = set()
|
||||
published = set()
|
||||
eventgroups = list()
|
||||
eventgroup = list()
|
||||
keytype = ("KSK" if ksk else "ZSK")
|
||||
|
||||
# collect up all events that have the same time
|
||||
eventsfound = False
|
||||
for event in eventsList:
|
||||
# if checking ZSKs, skip KSKs, and vice versa
|
||||
if (ksk and not event.sep) or (event.sep and not ksk):
|
||||
continue
|
||||
|
||||
# we found an appropriate (ZSK or KSK event)
|
||||
eventsfound = True
|
||||
|
||||
# add event to current eventgroup
|
||||
if (not eventgroup or eventgroup[0].when == event.when):
|
||||
eventgroup.append(event)
|
||||
|
||||
# if we're at the end of the list, we're done. if
|
||||
# we've found an event with a later time, start a new
|
||||
# eventgroup
|
||||
if (eventgroup[0].when != event.when):
|
||||
eventgroups.append(eventgroup)
|
||||
eventgroup = list()
|
||||
eventgroup.append(event)
|
||||
|
||||
if eventgroup:
|
||||
eventgroups.append(eventgroup)
|
||||
|
||||
for eventgroup in eventgroups:
|
||||
(active, published) = \
|
||||
process_events(eventgroup, active, published)
|
||||
|
||||
list_events(eventgroup)
|
||||
|
||||
# and then check for inconsistencies:
|
||||
if len(active) == 0:
|
||||
print ("ERROR: No %s's are active after this event" % keytype)
|
||||
return False
|
||||
elif len(published) == 0:
|
||||
sys.stdout.write("ERROR: ")
|
||||
print ("ERROR: No %s's are published after this event" % keytype)
|
||||
return False
|
||||
elif len(published.intersection(active)) == 0:
|
||||
sys.stdout.write("ERROR: ")
|
||||
print (("ERROR: No %s's are both active and published " +
|
||||
"after this event") % keytype)
|
||||
return False
|
||||
|
||||
if not eventsfound:
|
||||
print ("ERROR: No %s events found in '%s'" %
|
||||
(keytype, args.path))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
############################################################################
|
||||
# check_zones:
|
||||
# ############################################################################
|
||||
def check_zones(eventsList):
|
||||
"""scan events per zone, algorithm, and key type, in order of occurrance,
|
||||
noting inconsistent states when found"""
|
||||
global foundprob
|
||||
|
||||
foundprob = False
|
||||
zonesfound = False
|
||||
for zone in eventsList:
|
||||
if args.zone and zone != args.zone:
|
||||
continue
|
||||
|
||||
zonesfound = True
|
||||
for alg in eventsList[zone]:
|
||||
vspace()
|
||||
print("Checking scheduled KSK events for zone %s, algorithm %s..." %
|
||||
(zone, algname(alg)))
|
||||
if not check_events(eventsList[zone][alg], True):
|
||||
foundprob = True
|
||||
else:
|
||||
print ("No errors found")
|
||||
|
||||
vspace()
|
||||
print("Checking scheduled ZSK events for zone %s, algorithm %s..." %
|
||||
(zone, algname(alg)))
|
||||
if not check_events(eventsList[zone][alg], False):
|
||||
foundprob = True
|
||||
else:
|
||||
print ("No errors found")
|
||||
|
||||
if not zonesfound:
|
||||
print("ERROR: No key events found for %s in '%s'" %
|
||||
(args.zone, args.path))
|
||||
exit(1)
|
||||
|
||||
############################################################################
|
||||
# fill_eventsList:
|
||||
############################################################################
|
||||
def fill_eventsList(eventsList):
|
||||
"""populate the list of events"""
|
||||
for zone, algorithms in keyDict.items():
|
||||
for alg, keys in algorithms.items():
|
||||
for keyid, keydata in keys.items():
|
||||
if("Publish" in keydata.metadata):
|
||||
eventsList[zone][alg].append(Event("Publish", keydata))
|
||||
if("Activate" in keydata.metadata):
|
||||
eventsList[zone][alg].append(Event("Activate", keydata))
|
||||
if("Inactive" in keydata.metadata):
|
||||
eventsList[zone][alg].append(Event("Inactive", keydata))
|
||||
if("Delete" in keydata.metadata):
|
||||
eventsList[zone][alg].append(Event("Delete", keydata))
|
||||
|
||||
eventsList[zone][alg] = sorted(eventsList[zone][alg],
|
||||
key=lambda event: event.when)
|
||||
|
||||
foundprob = False
|
||||
if not keyDict:
|
||||
print("ERROR: No key events found in '%s'" % args.path)
|
||||
exit(1)
|
||||
|
||||
############################################################################
|
||||
# set_path:
|
||||
############################################################################
|
||||
def set_path(command, default=None):
|
||||
"""find the location of a specified command. if a default is supplied
|
||||
and it works, we use it; otherwise we search PATH for a match. If
|
||||
not found, error and exit"""
|
||||
fpath = default
|
||||
if not fpath or not os.path.isfile(fpath) or not os.access(fpath, os.X_OK):
|
||||
path = os.environ["PATH"]
|
||||
if not path:
|
||||
path = os.path.defpath
|
||||
for directory in path.split(os.pathsep):
|
||||
fpath = directory + os.sep + command
|
||||
if os.path.isfile(fpath) or os.access(fpath, os.X_OK):
|
||||
break
|
||||
fpath = None
|
||||
|
||||
return fpath
|
||||
|
||||
############################################################################
|
||||
# parse_args:
|
||||
############################################################################
|
||||
def parse_args():
|
||||
"""Read command line arguments, set global 'args' structure"""
|
||||
global args
|
||||
|
||||
compilezone = set_path('named-compilezone',
|
||||
'@prefix@/sbin/named-compilezone')
|
||||
|
||||
parser = argparse.ArgumentParser(description=prog + ': checks future ' +
|
||||
'DNSKEY coverage for a zone')
|
||||
|
||||
parser.add_argument('zone', type=str, help='zone to check')
|
||||
parser.add_argument('-K', dest='path', default='.', type=str,
|
||||
help='a directory containing keys to process',
|
||||
metavar='dir')
|
||||
parser.add_argument('-f', dest='filename', type=str,
|
||||
help='zone master file', metavar='file')
|
||||
parser.add_argument('-m', dest='maxttl', type=str,
|
||||
help='the longest TTL in the zone(s)',
|
||||
metavar='int')
|
||||
parser.add_argument('-d', dest='keyttl', type=str,
|
||||
help='the DNSKEY TTL', metavar='int')
|
||||
parser.add_argument('-r', dest='resign', default='1944000',
|
||||
type=int, help='the RRSIG refresh interval '
|
||||
'in seconds [default: 22.5 days]',
|
||||
metavar='int')
|
||||
parser.add_argument('-c', dest='compilezone',
|
||||
default=compilezone, type=str,
|
||||
help='path to \'named-compilezone\'',
|
||||
metavar='path')
|
||||
parser.add_argument('-D', '--debug', dest='debug_mode',
|
||||
action='store_true', default=False,
|
||||
help='Turn on debugging output')
|
||||
parser.add_argument('-v', '--version', action='version', version='9.9.1')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# convert from time arguments to seconds
|
||||
try:
|
||||
if args.maxttl:
|
||||
m = parse_time(args.maxttl)
|
||||
args.maxttl = m
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
if args.keyttl:
|
||||
k = parse_time(args.keyttl)
|
||||
args.keyttl = k
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
if args.resign:
|
||||
r = parse_time(args.resign)
|
||||
args.resign = r
|
||||
except:
|
||||
pass
|
||||
|
||||
# if we've got the values we need from the command line, stop now
|
||||
if args.maxttl and args.keyttl:
|
||||
return
|
||||
|
||||
# load keyttl and maxttl data from zonefile
|
||||
if args.zone and args.filename:
|
||||
try:
|
||||
zone = Zone(args.zone)
|
||||
zone.load(args.filename)
|
||||
if not args.maxttl:
|
||||
args.maxttl = zone.maxttl
|
||||
if not args.keyttl:
|
||||
args.keyttl = zone.maxttl
|
||||
except Exception as e:
|
||||
print("Unable to load zone data from %s: " % args.filename, e)
|
||||
|
||||
if not args.maxttl:
|
||||
vspace()
|
||||
print ("WARNING: Maximum TTL value was not specified. Using 1 week\n"
|
||||
"\t (604800 seconds); re-run with the -m option to get more\n"
|
||||
"\t accurate results.")
|
||||
args.maxttl = 604800
|
||||
|
||||
############################################################################
|
||||
# Main
|
||||
############################################################################
|
||||
def main():
|
||||
global keyDict
|
||||
|
||||
parse_args()
|
||||
path=args.path
|
||||
|
||||
print ("PHASE 1--Loading keys to check for internal timing problems")
|
||||
keyDict = defaultdict(lambda : defaultdict(dict))
|
||||
files = glob.glob(os.path.join(path, '*.private'))
|
||||
for infile in files:
|
||||
key = Key(infile)
|
||||
if args.zone and key.zone != args.zone:
|
||||
continue
|
||||
keyDict[key.zone][key.alg][key.keyid] = key
|
||||
key.check_prepub()
|
||||
if key.sep:
|
||||
key.check_postpub()
|
||||
else:
|
||||
key.check_postpub(args.maxttl + args.resign)
|
||||
|
||||
vspace()
|
||||
print ("PHASE 2--Scanning future key events for coverage failures")
|
||||
vreset()
|
||||
|
||||
eventsList = defaultdict(lambda : defaultdict(list))
|
||||
fill_eventsList(eventsList)
|
||||
check_zones(eventsList)
|
||||
|
||||
if foundprob:
|
||||
exit(1)
|
||||
else:
|
||||
exit(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -44,6 +44,7 @@ REVOKE=$TOP/bin/dnssec/dnssec-revoke
|
||||
SETTIME=$TOP/bin/dnssec/dnssec-settime
|
||||
DSFROMKEY=$TOP/bin/dnssec/dnssec-dsfromkey
|
||||
CHECKDS=$TOP/bin/python/dnssec-checkds
|
||||
COVERAGE=$TOP/bin/python/dnssec-coverage
|
||||
CHECKZONE=$TOP/bin/check/named-checkzone
|
||||
CHECKCONF=$TOP/bin/check/named-checkconf
|
||||
PK11GEN="$TOP/bin/pkcs11/pkcs11-keygen -s ${SLOT:-0} -p 1234"
|
||||
@ -57,8 +58,8 @@ ARPANAME=$TOP/bin/tools/arpaname
|
||||
# load on the machine to make it unusable to other users.
|
||||
# v6synth
|
||||
SUBDIRS="acl additional allow_query addzone autosign builtin
|
||||
cacheclean checkconf @CHECKDS@ checknames checkzone database
|
||||
dlv dlvauto dlz dlzexternal dlzredir dname dns64 dnssec
|
||||
cacheclean checkconf @CHECKDS@ checknames checkzone @COVERAGE@
|
||||
database dlv dlvauto dlz dlzexternal dlzredir dname dns64 dnssec
|
||||
dsdigest ecdsa formerr forward glue gost ixfr inline limits
|
||||
logfileconfig lwresd masterfile masterformat metadata
|
||||
notify nsupdate pending pkcs11 redirect resolver rndc rpz
|
||||
|
10
bin/tests/system/coverage/01-ksk-inactive/README
Normal file
10
bin/tests/system/coverage/01-ksk-inactive/README
Normal file
@ -0,0 +1,10 @@
|
||||
This set includes one KSK rollover. The KSK is deactivated prior to
|
||||
its replacement being activated. Tool output should resemble:
|
||||
|
||||
Checking KSK events for zone example.com, algorithm 7:
|
||||
ERROR: After 2012-31-Jul (20:59:14):
|
||||
Inactive: example.com/007/45435 (KSK)
|
||||
No KSK's are active
|
||||
|
||||
Checking ZSK events for zone example.com, algorithm 7:
|
||||
OK
|
6
bin/tests/system/coverage/01-ksk-inactive/expect
Normal file
6
bin/tests/system/coverage/01-ksk-inactive/expect
Normal file
@ -0,0 +1,6 @@
|
||||
args="-d 1h -m 2h"
|
||||
warn=0
|
||||
error=1
|
||||
ok=1
|
||||
retcode=1
|
||||
match="No KSK's are active"
|
10
bin/tests/system/coverage/02-zsk-inactive/README
Normal file
10
bin/tests/system/coverage/02-zsk-inactive/README
Normal file
@ -0,0 +1,10 @@
|
||||
This set includes one ZSK rollover. The first ZSK is deactivated
|
||||
prior to its replacement being activated. Tool output should resemble:
|
||||
|
||||
Checking KSK events for zone example.com, algorithm 7:
|
||||
OK
|
||||
|
||||
Checking ZSK events for zone example.com, algorithm 7:
|
||||
ERROR: After 2012-05-Dec (20:39:32):
|
||||
Inactive: example.com/005/08376 (ZSK)
|
||||
No ZSK's are active
|
6
bin/tests/system/coverage/02-zsk-inactive/expect
Normal file
6
bin/tests/system/coverage/02-zsk-inactive/expect
Normal file
@ -0,0 +1,6 @@
|
||||
args="-d 1h -m 2h"
|
||||
warn=0
|
||||
error=1
|
||||
ok=1
|
||||
retcode=1
|
||||
match="No ZSK's are active"
|
10
bin/tests/system/coverage/03-ksk-unpublished/README
Normal file
10
bin/tests/system/coverage/03-ksk-unpublished/README
Normal file
@ -0,0 +1,10 @@
|
||||
This set contains one KSK rollover. The KSK is unpublished before its
|
||||
successor is published. Tool output should resemble:
|
||||
|
||||
Checking KSK events for zone example.com, algorithm 7:
|
||||
ERROR: After 2012-06-Oct (21:07:57):
|
||||
Delete: example.com/007/23040 (KSK)
|
||||
No KSK's are published
|
||||
|
||||
Checking ZSK events for zone example.com, algorithm 7:
|
||||
OK
|
7
bin/tests/system/coverage/03-ksk-unpublished/expect
Normal file
7
bin/tests/system/coverage/03-ksk-unpublished/expect
Normal file
@ -0,0 +1,7 @@
|
||||
args="-d 1h -m 2h"
|
||||
warn=1
|
||||
error=1
|
||||
ok=1
|
||||
retcode=1
|
||||
match="WARNING: Key .* (KSK) is scheduled for deletion before
|
||||
No KSK's are published"
|
10
bin/tests/system/coverage/04-zsk-unpublished/README
Normal file
10
bin/tests/system/coverage/04-zsk-unpublished/README
Normal file
@ -0,0 +1,10 @@
|
||||
This set contains one ZSK rollover. The ZSK is unpublished before its
|
||||
successor is published. Tool output should resemble:
|
||||
|
||||
Checking KSK events for zone example.com, algorithm 7:
|
||||
OK
|
||||
|
||||
Checking ZSK events for zone example.com, algorithm 7:
|
||||
ERROR: After 2012-06-Oct (21:13:45):
|
||||
Delete: example.com/007/25967 (ZSK)
|
||||
No ZSK's are published
|
7
bin/tests/system/coverage/04-zsk-unpublished/expect
Normal file
7
bin/tests/system/coverage/04-zsk-unpublished/expect
Normal file
@ -0,0 +1,7 @@
|
||||
args="-d 1h -m 2h"
|
||||
warn=1
|
||||
error=1
|
||||
ok=1
|
||||
retcode=1
|
||||
match="WARNING: Key .* (ZSK) is scheduled for deletion before
|
||||
No ZSK's are published"
|
12
bin/tests/system/coverage/05-ksk-unpub-active/README
Normal file
12
bin/tests/system/coverage/05-ksk-unpub-active/README
Normal file
@ -0,0 +1,12 @@
|
||||
This set includes one KSK rollover. The first KSK is deleted
|
||||
and its successor published prior to the first KSK being deactivated
|
||||
and its successor activated. Tool output should resemble:
|
||||
|
||||
Checking KSK events for zone example.com, algorithm 7:
|
||||
ERROR: After 2012-05-Dec (21:22:19):
|
||||
Delete: example.com/007/06219 (KSK)
|
||||
Publish: example.com/007/20559 (KSK)
|
||||
No KSK's are both active and published
|
||||
|
||||
Checking ZSK events for zone example.com, algorithm 7:
|
||||
OK
|
7
bin/tests/system/coverage/05-ksk-unpub-active/expect
Normal file
7
bin/tests/system/coverage/05-ksk-unpub-active/expect
Normal file
@ -0,0 +1,7 @@
|
||||
args="-d 1h -m 2h"
|
||||
warn=1
|
||||
error=1
|
||||
ok=1
|
||||
retcode=1
|
||||
match="WARNING: Key .* (KSK) is scheduled for deletion before
|
||||
No KSK's are both active and published"
|
12
bin/tests/system/coverage/06-zsk-unpub-active/README
Normal file
12
bin/tests/system/coverage/06-zsk-unpub-active/README
Normal file
@ -0,0 +1,12 @@
|
||||
This set includes one KSK rollover. The first KSK is deleted
|
||||
and its successor published prior to the first KSK being deactivated
|
||||
and its successor activated. Tool output should resemble:
|
||||
|
||||
Checking KSK events for zone example.com, algorithm 7:
|
||||
OK
|
||||
|
||||
Checking ZSK events for zone example.com, algorithm 7:
|
||||
ERROR: After 2012-05-Dec (20:44:18):
|
||||
Delete: example.com/007/26369 (ZSK)
|
||||
Publish: example.com/007/21029 (ZSK)
|
||||
No ZSK's are both active and published
|
7
bin/tests/system/coverage/06-zsk-unpub-active/expect
Normal file
7
bin/tests/system/coverage/06-zsk-unpub-active/expect
Normal file
@ -0,0 +1,7 @@
|
||||
args="-d 1h -m 2h"
|
||||
warn=1
|
||||
error=1
|
||||
ok=1
|
||||
retcode=1
|
||||
match="WARNING: Key .* (ZSK) is scheduled for deletion before
|
||||
No ZSK's are both active and published"
|
4
bin/tests/system/coverage/07-ksk-ttl/README
Normal file
4
bin/tests/system/coverage/07-ksk-ttl/README
Normal file
@ -0,0 +1,4 @@
|
||||
This set includes a KSK rollover, with insufficient delay between
|
||||
prepublication and rollover.
|
||||
|
||||
Expected tool output TBD.
|
7
bin/tests/system/coverage/07-ksk-ttl/expect
Normal file
7
bin/tests/system/coverage/07-ksk-ttl/expect
Normal file
@ -0,0 +1,7 @@
|
||||
args="-d 1w -m 2w"
|
||||
warn=1
|
||||
error=0
|
||||
ok=2
|
||||
retcode=0
|
||||
match="WARNING: Key .* (KSK) is activated too soon after
|
||||
Activation should be at least 7 days after publication."
|
4
bin/tests/system/coverage/08-zsk-ttl/README
Normal file
4
bin/tests/system/coverage/08-zsk-ttl/README
Normal file
@ -0,0 +1,4 @@
|
||||
This set includes a KSK rollover, with insufficient delay between
|
||||
prepublication and rollover.
|
||||
|
||||
Expected tool output TBD.
|
7
bin/tests/system/coverage/08-zsk-ttl/expect
Normal file
7
bin/tests/system/coverage/08-zsk-ttl/expect
Normal file
@ -0,0 +1,7 @@
|
||||
args="-d 1w -m 2w"
|
||||
warn=1
|
||||
error=0
|
||||
ok=2
|
||||
retcode=0
|
||||
match="WARNING: Key .* (ZSK) is activated too soon after
|
||||
Activation should be at least 7 days after publication."
|
6
bin/tests/system/coverage/clean.sh
Normal file
6
bin/tests/system/coverage/clean.sh
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
rm -f named-compilezone
|
||||
rm -f */K*.key
|
||||
rm -f */K*.private
|
||||
rm -rf coverage.*
|
||||
rm -f random.data
|
106
bin/tests/system/coverage/setup.sh
Normal file
106
bin/tests/system/coverage/setup.sh
Normal file
@ -0,0 +1,106 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
SYSTEMTESTTOP=..
|
||||
. $SYSTEMTESTTOP/conf.sh
|
||||
|
||||
KEYGEN="$KEYGEN -qr random.data"
|
||||
|
||||
sh clean.sh
|
||||
|
||||
ln -s $CHECKZONE named-compilezone
|
||||
../../../tools/genrandom 400 random.data
|
||||
|
||||
# Test 1: KSK goes inactive before successor is active
|
||||
dir=01-ksk-inactive
|
||||
rm -f $dir/K*.key
|
||||
rm -f $dir/K*.private
|
||||
ksk1=`$KEYGEN -K $dir -3fk example.com`
|
||||
$SETTIME -K $dir -I +9mo -D +1y $ksk1 > /dev/null 2>&1
|
||||
ksk2=`$KEYGEN -K $dir -S $ksk1`
|
||||
$SETTIME -K $dir -I +7mo $ksk1 > /dev/null 2>&1
|
||||
zsk1=`$KEYGEN -K $dir -3 example.com`
|
||||
|
||||
# Test 2: ZSK goes inactive before successor is active
|
||||
dir=02-zsk-inactive
|
||||
rm -f $dir/K*.key
|
||||
rm -f $dir/K*.private
|
||||
zsk1=`$KEYGEN -K $dir -3 example.com`
|
||||
$SETTIME -K $dir -I +9mo -D +1y $zsk1 > /dev/null 2>&1
|
||||
zsk2=`$KEYGEN -K $dir -S $zsk1`
|
||||
$SETTIME -K $dir -I +7mo $zsk1 > /dev/null 2>&1
|
||||
ksk1=`$KEYGEN -K $dir -3fk example.com`
|
||||
|
||||
# Test 3: KSK is unpublished before its successor is published
|
||||
dir=03-ksk-unpublished
|
||||
rm -f $dir/K*.key
|
||||
rm -f $dir/K*.private
|
||||
ksk1=`$KEYGEN -K $dir -3fk example.com`
|
||||
$SETTIME -K $dir -I +9mo -D +1y $ksk1 > /dev/null 2>&1
|
||||
ksk2=`$KEYGEN -K $dir -S $ksk1`
|
||||
$SETTIME -K $dir -D +6mo $ksk1 > /dev/null 2>&1
|
||||
zsk1=`$KEYGEN -K $dir -3 example.com`
|
||||
|
||||
# Test 4: ZSK is unpublished before its successor is published
|
||||
dir=04-zsk-unpublished
|
||||
rm -f $dir/K*.key
|
||||
rm -f $dir/K*.private
|
||||
zsk1=`$KEYGEN -K $dir -3 example.com`
|
||||
$SETTIME -K $dir -I +9mo -D +1y $zsk1 > /dev/null 2>&1
|
||||
zsk2=`$KEYGEN -K $dir -S $zsk1`
|
||||
$SETTIME -K $dir -D +6mo $zsk1 > /dev/null 2>&1
|
||||
ksk1=`$KEYGEN -K $dir -3fk example.com`
|
||||
|
||||
# Test 5: KSK deleted and successor published before KSK is deactivated
|
||||
# and successor activated.
|
||||
dir=05-ksk-unpub-active
|
||||
rm -f $dir/K*.key
|
||||
rm -f $dir/K*.private
|
||||
ksk1=`$KEYGEN -K $dir -3fk example.com`
|
||||
$SETTIME -K $dir -I +9mo -D +8mo $ksk1 > /dev/null 2>&1
|
||||
ksk2=`$KEYGEN -K $dir -S $ksk1`
|
||||
zsk1=`$KEYGEN -K $dir -3 example.com`
|
||||
|
||||
# Test 6: ZSK deleted and successor published before ZSK is deactivated
|
||||
# and successor activated.
|
||||
dir=06-zsk-unpub-active
|
||||
rm -f $dir/K*.key
|
||||
rm -f $dir/K*.private
|
||||
zsk1=`$KEYGEN -K $dir -3 example.com`
|
||||
$SETTIME -K $dir -I +9mo -D +8mo $zsk1 > /dev/null 2>&1
|
||||
zsk2=`$KEYGEN -K $dir -S $zsk1`
|
||||
ksk1=`$KEYGEN -K $dir -3fk example.com`
|
||||
|
||||
# Test 7: KSK rolled with insufficient delay after prepublication.
|
||||
dir=07-ksk-ttl
|
||||
rm -f $dir/K*.key
|
||||
rm -f $dir/K*.private
|
||||
ksk1=`$KEYGEN -K $dir -3fk example.com`
|
||||
$SETTIME -K $dir -I +9mo -D +1y $ksk1 > /dev/null 2>&1
|
||||
ksk2=`$KEYGEN -K $dir -S $ksk1`
|
||||
# allow only 1 day between publication and activation
|
||||
$SETTIME -K $dir -P +269d $ksk2 > /dev/null 2>&1
|
||||
zsk1=`$KEYGEN -K $dir -3 example.com`
|
||||
|
||||
# Test 8: ZSK rolled with insufficient delay after prepublication.
|
||||
dir=08-zsk-ttl
|
||||
rm -f $dir/K*.key
|
||||
rm -f $dir/K*.private
|
||||
zsk1=`$KEYGEN -K $dir -3 example.com`
|
||||
$SETTIME -K $dir -I +9mo -D +1y $zsk1 > /dev/null 2>&1
|
||||
zsk2=`$KEYGEN -K $dir -S $zsk1`
|
||||
# allow only 1 day between publication and activation
|
||||
$SETTIME -K $dir -P +269d $zsk2 > /dev/null 2>&1
|
||||
ksk1=`$KEYGEN -K $dir -3fk example.com`
|
67
bin/tests/system/coverage/tests.sh
Normal file
67
bin/tests/system/coverage/tests.sh
Normal file
@ -0,0 +1,67 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
SYSTEMTESTTOP=..
|
||||
. $SYSTEMTESTTOP/conf.sh
|
||||
|
||||
COVERAGE="$COVERAGE -c ./named-compilezone"
|
||||
|
||||
status=0
|
||||
n=1
|
||||
|
||||
matchall () {
|
||||
file=$1
|
||||
echo "$2" | while read matchline; do
|
||||
grep "$matchline" $file > /dev/null 2>&1 || {
|
||||
echo "FAIL"
|
||||
return
|
||||
}
|
||||
done
|
||||
}
|
||||
|
||||
echo "I:checking for DNSSEC key coverage issues"
|
||||
ret=0
|
||||
for dir in [0-9][0-9]-*; do
|
||||
ret=0
|
||||
echo "I:$dir"
|
||||
args= warn= error= ok= retcode= match=
|
||||
. $dir/expect
|
||||
$COVERAGE $args -K $dir example.com > coverage.$n 2>&1
|
||||
|
||||
# check that return code matches expectations
|
||||
[ $? -eq $retcode ] || ret=1
|
||||
|
||||
# check for correct number of errors
|
||||
found=`grep ERROR coverage.$n | wc -l`
|
||||
[ $found -eq $error ] || ret=1
|
||||
|
||||
# check for correct number of warnings
|
||||
found=`grep WARNING coverage.$n | wc -l`
|
||||
[ $found -eq $warn ] || ret=1
|
||||
|
||||
# check for correct number of OKs
|
||||
found=`grep "No errors found" coverage.$n | wc -l`
|
||||
[ $found -eq $ok ] || ret=1
|
||||
|
||||
found=`matchall coverage.$n "$match"`
|
||||
[ "$found" = "FAIL" ] && ret=1
|
||||
|
||||
n=`expr $n + 1`
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
done
|
||||
|
||||
echo "I:exit status: $status"
|
||||
exit $status
|
@ -1236,6 +1236,18 @@ israw1 signer/signer.out.7 || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking dnssec-signzone output format ($n)"
|
||||
ret=0
|
||||
(
|
||||
cd signer
|
||||
$SIGNER -O full -f - -Sxt -o example example.db > signer.out.3 2>&1
|
||||
$SIGNER -O text -f - -Sxt -o example example.db > signer.out.4 2>&1
|
||||
) || ret=1
|
||||
awk '/IN *SOA/ {if (NF != 11) exit(1)}' signer/signer.out.3 || ret=1
|
||||
awk '/IN *SOA/ {if (NF != 7) exit(1)}' signer/signer.out.4 || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking validated data are not cached longer than originalttl ($n)"
|
||||
ret=0
|
||||
$DIG $DIGOPTS +ttl +noauth a.ttlpatch.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
|
||||
@ -2011,5 +2023,14 @@ n=`expr $n + 1`
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:check dnssec-dsfromkey from stdin($n)"
|
||||
ret=0
|
||||
$DIG $DIGOPTS dnskey algroll. @10.53.0.2 | \
|
||||
$DSFROMKEY -f - algroll. > dig.out.ns2.test$n || ret=1
|
||||
diff -b dig.out.ns2.test$n ns1/dsset-algroll. > /dev/null 2>&1 || ret=1
|
||||
n=`expr $n + 1`
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:exit status: $status"
|
||||
exit $status
|
||||
|
8
configure
vendored
8
configure
vendored
@ -1339,6 +1339,7 @@ ISC_PLATFORM_NORETURN_PRE
|
||||
ISC_PLATFORM_HAVELONGLONG
|
||||
ISC_SOCKADDR_LEN_T
|
||||
PYTHON_TOOLS
|
||||
COVERAGE
|
||||
CHECKDS
|
||||
PYTHON
|
||||
PERL
|
||||
@ -12206,6 +12207,7 @@ $as_echo "found, using $PYTHON" >&6; }
|
||||
unspec)
|
||||
PYTHON=""
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not found, python disabled" >&5
|
||||
$as_echo "not found, python disabled" >&6; }
|
||||
;;
|
||||
@ -12221,13 +12223,16 @@ esac
|
||||
|
||||
PYTHON_TOOLS=''
|
||||
CHECKDS=''
|
||||
COVERAGE=''
|
||||
if test "X$PYTHON" != "X"; then
|
||||
PYTHON_TOOLS=python
|
||||
CHECKDS=checkds
|
||||
COVERAGE=coverage
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Special processing of paths depending on whether --prefix,
|
||||
# --sysconfdir or --localstatedir arguments were given. What's
|
||||
@ -20838,7 +20843,7 @@ ac_config_commands="$ac_config_commands chmod"
|
||||
# elsewhere if there's a good reason for doing so.
|
||||
#
|
||||
|
||||
ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/dnssec-checkds.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/dst/Kdh.+002+18602.key bin/tests/dst/Kdh.+002+18602.private bin/tests/dst/Kdh.+002+48957.key bin/tests/dst/Kdh.+002+48957.private bin/tests/dst/Ktest.+001+00002.key bin/tests/dst/Ktest.+001+54622.key bin/tests/dst/Ktest.+001+54622.private bin/tests/dst/Ktest.+003+23616.key bin/tests/dst/Ktest.+003+23616.private bin/tests/dst/Ktest.+003+49667.key bin/tests/dst/dst_2_data bin/tests/dst/t2_data_1 bin/tests/dst/t2_data_2 bin/tests/dst/t2_dsasig bin/tests/dst/t2_rsasig bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/conf.sh bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/dsdigest/prereq.sh bin/tests/system/ecdsa/prereq.sh bin/tests/system/dlzredir/prereq.sh bin/tests/system/filter-aaaa/Makefile bin/tests/system/geoip/Makefile bin/tests/system/gost/prereq.sh bin/tests/system/lwresd/Makefile bin/tests/system/rpz/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile bin/tests/system/tsiggss/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/check-secure-delegation.pl contrib/zone-edit.sh doc/Makefile doc/arm/Makefile doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-docbook-latex.xsl doc/xsl/isc-manpage.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/export/Makefile lib/export/dns/Makefile lib/export/dns/include/Makefile lib/export/dns/include/dns/Makefile lib/export/dns/include/dst/Makefile lib/export/irs/Makefile lib/export/irs/include/Makefile lib/export/irs/include/irs/Makefile lib/export/isc/$thread_dir/Makefile lib/export/isc/$thread_dir/include/Makefile lib/export/isc/$thread_dir/include/isc/Makefile lib/export/isc/Makefile lib/export/isc/include/Makefile lib/export/isc/include/isc/Makefile lib/export/isc/nls/Makefile lib/export/isc/unix/Makefile lib/export/isc/unix/include/Makefile lib/export/isc/unix/include/isc/Makefile lib/export/isccfg/Makefile lib/export/isccfg/include/Makefile lib/export/isccfg/include/isccfg/Makefile lib/export/samples/Makefile lib/export/samples/Makefile-postinstall lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile unit/Makefile unit/unittest.sh"
|
||||
ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/dnssec-checkds.py bin/python/dnssec-coverage.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/dst/Kdh.+002+18602.key bin/tests/dst/Kdh.+002+18602.private bin/tests/dst/Kdh.+002+48957.key bin/tests/dst/Kdh.+002+48957.private bin/tests/dst/Ktest.+001+00002.key bin/tests/dst/Ktest.+001+54622.key bin/tests/dst/Ktest.+001+54622.private bin/tests/dst/Ktest.+003+23616.key bin/tests/dst/Ktest.+003+23616.private bin/tests/dst/Ktest.+003+49667.key bin/tests/dst/dst_2_data bin/tests/dst/t2_data_1 bin/tests/dst/t2_data_2 bin/tests/dst/t2_dsasig bin/tests/dst/t2_rsasig bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/conf.sh bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/dsdigest/prereq.sh bin/tests/system/ecdsa/prereq.sh bin/tests/system/dlzredir/prereq.sh bin/tests/system/filter-aaaa/Makefile bin/tests/system/geoip/Makefile bin/tests/system/gost/prereq.sh bin/tests/system/lwresd/Makefile bin/tests/system/rpz/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile bin/tests/system/tsiggss/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/check-secure-delegation.pl contrib/zone-edit.sh doc/Makefile doc/arm/Makefile doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-docbook-latex.xsl doc/xsl/isc-manpage.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/export/Makefile lib/export/dns/Makefile lib/export/dns/include/Makefile lib/export/dns/include/dns/Makefile lib/export/dns/include/dst/Makefile lib/export/irs/Makefile lib/export/irs/include/Makefile lib/export/irs/include/irs/Makefile lib/export/isc/$thread_dir/Makefile lib/export/isc/$thread_dir/include/Makefile lib/export/isc/$thread_dir/include/isc/Makefile lib/export/isc/Makefile lib/export/isc/include/Makefile lib/export/isc/include/isc/Makefile lib/export/isc/nls/Makefile lib/export/isc/unix/Makefile lib/export/isc/unix/include/Makefile lib/export/isc/unix/include/isc/Makefile lib/export/isccfg/Makefile lib/export/isccfg/include/Makefile lib/export/isccfg/include/isccfg/Makefile lib/export/samples/Makefile lib/export/samples/Makefile-postinstall lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile unit/Makefile unit/unittest.sh"
|
||||
|
||||
|
||||
#
|
||||
@ -21846,6 +21851,7 @@ do
|
||||
"bin/pkcs11/Makefile") CONFIG_FILES="$CONFIG_FILES bin/pkcs11/Makefile" ;;
|
||||
"bin/python/Makefile") CONFIG_FILES="$CONFIG_FILES bin/python/Makefile" ;;
|
||||
"bin/python/dnssec-checkds.py") CONFIG_FILES="$CONFIG_FILES bin/python/dnssec-checkds.py" ;;
|
||||
"bin/python/dnssec-coverage.py") CONFIG_FILES="$CONFIG_FILES bin/python/dnssec-coverage.py" ;;
|
||||
"bin/rndc/Makefile") CONFIG_FILES="$CONFIG_FILES bin/rndc/Makefile" ;;
|
||||
"bin/tests/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/Makefile" ;;
|
||||
"bin/tests/atomic/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/atomic/Makefile" ;;
|
||||
|
@ -179,6 +179,7 @@ except: exit(1)'
|
||||
unspec)
|
||||
PYTHON=""
|
||||
AC_SUBST(CHECKDS)
|
||||
AC_SUBST(COVERAGE)
|
||||
AC_MSG_RESULT([not found, python disabled])
|
||||
;;
|
||||
yes)
|
||||
@ -192,11 +193,14 @@ esac
|
||||
|
||||
PYTHON_TOOLS=''
|
||||
CHECKDS=''
|
||||
COVERAGE=''
|
||||
if test "X$PYTHON" != "X"; then
|
||||
PYTHON_TOOLS=python
|
||||
CHECKDS=checkds
|
||||
COVERAGE=coverage
|
||||
fi
|
||||
AC_SUBST(CHECKDS)
|
||||
AC_SUBST(COVERAGE)
|
||||
AC_SUBST(PYTHON_TOOLS)
|
||||
|
||||
#
|
||||
@ -3778,6 +3782,7 @@ AC_CONFIG_FILES([
|
||||
bin/pkcs11/Makefile
|
||||
bin/python/Makefile
|
||||
bin/python/dnssec-checkds.py
|
||||
bin/python/dnssec-coverage.py
|
||||
bin/rndc/Makefile
|
||||
bin/tests/Makefile
|
||||
bin/tests/atomic/Makefile
|
||||
|
@ -17504,6 +17504,8 @@ zone "example.com" {
|
||||
<title>Manual pages</title>
|
||||
<xi:include href="../../bin/dig/dig.docbook"/>
|
||||
<xi:include href="../../bin/dig/host.docbook"/>
|
||||
<xi:include href="../../bin/python/dnssec-checkds.docbook"/>
|
||||
<xi:include href="../../bin/python/dnssec-coverage.docbook"/>
|
||||
<xi:include href="../../bin/dnssec/dnssec-dsfromkey.docbook"/>
|
||||
<xi:include href="../../bin/dnssec/dnssec-keyfromlabel.docbook"/>
|
||||
<xi:include href="../../bin/dnssec/dnssec-keygen.docbook"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user