Commit ba37674d authored by Evan Hunt's avatar Evan Hunt

[master] dnssec-cds

4757.   [func]          New "dnssec-cds" command creates a new parent DS
                        RRset based on CDS or CDNSKEY RRsets found in
                        a child zone, and generates either a dsset file
                        or stream of nsupdate commands to update the
                        parent. Thanks to Tony Finch. [RT #46090]
parent 14afc842
4757. [func] New "dnssec-cds" command creates a new parent DS
RRset based on CDS or CDNSKEY RRsets found in
a child zone, and generates either a dsset file
or stream of nsupdate commands to update the
parent. Thanks to Tony Finch. [RT #46090]
4756. [bug] Interrupting dig could lead to an INSIST failure after
certain errors were encountered while querying a host
whose name resolved to more than one address. Change
......
dnssec-cds
dnssec-dsfromkey
dnssec-keyfromlabel
dnssec-keygen
......
......@@ -32,30 +32,37 @@ LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
NOSYMLIBS = ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@
# Alphabetically
TARGETS = dnssec-keygen@EXEEXT@ dnssec-signzone@EXEEXT@ \
dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@ \
dnssec-revoke@EXEEXT@ dnssec-settime@EXEEXT@ \
dnssec-verify@EXEEXT@ dnssec-importkey@EXEEXT@
TARGETS = dnssec-cds@EXEEXT@ dnssec-dsfromkey@EXEEXT@ \
dnssec-importkey@EXEEXT@ dnssec-keyfromlabel@EXEEXT@ \
dnssec-keygen@EXEEXT@ dnssec-revoke@EXEEXT@ \
dnssec-settime@EXEEXT@ dnssec-signzone@EXEEXT@ \
dnssec-verify@EXEEXT@
OBJS = dnssectool.@O@
SRCS = dnssec-dsfromkey.c dnssec-keyfromlabel.c dnssec-keygen.c \
dnssec-revoke.c dnssec-settime.c dnssec-signzone.c \
dnssec-verify.c dnssec-importkey.c dnssectool.c
SRCS = dnssec-cds.c dnssec-dsfromkey.c dnssec-importkey.c \
dnssec-keyfromlabel.c dnssec-keygen.c dnssec-revoke.c \
dnssec-settime.c dnssec-signzone.c dnssec-verify.c \
dnssectool.c
MANPAGES = dnssec-dsfromkey.8 dnssec-keyfromlabel.8 dnssec-keygen.8 \
dnssec-revoke.8 dnssec-settime.8 dnssec-signzone.8 \
dnssec-verify.8 dnssec-importkey.8
MANPAGES = dnssec-cds.8 dnssec-dsfromkey.8 dnssec-importkey.8 \
dnssec-keyfromlabel.8 dnssec-keygen.8 dnssec-revoke.8 \
dnssec-settime.8 dnssec-signzone.8 dnssec-verify.8
HTMLPAGES = dnssec-dsfromkey.html dnssec-keyfromlabel.html \
HTMLPAGES = dnssec-cds.html dnssec-dsfromkey.html \
dnssec-importkey.html dnssec-keyfromlabel.html \
dnssec-keygen.html dnssec-revoke.html \
dnssec-settime.html dnssec-signzone.html \
dnssec-verify.html dnssec-importkey.html
dnssec-verify.html
MANOBJS = ${MANPAGES} ${HTMLPAGES}
@BIND9_MAKE_RULES@
dnssec-cds@EXEEXT@: dnssec-cds.@O@ ${OBJS} ${DEPLIBS}
export BASEOBJS="dnssec-cds.@O@ ${OBJS}"; \
${FINALBUILDCMD}
dnssec-dsfromkey@EXEEXT@: dnssec-dsfromkey.@O@ ${OBJS} ${DEPLIBS}
export BASEOBJS="dnssec-dsfromkey.@O@ ${OBJS}"; \
${FINALBUILDCMD}
......@@ -115,4 +122,3 @@ uninstall::
clean distclean::
rm -f ${TARGETS}
.\" Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
.\"
.\" This Source Code Form is subject to the terms of the Mozilla Public
.\" License, v. 2.0. If a copy of the MPL was not distributed with this
.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
.\"
.hy 0
.ad l
'\" t
.\" Title: dnssec-cds
.\" Author:
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 2017-10-02
.\" Manual: BIND9
.\" Source: ISC
.\" Language: English
.\"
.TH "DNSSEC\-CDS" "8" "2017\-10\-02" "ISC" "BIND9"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\" http://bugs.debian.org/507673
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
dnssec-cds \- change DS records for a child zone based on CDS/CDNSKEY
.SH "SYNOPSIS"
.HP 11
\fBdnssec\-cds\fR [\fB\-a\ \fR\fB\fIalg\fR\fR...] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-D\fR] {\fB\-d\ \fR\fB\fIdsset\-file\fR\fR} {\fB\-f\ \fR\fB\fIchild\-file\fR\fR} [\fB\-i\fR\ [\fIextension\fR]] [\fB\-s\ \fR\fB\fIstart\-time\fR\fR] [\fB\-T\ \fR\fB\fIttl\fR\fR] [\fB\-u\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-V\fR] {domain}
.SH "DESCRIPTION"
.PP
The
\fBdnssec\-cds\fR
command changes DS records at a delegation point based on CDS or CDNSKEY records published in the child zone\&. If both CDS and CDNSKEY records are present in the child zone, the CDS is preferred\&.
.PP
Two input files are required\&. The
\fB\-f \fR\fB\fIchild\-file\fR\fR
option specifies a file containing the child\*(Aqs CDS and/or CDNSKEY records, plus RRSIG and DNSKEY records so that they can be authenticated\&. The
\fB\-d \fR\fB\fIpath\fR\fR
option specifies the location of a file containing the current DS records\&. For example, this could be a
dsset\-
file generated by
\fBdnssec\-signzone\fR, or the output of
\fBdnssec\-dsfromkey\fR, or the output of a previous run of
\fBdnssec\-cds\fR\&.
.PP
For protection against replay attacks, the signatures on the child records must not be older than they were on a previous run of
\fBdnssec\-cds\fR\&. This time is obtained from the modification time of the
dsset\-
file, or from the
\fB\-s\fR
option\&.
.PP
To protect against breaking the delegation,
\fBdnssec\-cds\fR
ensures that the DNSKEY RRset can be verified by every key algorithm in the new DS RRset, and that the same set of keys are covered by every DS digest type\&.
.PP
By default, replacement DS records are written to the standard output; with the
\fB\-i\fR
option the input file is overwritten in place\&. The replacement DS records will be the same as the existing records when no change is required\&. The output can be empty if the CDS / CDNSKEY records specify that the child zone wants to go insecure\&.
.PP
Warning: Be careful not to delete the DS records when
\fBdnssec\-cds\fR
fails!
.PP
Alternatively,
\fBdnssec\-cds \-u\fR
writes an
\fBnsupdate\fR
script to the standard output\&. You can use the
\fB\-u\fR
and
\fB\-i\fR
options together to maintain a
dsset\-
file as well as emit an
\fBnsupdate\fR
script\&.
.SH "OPTIONS"
.PP
\-a \fIalgorithm\fR
.RS 4
Specify a digest algorithm to use when converting CDNSKEY records to DS records\&. This option can be repeated, so that multiple DS records are created for each CDNSKEY record\&. This option has no effect when using CDS records\&.
.sp
The
\fIalgorithm\fR
must be one of SHA\-1 (SHA1), SHA\-256 (SHA256), GOST, or SHA\-384 (SHA384)\&. These values are case insensitive\&. If no algorithm is specified, the default is SHA\-256\&.
.RE
.PP
\-c \fIclass\fR
.RS 4
Specifies the DNS class of the zones\&.
.RE
.PP
\-D
.RS 4
Generate DS records from CDNSKEY records if both CDS and CDNSKEY records are present in the child zone\&. By default CDS records are preferred\&.
.RE
.PP
\-d \fIpath\fR
.RS 4
Location of the parent DS records\&. The
\fIpath\fR
can be the name of a file containing the DS records, or if it is a directory,
\fBdnssec\-cds\fR
looks for a
dsset\-
file for the
\fIdomain\fR
inside the directory\&.
.sp
To protect against replay attacks, child records are rejected if they were signed earlier than the modification time of the
dsset\-
file\&. This can be adjusted with the
\fB\-s\fR
option\&.
.RE
.PP
\-f \fIchild\-file\fR
.RS 4
File containing the child\*(Aqs CDS and/or CDNSKEY records, plus its DNSKEY records and the covering RRSIG records so that they can be authenticated\&.
.sp
The EXAMPLES below describe how to generate this file\&.
.RE
.PP
\-i [\fIextension\fR]
.RS 4
Update the
dsset\-
file in place, instead of writing DS records to the standard output\&.
.sp
There must be no space between the
\fB\-i\fR
and the
\fIextension\fR\&. If you provide no
\fIextension\fR
then the old
dsset\-
is discarded\&. If an
\fIextension\fR
is present, a backup of the old
dsset\-
file is kept with the
\fIextension\fR
appended to its filename\&.
.sp
To protect against replay attacks, the modification time of the
dsset\-
file is set to match the signature inception time of the child records, provided that is later than the file\*(Aqs current modification time\&.
.RE
.PP
\-s \fIstart\-time\fR
.RS 4
Specify the date and time after which RRSIG records become acceptable\&. This can be either an absolute or relative time\&. An absolute start time is indicated by a number in YYYYMMDDHHMMSS notation; 20170827133700 denotes 13:37:00 UTC on August 27th, 2017\&. A time relative to the
dsset\-
file is indicated with \-N, which is N seconds before the file modification time\&. A time relative to the current time is indicated with now+N\&.
.sp
If no
\fIstart\-time\fR
is specified, the modification time of the
dsset\-
file is used\&.
.RE
.PP
\-T \fIttl\fR
.RS 4
Specifies a TTL to be used for new DS records\&. If not specified, the default is the TTL of the old DS records\&. If they had no explicit TTL then the new DS records also have no explicit TTL\&.
.RE
.PP
\-u
.RS 4
Write an
\fBnsupdate\fR
script to the standard output, instead of printing the new DS reords\&. The output will be empty if no change is needed\&.
.sp
Note: The TTL of new records needs to be specified, either in the original
dsset\-
file, or with the
\fB\-T\fR
option, or using the
\fBnsupdate\fR
\fBttl\fR
command\&.
.RE
.PP
\-V
.RS 4
Print version information\&.
.RE
.PP
\-v \fIlevel\fR
.RS 4
Sets the debugging level\&. Level 1 is intended to be usefully verbose for general users; higher levels are intended for developers\&.
.RE
.PP
\fIdomain\fR
.RS 4
The name of the delegation point / child zone apex\&.
.RE
.SH "EXIT STATUS"
.PP
The
\fBdnssec\-cds\fR
command exits 0 on success, or non\-zero if an error occurred\&.
.PP
In the success case, the DS records might or might not need to be changed\&.
.SH "EXAMPLES"
.PP
Before running
\fBdnssec\-signzone\fR, you can ensure that the delegations are up\-to\-date by running
\fBdnssec\-cds\fR
on every
dsset\-
file\&.
.PP
To fetch the child records required by
\fBdnssec\-cds\fR
you can invoke
\fBdig\fR
as in the script below\&. It\*(Aqs okay if the
\fBdig\fR
fails since
\fBdnssec\-cds\fR
performs all the necessary checking\&.
.sp
.if n \{\
.RS 4
.\}
.nf
for f in dsset\-*
do
d=${f#dsset\-}
dig +dnssec +noall +answer $d DNSKEY $d CDNSKEY $d CDS |
dnssec\-cds \-i \-f /dev/stdin \-d $f $d
done
.fi
.if n \{\
.RE
.\}
.PP
When the parent zone is automatically signed by
\fBnamed\fR, you can use
\fBdnssec\-cds\fR
with
\fBnsupdate\fR
to maintain a delegation as follows\&. The
dsset\-
file allows the script to avoid having to fetch and validate the parent DS records, and it keeps the replay attack protection time\&.
.sp
.if n \{\
.RS 4
.\}
.nf
dig +dnssec +noall +answer $d DNSKEY $d CDNSKEY $d CDS |
dnssec\-cds \-u \-i \-f /dev/stdin \-d $f $d |
nsupdate \-l
.fi
.if n \{\
.RE
.\}
.SH "SEE ALSO"
.PP
\fBdig\fR(1),
\fBdnssec-settime\fR(8),
\fBdnssec-signzone\fR(8),
\fBnsupdate\fR(1),
BIND 9 Administrator Reference Manual,
RFC 7344\&.
.SH "AUTHORS"
.PP
\fBInternet Systems Consortium, Inc\&.\fR
.PP
\fBTony Finch\fR <\&dot@dotat\&.at\&>, <\&fanf2@cam\&.ac\&.uk\&>
.br
.RS 4
.RE
.SH "COPYRIGHT"
.br
Copyright \(co 2017 Internet Systems Consortium, Inc. ("ISC")
.br
/*
* Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
* Written by Tony Finch <dot@dotat.at> <fanf2@cam.ac.uk>
* at Cambridge University Information Services
*/
/*! \file */
#include <config.h>
#include <errno.h>
#include <stdlib.h>
#include <isc/buffer.h>
#include <isc/commandline.h>
#include <isc/entropy.h>
#include <isc/file.h>
#include <isc/hash.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/serial.h>
#include <isc/string.h>
#include <isc/time.h>
#include <isc/util.h>
#include <dns/callbacks.h>
#include <dns/db.h>
#include <dns/dbiterator.h>
#include <dns/dnssec.h>
#include <dns/ds.h>
#include <dns/fixedname.h>
#include <dns/keyvalues.h>
#include <dns/log.h>
#include <dns/master.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
#include <dns/rdatasetiter.h>
#include <dns/rdatatype.h>
#include <dns/result.h>
#include <dns/time.h>
#include <dst/dst.h>
#ifdef PKCS11CRYPTO
#include <pk11/result.h>
#endif
#include "dnssectool.h"
#ifndef PATH_MAX
#define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */
#endif
const char *program = "dnssec-cds";
int verbose;
/*
* Infrastructure
*/
static isc_log_t *lctx = NULL;
static isc_mem_t *mctx = NULL;
static isc_entropy_t *ectx = NULL;
/*
* The domain we are working on
*/
static const char *namestr = NULL;
static dns_fixedname_t fixed;
static dns_name_t *name = NULL;
static dns_rdataclass_t rdclass = dns_rdataclass_in;
/*
* List of digest types used by ds_from_cdnskey(), filled in by add_dtype()
* from -a arguments. The size of the array is an arbitrary limit.
*/
static isc_uint8_t dtype[8];
static const char *startstr = NULL; /* from which we derive notbefore */
static isc_stdtime_t notbefore = 0; /* restrict sig inception times */
static dns_rdata_rrsig_t oldestsig; /* for recording inception time */
static int nkey; /* number of child zone DNSKEY records */
/*
* The validation strategy of this program is top-down.
*
* We start with an implicitly trusted authoritative dsset.
*
* The child DNSKEY RRset is scanned to find out which keys are
* authenticated by DS records, and the result is recorded in a key
* table as described later in this comment.
*
* The key table is used up to three times to verify the signatures on
* the child DNSKEY, CDNSKEY, and CDS RRsets. In this program, only keys
* that have matching DS records are used for validating signatures.
*
* For replay attack protection, signatures are ignored if their inception
* time is before the previously recorded inception time. We use the earliest
* signature so that another run of dnssec-cds with the same records will
* still accept all the signatures.
*
* A key table is an array of nkey keyinfo structures, like
*
* keyinfo_t key_tbl[nkey];
*
* Each key is decoded into more useful representations, held in
* keyinfo->rdata
* keyinfo->dst
*
* If a key has no matching DS record then keyinfo->dst is NULL.
*
* The key algorithm and ID are saved in keyinfo->algo and
* keyinfo->tag for quicky skipping DS and RRSIG records that can't
* match.
*/
typedef struct keyinfo {
dns_rdata_t rdata;
dst_key_t *dst;
isc_uint8_t algo;
dns_keytag_t tag;
} keyinfo_t;
/* A replaceable function that can generate a DS RRset from some input */
typedef isc_result_t
ds_maker_func_t(dns_rdatalist_t *dslist, isc_buffer_t *buf, dns_rdata_t *rdata);
static dns_rdataset_t cdnskey_set, cdnskey_sig;
static dns_rdataset_t cds_set, cds_sig;
static dns_rdataset_t dnskey_set, dnskey_sig;
static dns_rdataset_t old_ds_set, new_ds_set;
static keyinfo_t *old_key_tbl, *new_key_tbl;
isc_buffer_t *new_ds_buf = NULL; /* backing store for new_ds_set */
static void
verbose_time(int level, const char *msg, isc_stdtime_t time) {
isc_result_t result;
isc_buffer_t timebuf;
char timestr[32];
if (verbose < level) {
return;
}
isc_buffer_init(&timebuf, timestr, sizeof(timestr));
result = dns_time64_totext(time, &timebuf);
check_result(result, "dns_time64_totext()");
isc_buffer_putuint8(&timebuf, 0);
if (verbose < 3) {
vbprintf(level, "%s %s\n", msg, timestr);
} else {
vbprintf(level, "%s %s (%lld)\n",
msg, timestr, (long long)time);
}
}
static void
initname(char *setname) {
isc_result_t result;
isc_buffer_t buf;
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
namestr = setname;
isc_buffer_init(&buf, setname, strlen(setname));
isc_buffer_add(&buf, strlen(setname));
result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS) {
fatal("could not initialize name %s", setname);
}
}
static void
findset(dns_db_t *db, dns_dbnode_t *node, dns_rdatatype_t type,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
{
isc_result_t result;
dns_rdataset_init(rdataset);
if (sigrdataset != NULL) {
dns_rdataset_init(sigrdataset);
}
result = dns_db_findrdataset(db, node, NULL, type, 0, 0,
rdataset, sigrdataset);
if (result != ISC_R_NOTFOUND) {
check_result(result, "dns_db_findrdataset()");
}
}
static void
freeset(dns_rdataset_t *rdataset) {
if (dns_rdataset_isassociated(rdataset)) {
dns_rdataset_disassociate(rdataset);
}
}
static void
freelist(dns_rdataset_t *rdataset) {
dns_rdatalist_t *rdlist;
dns_rdata_t *rdata;
if (!dns_rdataset_isassociated(rdataset)) {
return;
}
dns_rdatalist_fromrdataset(rdataset, &rdlist);
for (rdata = ISC_LIST_HEAD(rdlist->rdata);
rdata != NULL;
rdata = ISC_LIST_HEAD(rdlist->rdata))
{
ISC_LIST_UNLINK(rdlist->rdata, rdata, link);
isc_mem_put(mctx, rdata, sizeof(*rdata));
}
isc_mem_put(mctx, rdlist, sizeof(*rdlist));
dns_rdataset_disassociate(rdataset);
}
static void
free_all_sets(void) {
freeset(&cdnskey_set);
freeset(&cdnskey_sig);
freeset(&cds_set);
freeset(&cds_sig);
freeset(&dnskey_set);
freeset(&dnskey_sig);
freeset(&old_ds_set);
freelist(&new_ds_set);
if (new_ds_buf != NULL) {
isc_buffer_free(&new_ds_buf);
}
}
static void
load_db(const char *filename, dns_db_t **dbp, dns_dbnode_t **nodep) {
isc_result_t result;
result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
rdclass, 0, NULL, dbp);
check_result(result, "dns_db_create()");
result = dns_db_load3(*dbp, filename,
dns_masterformat_text, DNS_MASTER_HINT);
if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
fatal("can't load %s: %s", filename,
isc_result_totext(result));
}
result = dns_db_findnode(*dbp, name, ISC_FALSE, nodep);
if (result != ISC_R_SUCCESS) {
fatal("can't find %s node in %s", namestr, filename);
}
}
static void
free_db(dns_db_t **dbp, dns_dbnode_t **nodep) {
dns_db_detachnode(*dbp, nodep);
dns_db_detach(dbp);
}
static void
load_child_sets(const char *file) {
dns_db_t *db = NULL;
dns_dbnode_t *node = NULL;
load_db(file, &db, &node);
findset(db, node, dns_rdatatype_dnskey, &dnskey_set, &dnskey_sig);
findset(db, node, dns_rdatatype_cdnskey, &cdnskey_set, &cdnskey_sig);
findset(db, node, dns_rdatatype_cds, &cds_set, &cds_sig);
free_db(&db, &node);
}
static void
get_dsset_name(char *filename, size_t size,
const char *path, const char *suffix)
{
isc_result_t result;
isc_buffer_t buf;
size_t len;
isc_buffer_init(&buf, filename, size);
len = strlen(path);
/* allow room for a trailing slash */
if (isc_buffer_availablelength(&buf) <= len) {
fatal("%s: pathname too long", path);
}
isc_buffer_putstr(&buf, path);
if (isc_file_isdirectory(path) == ISC_R_SUCCESS) {
const char *prefix = "dsset-";
if (path[len - 1] != '/') {
isc_buffer_putstr(&buf, "/");
}
if (isc_buffer_availablelength(&buf) < strlen(prefix)) {
fatal("%s: pathname too long", path);
}
isc_buffer_putstr(&buf, prefix);
result = dns_name_tofilenametext(name, ISC_FALSE, &buf);
check_result(result, "dns_name_tofilenametext()");
if (isc_buffer_availablelength(&buf) == 0) {
fatal("%s: pathname too long", path);
}
}
/* allow room for a trailing nul */
if (isc_buffer_availablelength(&buf) <= strlen(suffix)) {
fatal("%s: pathname too long", path);
}
isc_buffer_putstr(&buf, suffix);
isc_buffer_putuint8(&buf, 0);
}
static void
load_parent_set(const char *path) {
isc_result_t result;
dns_db_t *db = NULL;
dns_dbnode_t *node = NULL;
isc_time_t modtime;
char filename[PATH_MAX + 1];
get_dsset_name(filename, sizeof(filename), path, "");
result = isc_file_getmodtime(filename, &modtime);
if (result != ISC_R_SUCCESS) {
fatal("could not get modification time of %s: %s",
filename, isc_result_totext(result));
}
notbefore = isc_time_seconds(&modtime);
if (startstr != NULL) {
isc_stdtime_t now;
isc_stdtime_get(&now);
notbefore = strtotime(startstr, now, notbefore, NULL);
}
verbose_time(1, "child records must not be signed before", notbefore);
load_db(filename, &db, &node);
findset(db, node, dns_rdatatype_ds, &old_ds_set, NULL);
if (!dns_rdataset_isassociated(&old_ds_set)) {
fatal("could not find DS records for %s in %s",
namestr, filename);
}
free_db(&db, &node);
}
static isc_buffer_t *
formatset(dns_rdataset_t *rdataset) {
isc_result_t result;
isc_buffer_t *buf = NULL;
dns_master_style_t *style = NULL;
unsigned int styleflags;
unsigned int size;
styleflags = (rdataset->ttl == 0) ? DNS_STYLEFLAG_NO_TTL : 0;
/*
* This style is for consistency with the output of dnssec-dsfromkey
* which just separates fields with spaces. The huge tab stop width
* eliminates any tab characters.
*/
result = dns_master_stylecreate2(&style, styleflags,
0, 0, 0, 0, 0, 1000000, 0,
mctx);
size = 256;
do {
result = isc_buffer_allocate(mctx, &buf, size);
check_result(result, "printing DS records");
result = dns_master_rdatasettotext(name, rdataset,
style, buf);
if (result == ISC_R_NOSPACE ||
isc_buffer_availablelength(buf) < 1)
{