Commit 4a2f72fb authored by Tony Finch's avatar Tony Finch
Browse files

dnssec-checkds CDS support, and other improvements

* Use `dnssec-dsfromkey -p` to work out what the delegation records
  should be, based on CDS records.

* Better error checking for failures by `dig`.

* Add a --every mode for checking all the parent name servers. This is
  for extra protection against long propagation delays.

* Add a --quiet mode to avoid unwanted cronspam. There is still output
  if something unexpected happens, so --quiet mode is better for cron
  jobs than just redirecting the output.

* Explain how this tool relates to other tools. The current strict
  consistency logic was introduced when SHA-1 was deprecated, but it
  wasn't documented. The manual has now been updated. (Users who want
  checks based on validation semantics should use something like
  zonemaster or dnsviz instead.)
parent 5971eed2
Pipeline #32180 failed with stages
in 21 minutes and 5 seconds
......@@ -9,7 +9,7 @@
'\" t
.\" Title: dnssec-checkds
.\" Author:
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 2013-01-01
.\" Manual: BIND9
.\" Source: ISC
......@@ -38,12 +38,44 @@
.SH "NAME"
dnssec-checkds \- DNSSEC delegation consistency checking tool
.SH "SYNOPSIS"
.HP \w'\fBdnssec\-checkds\fR\ 'u
\fBdnssec\-checkds\fR [\fB\-d\ \fR\fB\fIdig\ path\fR\fR] [\fB\-D\ \fR\fB\fIdsfromkey\ path\fR\fR] [\fB\-f\ \fR\fB\fIfile\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-s\ \fR\fB\fIfile\fR\fR] {zone}
.HP 15
\fBdnssec\-checkds\fR [\fB\-a\ \fR\fB\fIalg\fR\fR] [\fB\-d\ \fR\fB\fIdig\ path\fR\fR] [\fB\-D\ \fR\fB\fIdsfromkey\ path\fR\fR] [\fB\-e\fR] [\fB\-f\ \fR\fB\fIfile\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-q\fR] [\fB\-s\ \fR\fB\fIfile\fR\fR] {zone}
.SH "DESCRIPTION"
.PP
The
\fBdnssec\-checkds\fR
verifies the correctness of Delegation Signer (DS) resource records for keys in a specified zone\&.
command checks whether a zone\*(Aqs DNSSEC delegation records are consistent with its DNSSEC apex records\&. It is used by
\fBdnssec\-keymgr\fR
during a key rollover to find out whether the zone\*(Aqs delegation has been updated, so the rollover can safely proceed to the next step\&.
.PP
This consistency check is not the same as a DNSSEC validation check\&. In many cases it is stricter: for example, superfluous DS records are benign for validation, but count as an inconsistency\&. It can also be weaker, if there is an error in the zone\*(Aqs key schedule: for example, if the zone\*(Aqs CDS records and DS records are consistent with each other, but do not match any DNSKEY record\&.
.PP
Normally, the
\fBdnssec\-checkds\fR
command checks Delegation Signer (DS) records in the zone\*(Aqs parent, queried from the default DNS resolver\&. With the
\fB\-l\fR
option it checks DNSSEC Lookaside Validation (DLV) records in a specified lookaside zone\&. The delegation records can be checked against a dsset file with the
\fB\-s\fR
option, or against every parent name server with the
\fB\-e\fR
option\&.
.PP
The delegation records expected by
\fBdnssec\-checkds\fR
are generated from the zone\*(Aqs apex Child DS (CDS), CDNSKEY, and DNSKEY records using
\fBdnssec\-dsfromkey\fR
\fB\-p\fR\&. These apex records are managed by
\fBdnssec\-keymgr\fR
and the
\fBdnssec\-settime\fR
\fB\-P sync\fR
and
\fB\-D sync\fR
options\&. By default
\fBdnssec\-checkds\fR
queries these records from the default DNS resolver; with the
\fB\-f\fR
option it reads them from a file instead\&.
.SH "OPTIONS"
.PP
\-a \fIalgorithm\fR
......@@ -55,37 +87,75 @@ The
must be one of SHA\-1, SHA\-256, or SHA\-384\&. These values are case insensitive, and the hyphen may be omitted\&. If no algorithm is specified, the default is SHA\-256\&.
.RE
.PP
\-d \fIdig path\fR
.RS 4
Specifies a path to a
\fBdig\fR
binary\&. Used for regression tests\&.
.RE
.PP
\-D \fIdsfromkey path\fR
.RS 4
Specifies a path to a
\fBdnssec\-dsfromkey\fR
binary\&. Used for regression tests\&.
.RE
.PP
\-e
.RS 4
Check consistency at every name server for the parent zone (or the lookaside zone if the
\fB\-l\fR
option is given)\&. By default, only the local resolver is checked\&. The
\fB\-e\fR
option can protect against propagation delays between parent zone name servers\&. The
\fB\-e\fR
option conflicts with the
\fB\-s\fR
option\&.
.RE
.PP
\-f \fIfile\fR
.RS 4
If a
\fBfile\fR
is specified, then the zone is read from that file to find the DNSKEY records\&. If not, then the DNSKEY records for the zone are looked up in the DNS\&.
is specified, then the zone is read from that file to find the CDS, CDNSKEY, and DNSKEY records, instead of querying the DNS\&.
.RE
.PP
\-s \fIfile\fR
\-l \fIdomain\fR
.RS 4
Specifies a prepared dsset file, such as would be generated by
\fBdnssec\-signzone\fR, to use as a source for the DS RRset instead of querying the parent\&.
Check for a DLV record in the specified lookaside domain, instead of checking for a DS record in the zone\*(Aqs parent\&.
.RE
.PP
\-d \fIdig path\fR
\-q
.RS 4
Specifies a path to a
\fBdig\fR
binary\&. Used for testing\&.
Quiet mode: only return the exit status\&. Nothing is printed unless there are unexpected problems (inconsistent delegations are expected)\&. The
\fB\-q\fR
option is for use in cron jobs when waiting for a delegation to be updated\&.
.RE
.PP
\-D \fIdsfromkey path\fR
\-s \fIfile\fR
.RS 4
Specifies a path to a
\fBdnssec\-dsfromkey\fR
binary\&. Used for testing\&.
Specifies a prepared dsset file, such as would be generated by
\fBdnssec\-signzone\fR, to use as a source for the DS RRset instead of querying the parent\&. The
\fB\-s\fR
option conflicts with the
\fB\-e\fR
option\&.
.RE
.SH "EXIT STATUS"
.PP
Returns zero if the delegation and apex records match
.PP
Returns one if they do not match
.PP
Returns two if there is an unexpected error
.SH "SEE ALSO"
.PP
\fBdig\fR(1),
\fBdnssec-dsfromkey\fR(8),
\fBdnssec-keygen\fR(8),
\fBdnssec-signzone\fR(8),
\fBdnssec-keymgr\fR(8),
\fBdnssec-settime\fR(8),
\fBdnssec-signzone\fR(8)\&.
.SH "AUTHOR"
.PP
\fBInternet Systems Consortium, Inc\&.\fR
......
......@@ -48,10 +48,13 @@
<refsynopsisdiv>
<cmdsynopsis sepchar=" ">
<command>dnssec-checkds</command>
<arg choice="opt"><option>-a <replaceable class="parameter">alg</replaceable></option></arg>
<arg choice="opt" rep="norepeat"><option>-d <replaceable class="parameter">dig path</replaceable></option></arg>
<arg choice="opt" rep="norepeat"><option>-D <replaceable class="parameter">dsfromkey path</replaceable></option></arg>
<arg choice="opt" rep="norepeat"><option>-e</option></arg>
<arg choice="opt" rep="norepeat"><option>-f <replaceable class="parameter">file</replaceable></option></arg>
<arg choice="opt" rep="norepeat"><option>-l <replaceable class="parameter">domain</replaceable></option></arg>
<arg choice="opt" rep="norepeat"><option>-q</option></arg>
<arg choice="opt" rep="norepeat"><option>-s <replaceable class="parameter">file</replaceable></option></arg>
<arg choice="req" rep="norepeat">zone</arg>
</cmdsynopsis>
......@@ -59,10 +62,50 @@
<refsection><info><title>DESCRIPTION</title></info>
<para><command>dnssec-checkds</command>
verifies the correctness of Delegation Signer (DS)
resource records for keys in a specified zone.
<para>
The <command>dnssec-checkds</command> command checks whether a
zone's DNSSEC delegation records are consistent with its DNSSEC
apex records. It is used by <command>dnssec-keymgr</command>
during a key rollover to find out whether the zone's delegation
has been updated, so the rollover can safely proceed to the next
step.
</para>
<para>
This consistency check is not the same as a DNSSEC validation
check. In many cases it is stricter: for example, superfluous DS
records are benign for validation, but count as an
inconsistency. It can also be weaker, if there is an error in
the zone's key schedule: for example, if the zone's CDS records
and DS records are consistent with each other, but do not match
any DNSKEY record.
</para>
<para>
Normally, the <command>dnssec-checkds</command> command checks
Delegation Signer (DS) records in the zone's parent, queried
from the default DNS resolver. With the <option>-l</option>
option it checks DNSSEC Lookaside Validation (DLV) records in a
specified lookaside zone. The delegation records can be checked
against a dsset file with the <option>-s</option> option, or
against every parent name server with the <option>-e</option>
option.
</para>
<para>
The delegation records expected
by <command>dnssec-checkds</command> are generated from the
zone's apex Child DS (CDS), CDNSKEY, and DNSKEY records
using <command>dnssec-dsfromkey</command> <option>-p</option>.
These apex records are managed
by <command>dnssec-keymgr</command> and
the <command>dnssec-settime</command> <option>-P sync</option>
and <option>-D sync</option> options. By
default <command>dnssec-checkds</command> queries these records
from the default DNS resolver; with the <option>-f</option>
option it reads them from a file instead.
</para>
</refsection>
<refsection><info><title>OPTIONS</title></info>
......@@ -87,61 +130,120 @@
</listitem>
</varlistentry>
<varlistentry>
<term>-d <replaceable class="parameter">dig path</replaceable></term>
<listitem>
<para>
Specifies a path to a <command>dig</command> binary. Used
for regression tests.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-D <replaceable class="parameter">dsfromkey path</replaceable></term>
<listitem>
<para>
Specifies a path to a <command>dnssec-dsfromkey</command> binary.
Used for regression tests.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-e</term>
<listitem>
<para>
Check consistency at every name server for the parent zone
(or the lookaside zone if the <option>-l</option> option
is given). By default, only the local resolver is checked.
The <option>-e</option> option can protect against
propagation delays between parent zone name servers.
The <option>-e</option> option conflicts with
the <option>-s</option> option.
</para>
</listitem>
</varlistentry>
<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 to find the DNSKEY records. If not,
then the DNSKEY records for the zone are looked up in the DNS.
read from that file to find the CDS, CDNSKEY, and DNSKEY
records, instead of querying the DNS.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-s <replaceable class="parameter">file</replaceable></term>
<term>-l <replaceable class="parameter">domain</replaceable></term>
<listitem>
<para>
Specifies a prepared dsset file, such as would be generated
by <command>dnssec-signzone</command>, to use as a source for
the DS RRset instead of querying the parent.
Check for a DLV record in the specified lookaside domain,
instead of checking for a DS record in the zone's parent.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-d <replaceable class="parameter">dig path</replaceable></term>
<term>-q</term>
<listitem>
<para>
Specifies a path to a <command>dig</command> binary. Used
for testing.
Quiet mode: only return the exit status. Nothing is
printed unless there are unexpected problems (inconsistent
delegations are expected). The <option>-q</option> option
is for use in cron jobs when waiting for a delegation to
be updated.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-D <replaceable class="parameter">dsfromkey path</replaceable></term>
<term>-s <replaceable class="parameter">file</replaceable></term>
<listitem>
<para>
Specifies a path to a <command>dnssec-dsfromkey</command> binary.
Used for testing.
Specifies a prepared dsset file, such as would be generated
by <command>dnssec-signzone</command>, to use as a source for
the DS RRset instead of querying the parent.
The <option>-s</option> option conflicts with
the <option>-e</option> option.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
<refsection><info><title>SEE ALSO</title></info>
<refsection><info><title>EXIT STATUS</title></info>
<para>
Returns zero if the delegation and apex records match
</para>
<para>
Returns one if they do not match
</para>
<para>
Returns two if there is an unexpected error
</para>
</refsection>
<para><citerefentry>
<refsection><info><title>SEE ALSO</title></info>
<para>
<citerefentry>
<refentrytitle>dig</refentrytitle><manvolnum>1</manvolnum>
</citerefentry>,
<citerefentry>
<refentrytitle>dnssec-dsfromkey</refentrytitle><manvolnum>8</manvolnum>
</citerefentry>,
<citerefentry>
<refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
<refentrytitle>dnssec-keymgr</refentrytitle><manvolnum>8</manvolnum>
</citerefentry>,
<citerefentry>
<refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
<refentrytitle>dnssec-settime</refentrytitle><manvolnum>8</manvolnum>
</citerefentry>,
<citerefentry>
<refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
</citerefentry>.
</para>
</refsection>
......
......@@ -10,113 +10,149 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>dnssec-checkds</title>
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
<a name="man.dnssec-checkds"></a><div class="titlepage"></div>
<div class="refnamediv">
<div class="refnamediv">
<h2>Name</h2>
<p>
<span class="application">dnssec-checkds</span>
&#8212; DNSSEC delegation consistency checking tool
</p>
<p><span class="application">dnssec-checkds</span> &#8212; DNSSEC delegation consistency checking tool</p>
</div>
<div class="refsynopsisdiv">
<div class="refsynopsisdiv">
<h2>Synopsis</h2>
<div class="cmdsynopsis"><p>
<code class="command">dnssec-checkds</code>
[<code class="option">-d <em class="replaceable"><code>dig path</code></em></code>]
[<code class="option">-D <em class="replaceable"><code>dsfromkey path</code></em></code>]
[<code class="option">-f <em class="replaceable"><code>file</code></em></code>]
[<code class="option">-l <em class="replaceable"><code>domain</code></em></code>]
[<code class="option">-s <em class="replaceable"><code>file</code></em></code>]
{zone}
</p></div>
</div>
<div class="refsection">
<div class="cmdsynopsis"><p><code class="command">dnssec-checkds</code> [<code class="option">-a <em class="replaceable"><code>alg</code></em></code>] [<code class="option">-d <em class="replaceable"><code>dig path</code></em></code>] [<code class="option">-D <em class="replaceable"><code>dsfromkey path</code></em></code>] [<code class="option">-e</code>] [<code class="option">-f <em class="replaceable"><code>file</code></em></code>] [<code class="option">-l <em class="replaceable"><code>domain</code></em></code>] [<code class="option">-q</code>] [<code class="option">-s <em class="replaceable"><code>file</code></em></code>] {zone}</p></div>
</div>
<div class="refsection">
<a name="id-1.7"></a><h2>DESCRIPTION</h2>
<p><span class="command"><strong>dnssec-checkds</strong></span>
verifies the correctness of Delegation Signer (DS)
resource records for keys in a specified zone.
<p>
The <span class="command"><strong>dnssec-checkds</strong></span> command checks whether a
zone's DNSSEC delegation records are consistent with its DNSSEC
apex records. It is used by <span class="command"><strong>dnssec-keymgr</strong></span>
during a key rollover to find out whether the zone's delegation
has been updated, so the rollover can safely proceed to the next
step.
</p>
<p>
This consistency check is not the same as a DNSSEC validation
check. In many cases it is stricter: for example, superfluous DS
records are benign for validation, but count as an
inconsistency. It can also be weaker, if there is an error in
the zone's key schedule: for example, if the zone's CDS records
and DS records are consistent with each other, but do not match
any DNSKEY record.
</p>
</div>
<div class="refsection">
<p>
Normally, the <span class="command"><strong>dnssec-checkds</strong></span> command checks
Delegation Signer (DS) records in the zone's parent, queried
from the default DNS resolver. With the <code class="option">-l</code>
option it checks DNSSEC Lookaside Validation (DLV) records in a
specified lookaside zone. The delegation records can be checked
against a dsset file with the <code class="option">-s</code> option, or
against every parent name server with the <code class="option">-e</code>
option.
</p>
<p>
The delegation records expected
by <span class="command"><strong>dnssec-checkds</strong></span> are generated from the
zone's apex Child DS (CDS), CDNSKEY, and DNSKEY records
using <span class="command"><strong>dnssec-dsfromkey</strong></span> <code class="option">-p</code>.
These apex records are managed
by <span class="command"><strong>dnssec-keymgr</strong></span> and
the <span class="command"><strong>dnssec-settime</strong></span> <code class="option">-P sync</code>
and <code class="option">-D sync</code> options. By
default <span class="command"><strong>dnssec-checkds</strong></span> queries these records
from the default DNS resolver; with the <code class="option">-f</code>
option it reads them from a file instead.
</p>
</div>
<div class="refsection">
<a name="id-1.8"></a><h2>OPTIONS</h2>
<div class="variablelist"><dl class="variablelist">
<div class="variablelist"><dl class="variablelist">
<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
<dd>
<p>
<p>
Specify a digest algorithm to use when converting the
zone's DNSKEY records to expected DS records. This
option can be repeated, so that multiple records are
checked for each DNSKEY record.
</p>
<p>
<p>
The <em class="replaceable"><code>algorithm</code></em> must be one of
SHA-1, SHA-256, or SHA-384. These values are case insensitive,
and the hyphen may be omitted. If no algorithm is specified,
the default is SHA-256.
</p>
</dd>
</dd>
<dt><span class="term">-d <em class="replaceable"><code>dig path</code></em></span></dt>
<dd><p>
Specifies a path to a <span class="command"><strong>dig</strong></span> binary. Used
for regression tests.
</p></dd>
<dt><span class="term">-D <em class="replaceable"><code>dsfromkey path</code></em></span></dt>
<dd><p>
Specifies a path to a <span class="command"><strong>dnssec-dsfromkey</strong></span> binary.
Used for regression tests.
</p></dd>
<dt><span class="term">-e</span></dt>
<dd><p>
Check consistency at every name server for the parent zone
(or the lookaside zone if the <code class="option">-l</code> option
is given). By default, only the local resolver is checked.
The <code class="option">-e</code> option can protect against
propagation delays between parent zone name servers.
The <code class="option">-e</code> option conflicts with
the <code class="option">-s</code> option.
</p></dd>
<dt><span class="term">-f <em class="replaceable"><code>file</code></em></span></dt>
<dd>
<p>
<dd><p>
If a <code class="option">file</code> is specified, then the zone is
read from that file to find the DNSKEY records. If not,
then the DNSKEY records for the zone are looked up in the DNS.
</p>
</dd>
read from that file to find the CDS, CDNSKEY, and DNSKEY
records, instead of querying the DNS.
</p></dd>
<dt><span class="term">-l <em class="replaceable"><code>domain</code></em></span></dt>
<dd><p>
Check for a DLV record in the specified lookaside domain,
instead of checking for a DS record in the zone's parent.
</p></dd>
<dt><span class="term">-q</span></dt>
<dd><p>
Quiet mode: only return the exit status. Nothing is
printed unless there are unexpected problems (inconsistent
delegations are expected). The <code class="option">-q</code> option
is for use in cron jobs when waiting for a delegation to
be updated.
</p></dd>
<dt><span class="term">-s <em class="replaceable"><code>file</code></em></span></dt>
<dd>
<p>
<dd><p>
Specifies a prepared dsset file, such as would be generated
by <span class="command"><strong>dnssec-signzone</strong></span>, to use as a source for
the DS RRset instead of querying the parent.
</p>
</dd>
<dt><span class="term">-d <em class="replaceable"><code>dig path</code></em></span></dt>
<dd>
<p>
Specifies a path to a <span class="command"><strong>dig</strong></span> binary. Used
for testing.
</p>
</dd>
<dt><span class="term">-D <em class="replaceable"><code>dsfromkey path</code></em></span></dt>
<dd>
<p>
Specifies a path to a <span class="command"><strong>dnssec-dsfromkey</strong></span> binary.
Used for testing.
</p>
</dd>
The <code class="option">-s</code> option conflicts with
the <code class="option">-e</code> option.
</p></dd>
</dl></div>
</div>
<div class="refsection">
<a name="id-1.9"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry">
<span class="refentrytitle">dnssec-dsfromkey</span>(8)
</span>,
<span class="citerefentry">
<span class="refentrytitle">dnssec-keygen</span>(8)
</span>,
<span class="citerefentry">
<span class="refentrytitle">dnssec-signzone</span>(8)
</span>,
</div>
<div class="refsection">
<a name="id-1.9"></a><h2>EXIT STATUS</h2>
<p>
Returns zero if the delegation and apex records match
</p>
<p>
Returns one if they do not match
</p>
<p>
Returns two if there is an unexpected error
</p>
</div>
</div>
<div class="refsection">
<a name="id-1.10"></a><h2>SEE ALSO</h2>
<p>
<span class="citerefentry"><span class="refentrytitle">dig</span>(1)</span>,
<span class="citerefentry"><span class="refentrytitle">dnssec-dsfromkey</span>(8)</span>,
<span class="citerefentry"><span class="refentrytitle">dnssec-keymgr</span>(8)</span>,
<span class="citerefentry"><span class="refentrytitle">dnssec-settime</span>(8)</span>,
<span class="citerefentry"><span class="refentrytitle">dnssec-signzone</span>(8)</span>.
</p>
</div>
</div></body>
</html>
......@@ -11,141 +11,203 @@
import argparse
import os
import re
import sys
from subprocess import Popen, PIPE
from isc.utils import prefix,version
from isc.utils import prefix, version
prog = 'dnssec-checkds'
digpath = None # for dig()
############################################################################
# SECRR class:
# Class for DS resource record
############################################################################
class SECRR:
hashalgs = {1: 'SHA-1', 2: 'SHA-256', 3: 'GOST', 4: 'SHA-384'}
rrname = ''
rrclass = 'IN'
keyid = None
keyalg = None
hashalg = None
digest = ''
ttl = 0
def __init__(self, rrtext):
if not rrtext:
raise Exception
# 'str' does not have decode method in python3
if type(rrtext) is not str:
fields = rrtext.decode('ascii').split()
else:
fields = rrtext.split()
if len(fields) < 7:
raise Exception
self.rrtype = "DS"
self.rrname = fields[0].lower()
fields = fields[1:]
if fields[0].upper() in ['IN', 'CH', 'HS']:
self.rrclass = fields[0].upper()
fields = fields[1:]