Merge branch '1015-ds-sha-1-deprecation' into 'master'

Deprecate SHA-1 hash in DS/CDS

Closes #1015

See merge request isc-projects/bind9!1908
This commit is contained in:
Evan Hunt 2019-05-08 21:32:27 -04:00
commit a157e0ac04
21 changed files with 255 additions and 206 deletions

View file

@ -1,3 +1,6 @@
5230. [protocol] The SHA-1 hash algorithm is no longer used when
generating DS and CDS records. [GL #1015]
5229. [protocol] Enforce known SSHFP fingerprint lengths. [GL #852]
5228. [func] If trusted-keys and managed-keys were configured

View file

@ -59,12 +59,7 @@
#include "dnssectool.h"
#ifndef PATH_MAX
#define PATH_MAX 1024 /* WIN32, and others don't define this. */
#endif
const char *program = "dnssec-cds";
int verbose;
/*
* Infrastructure
@ -80,12 +75,6 @@ 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 dns_dsdigest_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 */
@ -836,34 +825,6 @@ ds_from_cdnskey(dns_rdatalist_t *dslist, isc_buffer_t *buf,
return (ISC_R_SUCCESS);
}
/*
* For sorting the digest types so that DS records generated
* from CDNSKEY records are in canonical order.
*/
static int
cmp_dtype(const void *ap, const void *bp) {
int a = *(const dns_dsdigest_t *)ap;
int b = *(const dns_dsdigest_t *)bp;
return (a - b);
}
static void
add_dtype(const char *dn) {
dns_dsdigest_t dt;
unsigned i, n;
dt = strtodsdigest(dn);
n = sizeof(dtype)/sizeof(dtype[0]);
for (i = 0; i < n; i++) {
if (dtype[i] == 0 || dtype[i] == dt) {
dtype[i] = dt;
qsort(dtype, i+1, 1, cmp_dtype);
return;
}
}
fatal("too many -a digest type arguments");
}
static void
make_new_ds_set(ds_maker_func_t *ds_from_rdata,
uint32_t ttl, dns_rdataset_t *rdset)
@ -1152,7 +1113,7 @@ main(int argc, char *argv[]) {
while ((ch = isc_commandline_parse(argc, argv, OPTIONS)) != -1) {
switch (ch) {
case 'a':
add_dtype(isc_commandline_argument);
add_dtype(strtodsdigest(isc_commandline_argument));
break;
case 'c':
rdclass = strtoclass(isc_commandline_argument);

View file

@ -47,12 +47,7 @@
#include "dnssectool.h"
#ifndef PATH_MAX
#define PATH_MAX 1024 /* WIN32, and others don't define this. */
#endif
const char *program = "dnssec-dsfromkey";
int verbose;
static dns_rdataclass_t rdclass;
static dns_fixedname_t fixed;
@ -233,7 +228,7 @@ logkey(dns_rdata_t *rdata)
}
static void
emit(dns_dsdigest_t dtype, bool showall, char *lookaside,
emit(dns_dsdigest_t dt, bool showall, char *lookaside,
bool cds, dns_rdata_t *rdata)
{
isc_result_t result;
@ -259,7 +254,7 @@ emit(dns_dsdigest_t dtype, bool showall, char *lookaside,
if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && !showall)
return;
result = dns_ds_buildrdata(name, rdata, dtype, buf, &ds);
result = dns_ds_buildrdata(name, rdata, dt, buf, &ds);
if (result != ISC_R_SUCCESS)
fatal("can't build record");
@ -310,6 +305,18 @@ emit(dns_dsdigest_t dtype, bool showall, char *lookaside,
printf("%.*s\n", (int)r.length, r.base);
}
static void
emits(bool showall, char *lookaside, bool cds, dns_rdata_t *rdata) {
unsigned i, n;
n = sizeof(dtype)/sizeof(dtype[0]);
for (i = 0; i < n; i++) {
if (dtype[i] != 0) {
emit(dtype[i], showall, lookaside, cds, rdata);
}
}
}
ISC_PLATFORM_NORETURN_PRE static void
usage(void) ISC_PLATFORM_NORETURN_POST;
@ -348,11 +355,9 @@ main(int argc, char **argv) {
char *lookaside = NULL;
char *endp;
int ch;
dns_dsdigest_t dtype = DNS_DSDIGEST_SHA1;
bool cds = false;
bool both = true;
bool usekeyset = false;
bool showall = false;
bool cds = false;
bool usekeyset = false;
bool showall = false;
isc_result_t result;
isc_log_t *log = NULL;
dns_rdataset_t rdataset;
@ -360,12 +365,14 @@ main(int argc, char **argv) {
dns_rdata_init(&rdata);
if (argc == 1)
if (argc == 1) {
usage();
}
result = isc_mem_create(0, 0, &mctx);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
fatal("out of memory");
}
#if USE_PKCS11
pk11_result_register();
@ -378,19 +385,16 @@ main(int argc, char **argv) {
while ((ch = isc_commandline_parse(argc, argv, OPTIONS)) != -1) {
switch (ch) {
case '1':
dtype = DNS_DSDIGEST_SHA1;
both = false;
add_dtype(DNS_DSDIGEST_SHA1);
break;
case '2':
dtype = DNS_DSDIGEST_SHA256;
both = false;
add_dtype(DNS_DSDIGEST_SHA256);
break;
case 'A':
showall = true;
break;
case 'a':
dtype = strtodsdigest(isc_commandline_argument);
both = false;
add_dtype(strtodsdigest(isc_commandline_argument));
break;
case 'C':
if (lookaside != NULL)
@ -458,22 +462,32 @@ main(int argc, char **argv) {
rdclass = strtoclass(classname);
if (usekeyset && filename != NULL)
if (usekeyset && filename != NULL) {
fatal("cannot use both -s and -f");
}
/* When not using -f, -A is implicit */
if (filename == NULL)
if (filename == NULL) {
showall = true;
}
if (argc < isc_commandline_index + 1 && filename == NULL)
/* Default digest type if none specified. */
if (dtype[0] == 0) {
dtype[0] = DNS_DSDIGEST_SHA256;
}
if (argc < isc_commandline_index + 1 && filename == NULL) {
fatal("the key file name was not specified");
if (argc > isc_commandline_index + 1)
}
if (argc > isc_commandline_index + 1) {
fatal("extraneous arguments");
}
result = dst_lib_init(mctx, NULL);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
fatal("could not initialize dst: %s",
isc_result_totext(result));
}
setup_logging(mctx, &log);
@ -483,38 +497,38 @@ main(int argc, char **argv) {
if (argc < isc_commandline_index + 1 && filename != NULL) {
/* using zone name as the zone file name */
namestr = filename;
} else
} else {
namestr = argv[isc_commandline_index];
}
result = initname(namestr);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
fatal("could not initialize name %s", namestr);
}
if (usekeyset)
if (usekeyset) {
result = loadkeyset(dir, &rdataset);
else
} else {
result = loadset(filename, &rdataset);
}
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
fatal("could not load DNSKEY set: %s\n",
isc_result_totext(result));
}
for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset)) {
result = dns_rdataset_next(&rdataset))
{
dns_rdata_init(&rdata);
dns_rdataset_current(&rdataset, &rdata);
if (verbose > 2)
if (verbose > 2) {
logkey(&rdata);
}
if (both) {
emit(DNS_DSDIGEST_SHA1, showall, lookaside,
cds, &rdata);
emit(DNS_DSDIGEST_SHA256, showall, lookaside,
cds, &rdata);
} else
emit(dtype, showall, lookaside, cds, &rdata);
emits(showall, lookaside, cds, &rdata);
}
} else {
unsigned char key_buf[DST_KEY_MAXSIZE];
@ -522,28 +536,25 @@ main(int argc, char **argv) {
loadkey(argv[isc_commandline_index], key_buf,
DST_KEY_MAXSIZE, &rdata);
if (both) {
emit(DNS_DSDIGEST_SHA1, showall, lookaside, cds,
&rdata);
emit(DNS_DSDIGEST_SHA256, showall, lookaside, cds,
&rdata);
} else
emit(dtype, showall, lookaside, cds, &rdata);
emits(showall, lookaside, cds, &rdata);
}
if (dns_rdataset_isassociated(&rdataset))
if (dns_rdataset_isassociated(&rdataset)) {
dns_rdataset_disassociate(&rdataset);
}
cleanup_logging(&log);
dst_lib_destroy();
dns_name_destroy();
if (verbose > 10)
if (verbose > 10) {
isc_mem_stats(mctx, stdout);
}
isc_mem_destroy(&mctx);
fflush(stdout);
if (ferror(stdout)) {
fprintf(stderr, "write error\n");
return (1);
} else
} else {
return (0);
}
}

View file

@ -12,7 +12,7 @@
<!-- Converted by db4-upgrade version 1.0 -->
<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dnssec-dsfromkey">
<info>
<date>2012-05-02</date>
<date>2019-05-08</date>
</info>
<refentryinfo>
<corpname>ISC</corpname>
@ -150,7 +150,9 @@
<term>-1</term>
<listitem>
<para>
An abbreviation for <option>-a SHA1</option>
An abbreviation for <option>-a SHA-1</option>.
(Note: The SHA-1 algorithm is no longer recommended for use
when generating new DS and CDS records.)
</para>
</listitem>
</varlistentry>
@ -159,7 +161,7 @@
<term>-2</term>
<listitem>
<para>
An abbreviation for <option>-a SHA-256</option>
An abbreviation for <option>-a SHA-256</option>.
</para>
</listitem>
</varlistentry>
@ -178,6 +180,8 @@
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.
(Note: The SHA-1 algorithm is no longer recommended for use
when generating new DS and CDS records.)
</para>
</listitem>
</varlistentry>

View file

@ -46,12 +46,7 @@
#include "dnssectool.h"
#ifndef PATH_MAX
#define PATH_MAX 1024 /* WIN32, and others don't define this. */
#endif
const char *program = "dnssec-importkey";
int verbose;
static dns_rdataclass_t rdclass;
static dns_fixedname_t fixed;

View file

@ -46,7 +46,6 @@
#define MAX_RSA 4096 /* should be long enough... */
const char *program = "dnssec-keyfromlabel";
int verbose;
ISC_PLATFORM_NORETURN_PRE static void
usage(void) ISC_PLATFORM_NORETURN_POST;

View file

@ -61,7 +61,6 @@
#define MAX_RSA 4096 /* should be long enough... */
const char *program = "dnssec-keygen";
int verbose;
ISC_PLATFORM_NORETURN_PRE static void
usage(void) ISC_PLATFORM_NORETURN_POST;

View file

@ -37,7 +37,6 @@
#include "dnssectool.h"
const char *program = "dnssec-revoke";
int verbose;
static isc_mem_t *mctx = NULL;

View file

@ -40,7 +40,6 @@
#include "dnssectool.h"
const char *program = "dnssec-settime";
int verbose;
static isc_mem_t *mctx = NULL;

View file

@ -86,12 +86,7 @@
#include "dnssectool.h"
#ifndef PATH_MAX
#define PATH_MAX 1024 /* WIN32, and others don't define this. */
#endif
const char *program = "dnssec-signzone";
int verbose;
typedef struct hashlist hashlist_t;
@ -992,16 +987,6 @@ loadds(dns_name_t *name, uint32_t ttl, dns_rdataset_t *dsset) {
dns_rdata_init(&key);
dns_rdata_init(&ds);
dns_rdataset_current(&keyset, &key);
result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
dsbuf, &ds);
check_result(result, "dns_ds_buildrdata");
result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name,
ttl, &ds, &tuple);
check_result(result, "dns_difftuple_create");
dns_diff_append(&diff, &tuple);
dns_rdata_reset(&ds);
result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
dsbuf, &ds);
check_result(result, "dns_ds_buildrdata");
@ -3000,19 +2985,6 @@ writeset(const char *prefix, dns_rdatatype_t type) {
isc_buffer_usedregion(&b, &r);
dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
if (type != dns_rdatatype_dnskey) {
result = dns_ds_buildrdata(gorigin, &rdata,
DNS_DSDIGEST_SHA1,
dsbuf, &ds);
check_result(result, "dns_ds_buildrdata");
if (type == dns_rdatatype_dlv)
ds.type = dns_rdatatype_dlv;
result = dns_difftuple_create(mctx,
DNS_DIFFOP_ADDRESIGN,
name, 0, &ds, &tuple);
check_result(result, "dns_difftuple_create");
dns_diff_append(&diff, &tuple);
dns_rdata_reset(&ds);
result = dns_ds_buildrdata(gorigin, &rdata,
DNS_DSDIGEST_SHA256,
dsbuf, &ds);
@ -3023,11 +2995,12 @@ writeset(const char *prefix, dns_rdatatype_t type) {
DNS_DIFFOP_ADDRESIGN,
name, 0, &ds, &tuple);
} else
} else {
result = dns_difftuple_create(mctx,
DNS_DIFFOP_ADDRESIGN,
gorigin, zone_soa_min_ttl,
&rdata, &tuple);
}
check_result(result, "dns_difftuple_create");
dns_diff_append(&diff, &tuple);
}

View file

@ -67,7 +67,6 @@
#include "dnssectool.h"
const char *program = "dnssec-verify";
int verbose;
static isc_stdtime_t now;
static isc_mem_t *mctx = NULL;

View file

@ -57,8 +57,8 @@
#include "dnssectool.h"
extern int verbose;
extern const char *program;
int verbose;
uint8_t dtype[8];
static fatalcallback_t *fatalcallback = NULL;
@ -344,6 +344,32 @@ strtodsdigest(const char *algname) {
}
}
static int
cmp_dtype(const void *ap, const void *bp) {
int a = *(const uint8_t *)ap;
int b = *(const uint8_t *)bp;
return (a - b);
}
void
add_dtype(unsigned int dt) {
unsigned i, n;
/* ensure there is space for a zero terminator */
n = sizeof(dtype)/sizeof(dtype[0]) - 1;
for (i = 0; i < n; i++) {
if (dtype[i] == dt) {
return;
}
if (dtype[i] == 0) {
dtype[i] = dt;
qsort(dtype, i+1, 1, cmp_dtype);
return;
}
}
fatal("too many -a digest type arguments");
}
isc_result_t
try_dir(const char *dirname) {
isc_result_t result;

View file

@ -21,6 +21,25 @@
#include <dns/rdatastruct.h>
#include <dst/dst.h>
#ifndef PATH_MAX
#define PATH_MAX 1024 /* WIN32, and others don't define this. */
#endif
/*! verbosity: set by -v option in each program, defined in dnssectool.c */
extern int verbose;
/*! program name, statically initialized in each program */
extern const char *program;
/*!
* List of DS digest types used by dnssec-cds and dnssec-dsfromkey,
* defined in dnssectool.c. Filled in by add_dtype() from -a
* arguments, sorted (so that DS records are in a canonical order) and
* terminated by a zero. The size of the array is an arbitrary limit
* which should be greater than the number of known digest types.
*/
extern uint8_t dtype[8];
typedef void (fatalcallback_t)(void);
ISC_PLATFORM_NORETURN_PRE void
@ -55,11 +74,14 @@ isc_stdtime_t
strtotime(const char *str, int64_t now, int64_t base,
bool *setp);
dns_rdataclass_t
strtoclass(const char *str);
unsigned int
strtodsdigest(const char *str);
dns_rdataclass_t
strtoclass(const char *str);
void
add_dtype(unsigned int dt);
isc_result_t
try_dir(const char *dirname);

View file

@ -67,8 +67,26 @@
<refsection><info><title>OPTIONS</title></info>
<variablelist>
<varlistentry>
<term>-a <replaceable class="parameter">algorithm</replaceable></term>
<listitem>
<para>
Specify a digest algorithm to use when converting the
zone's DNSKEY records to expected DS or DLV records. This
option can be repeated, so that multiple records are
checked for each DNSKEY record.
</para>
<para>
The <replaceable>algorithm</replaceable> 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.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-f <replaceable class="parameter">file</replaceable></term>
<listitem>

View file

@ -114,19 +114,19 @@ def check(zone, args):
klist = []
cmd = [args.dsfromkey]
for algo in args.algo:
cmd += ['-a', algo]
if args.lookaside:
cmd += ["-l", args.lookaside]
if args.masterfile:
cmd = [args.dsfromkey, "-f", args.masterfile]
if args.lookaside:
cmd += ["-l", args.lookaside]
cmd.append(zone)
cmd += ["-f", args.masterfile, zone]
fp, _ = Popen(cmd, stdout=PIPE).communicate()
else:
intods, _ = Popen([args.dig, "+noall", "+answer", "-t", "dnskey",
"-q", zone], stdout=PIPE).communicate()
cmd = [args.dsfromkey, "-f", "-"]
if args.lookaside:
cmd += ["-l", args.lookaside]
cmd.append(zone)
cmd += ["-f", "-", zone]
fp, _ = Popen(cmd, stdin=PIPE, stdout=PIPE).communicate(intods)
for line in fp.splitlines():
@ -138,23 +138,27 @@ def check(zone, args):
print("No DNSKEY records found in zone apex")
return False
found = False
match = True
for rr in rrlist:
if rr not in klist:
print("KSK for %s %s/%03d/%05d (%s) missing from child" %
(rr.rrtype, rr.rrname.strip('.'), rr.keyalg,
rr.keyid, SECRR.hashalgs[rr.hashalg]))
match = False
for rr in klist:
if rr not in rrlist:
print("%s for KSK %s/%03d/%05d (%s) missing from parent" %
(rr.rrtype, rr.rrname.strip('.'), rr.keyalg,
rr.keyid, SECRR.hashalgs[rr.hashalg]))
match = False
for rr in klist:
if rr in rrlist:
print("%s for KSK %s/%03d/%05d (%s) found in parent" %
(rr.rrtype, rr.rrname.strip('.'), rr.keyalg,
rr.keyid, SECRR.hashalgs[rr.hashalg]))
found = True
else:
print("%s for KSK %s/%03d/%05d (%s) missing from parent" %
(rr.rrtype, rr.rrname.strip('.'), rr.keyalg,
rr.keyid, SECRR.hashalgs[rr.hashalg]))
if not found:
print("No %s records were found for any DNSKEY" %
("DLV" if args.lookaside else "DS"))
return match
return found
############################################################################
# parse_args:
@ -167,6 +171,8 @@ def parse_args():
sbindir = 'bin' if os.name == 'nt' else 'sbin'
parser.add_argument('zone', type=str, help='zone to check')
parser.add_argument('-a', '--algo', dest='algo', action='append',
default=[], type=str, help='DS digest algorithm')
parser.add_argument('-d', '--dig', dest='dig',
default=os.path.join(prefix(bindir), 'dig'),
type=str, help='path to \'dig\'')
@ -196,5 +202,5 @@ def parse_args():
############################################################################
def main():
args = parse_args()
found = check(args.zone, args)
exit(0 if found else 1)
match = check(args.zone, args)
exit(0 if match else 1)

View file

@ -44,7 +44,7 @@ tac() {
convert() {
key=$1
n=$2
$DSFROMKEY $key >DS.$n
$DSFROMKEY -12 $key >DS.$n
grep ' 8 1 ' DS.$n >DS.$n-1
grep ' 8 2 ' DS.$n >DS.$n-2
sed 's/ IN DS / IN CDS /' <DS.$n >>CDS.$n

View file

@ -15,10 +15,10 @@ SYSTEMTESTTOP=..
if [ "$CYGWIN" ]; then
DIG=".\dig.bat"
WINDSFROMKEY=`cygpath -w $DSFROMKEY`
CHECKDS="$CHECKDS -d $DIG -D $WINDSFROMKEY"
CHECKDS="$CHECKDS -a sha1 -a sha256 -d $DIG -D $WINDSFROMKEY"
else
DIG="./dig.sh"
CHECKDS="$CHECKDS -d $DIG -D $DSFROMKEY"
CHECKDS="$CHECKDS -a sha1 -a sha256 -d $DIG -D $DSFROMKEY"
fi
chmod +x $DIG
@ -61,7 +61,7 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
echo_i "checking for incorrect DS, lowronging up key via 'dig' ($n)"
echo_i "checking for incorrect DS, looking up key via 'dig' ($n)"
ret=0
$CHECKDS wrong.example > checkds.out.$n 2>&1 || ret=1
grep 'SHA-1' checkds.out.$n > /dev/null 2>&1 || ret=1
@ -79,7 +79,7 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
echo_i "checking for incorrect DLV, lowronging up key via 'dig' ($n)"
echo_i "checking for incorrect DLV, looking up key via 'dig' ($n)"
ret=0
$CHECKDS -l dlv.example wrong.example > checkds.out.$n 2>&1 || ret=1
grep 'SHA-1' checkds.out.$n > /dev/null 2>&1 || ret=1
@ -97,10 +97,9 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
echo_i "checking for partially missing DS, looking up key via 'dig' ($n)"
ret=0
$CHECKDS missing.example > checkds.out.$n 2>&1 || ret=1
$CHECKDS missing.example > checkds.out.$n 2>&1 && ret=1
grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
grep 'SHA-1.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
@ -111,7 +110,7 @@ status=`expr $status + $ret`
echo_i "checking for partially missing DS, obtaining key from file ($n)"
ret=0
$CHECKDS -f missing.example.dnskey.db missing.example > checkds.out.$n 2>&1 || ret=1
$CHECKDS -f missing.example.dnskey.db missing.example > checkds.out.$n 2>&1 && ret=1
grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
grep 'SHA-1.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
@ -122,7 +121,7 @@ status=`expr $status + $ret`
echo_i "checking for partially missing DLV, looking up key via 'dig' ($n)"
ret=0
$CHECKDS -l dlv.example missing.example > checkds.out.$n 2>&1 || ret=1
$CHECKDS -l dlv.example missing.example > checkds.out.$n 2>&1 && ret=1
grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
grep 'SHA-1.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
@ -133,7 +132,7 @@ status=`expr $status + $ret`
echo_i "checking for partially missing DLV, obtaining key from file ($n)"
ret=0
$CHECKDS -l dlv.example -f missing.example.dnskey.db missing.example > checkds.out.$n 2>&1 || ret=1
$CHECKDS -l dlv.example -f missing.example.dnskey.db missing.example > checkds.out.$n 2>&1 && ret=1
grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
grep 'SHA-1.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
@ -145,7 +144,8 @@ status=`expr $status + $ret`
echo_i "checking for entirely missing DS, looking up key via 'dig' ($n)"
ret=0
$CHECKDS none.example > checkds.out.$n 2>&1 && ret=1
grep 'No DS' checkds.out.$n > /dev/null 2>&1 || ret=1
grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 && ret=1
grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 && ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@ -153,7 +153,8 @@ status=`expr $status + $ret`
echo_i "checking for entirely missing DS, obtaining key from file ($n)"
ret=0
$CHECKDS -f none.example.dnskey.db none.example > checkds.out.$n 2>&1 && ret=1
grep 'No DS' checkds.out.$n > /dev/null 2>&1 || ret=1
grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 && ret=1
grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 && ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@ -161,7 +162,8 @@ status=`expr $status + $ret`
echo_i "checking for entirely missing DLV, looking up key via 'dig' ($n)"
ret=0
$CHECKDS -l dlv.example none.example > checkds.out.$n 2>&1 && ret=1
grep 'No DLV' checkds.out.$n > /dev/null 2>&1 || ret=1
grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 && ret=1
grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 && ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@ -169,7 +171,8 @@ status=`expr $status + $ret`
echo_i "checking for entirely missing DLV, obtaining key from file ($n)"
ret=0
$CHECKDS -l dlv.example -f none.example.dnskey.db none.example > checkds.out.$n 2>&1 && ret=1
grep 'No DLV' checkds.out.$n > /dev/null 2>&1 || ret=1
grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 && ret=1
grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 && ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`

View file

@ -3337,7 +3337,7 @@ echo update delete cds-update.secure CDS
echo send
dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure |
grep "DNSKEY.257" |
$DSFROMKEY -C -f - -T 1 cds-update.secure |
$DSFROMKEY -12 -C -f - -T 1 cds-update.secure |
sed "s/^/update add /"
echo send
) | $NSUPDATE
@ -3360,7 +3360,7 @@ echo update delete cds-kskonly.secure CDS
echo send
dig_with_opts +noall +answer @10.53.0.2 dnskey cds-kskonly.secure |
grep "DNSKEY.257" |
$DSFROMKEY -C -f - -T 1 cds-kskonly.secure |
$DSFROMKEY -12 -C -f - -T 1 cds-kskonly.secure |
sed "s/^/update add /"
echo send
) | $NSUPDATE
@ -3394,11 +3394,11 @@ echo update delete cds-update.secure CDS
echo send
dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure |
grep "DNSKEY.257" |
$DSFROMKEY -C -f - -T 1 cds-update.secure |
$DSFROMKEY -12 -C -f - -T 1 cds-update.secure |
sed "s/^/update add /"
dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure |
grep "DNSKEY.257" | sed 's/DNSKEY.257/DNSKEY 258/' |
$DSFROMKEY -C -A -f - -T 1 cds-update.secure |
$DSFROMKEY -12 -C -A -f - -T 1 cds-update.secure |
sed "s/^/update add /"
echo send
) | $NSUPDATE

View file

@ -470,16 +470,16 @@ n=`expr $n + 1`
echo_i "check prefetch of validated DS's RRSIG TTL is updated (${n})"
ret=0
$DIG $DIGOPTS +dnssec @10.53.0.5 ds.example.net ds > dig.out.1.${n} || ret=1
ttl1=`awk '$4 == "DS" && $7 == "1" { print $2 - 2 }' dig.out.1.${n}`
ttl1=`awk '$4 == "DS" && $7 == "2" { print $2 - 2 }' dig.out.1.${n}`
# sleep so we are in prefetch range
sleep ${ttl1:-0}
# trigger prefetch
$DIG $DIGOPTS @10.53.0.5 ds.example.net ds > dig.out.2.${n} || ret=1
ttl1=`awk '$4 == "DS" && $7 == "1" { print $2 }' dig.out.2.${n}`
ttl1=`awk '$4 == "DS" && $7 == "2" { print $2 }' dig.out.2.${n}`
sleep 1
# check that prefetch occured
$DIG $DIGOPTS @10.53.0.5 ds.example.net ds +dnssec > dig.out.3.${n} || ret=1
dsttl=`awk '$4 == "DS" && $7 == "1" { print $2 }' dig.out.3.${n}`
dsttl=`awk '$4 == "DS" && $7 == "2" { print $2 }' dig.out.3.${n}`
sigttl=`awk '$4 == "RRSIG" && $5 == "DS" { print $2 }' dig.out.3.${n}`
test ${dsttl:-0} -gt ${ttl2:-1} || ret=1
test ${sigttl:-0} -gt ${ttl2:-1} || ret=1

View file

@ -144,6 +144,21 @@
configuration error. [GL #868]
</para>
</listitem>
<listitem>
<para>
DS and CDS records are now generated with SHA-256 digests
only, instead of both SHA-1 and SHA-256. This affects the
default output of <command>dnssec-dsfromkey</command>, the
<filename>dsset</filename> files generated by
<command>dnssec-signzone</command>, the DS records added to
a zone by <command>dnssec-signzone</command> based on
<filename>keyset</filename> files, the CDS records added to
a zone by <command>named</command> and
<command>dnssec-signzone</command> based on "sync" timing
parameters in key files, and the checks performed by
<command>dnssec-checkds</command>.
</para>
</listitem>
</itemizedlist>
</section>

View file

@ -1909,8 +1909,8 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
for (key = ISC_LIST_HEAD(*keys);
key != NULL;
key = ISC_LIST_NEXT(key, link)) {
dns_rdata_t cdsrdata1 = DNS_RDATA_INIT;
dns_rdata_t cdsrdata2 = DNS_RDATA_INIT;
dns_rdata_t cds_sha1 = DNS_RDATA_INIT;
dns_rdata_t cds_sha256 = DNS_RDATA_INIT;
dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT;
dns_name_t *origin = dst_key_name(key->key);
@ -1918,69 +1918,83 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
&cdnskeyrdata));
/*
* We construct the SHA-1 version of the record so we can
* delete any old records generated by previous versions of
* BIND. We only add SHA-256 records.
*
* XXXMPA we need to be able to specify the DS algorithms
* to be used here and below with rmkeys.
*/
RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata,
DNS_DSDIGEST_SHA1, dsbuf1,
&cdsrdata1));
&cds_sha1));
RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata,
DNS_DSDIGEST_SHA256, dsbuf2,
&cdsrdata2));
&cds_sha256));
/*
* Now that the we have created the DS records convert
* the rdata to CDNSKEY and CDS for comparison.
*/
cdnskeyrdata.type = dns_rdatatype_cdnskey;
cdsrdata1.type = dns_rdatatype_cds;
cdsrdata2.type = dns_rdatatype_cds;
cds_sha1.type = dns_rdatatype_cds;
cds_sha256.type = dns_rdatatype_cds;
if (syncpublish(key->key, now)) {
if (!dns_rdataset_isassociated(cdnskey) ||
!exists(cdnskey, &cdnskeyrdata))
{
RETERR(publish(&cdnskeyrdata, diff, origin,
ttl, mctx));
}
/* Only publish SHA-256 (SHA-1 is deprecated) */
if (!dns_rdataset_isassociated(cds) ||
!exists(cds, &cdsrdata1))
RETERR(publish(&cdsrdata1, diff, origin,
ttl, mctx));
if (!dns_rdataset_isassociated(cds) ||
!exists(cds, &cdsrdata2))
RETERR(publish(&cdsrdata2, diff, origin,
!exists(cds, &cds_sha256))
{
RETERR(publish(&cds_sha256, diff, origin,
ttl, mctx));
}
}
if (dns_rdataset_isassociated(cds) &&
syncdelete(key->key, now)) {
if (exists(cds, &cdsrdata1))
RETERR(delrdata(&cdsrdata1, diff, origin,
syncdelete(key->key, now))
{
/* Delete both SHA-1 and SHA-256 */
if (exists(cds, &cds_sha1)) {
RETERR(delrdata(&cds_sha1, diff, origin,
cds->ttl, mctx));
if (exists(cds, &cdsrdata2))
RETERR(delrdata(&cdsrdata2, diff, origin,
}
if (exists(cds, &cds_sha256)) {
RETERR(delrdata(&cds_sha256, diff, origin,
cds->ttl, mctx));
}
}
if (dns_rdataset_isassociated(cdnskey) &&
syncdelete(key->key, now)) {
if (exists(cdnskey, &cdnskeyrdata))
syncdelete(key->key, now))
{
if (exists(cdnskey, &cdnskeyrdata)) {
RETERR(delrdata(&cdnskeyrdata, diff, origin,
cdnskey->ttl, mctx));
}
}
}
if (!dns_rdataset_isassociated(cds) &&
!dns_rdataset_isassociated(cdnskey))
{
return (ISC_R_SUCCESS);
}
/*
* Unconditionaly remove CDS/DNSKEY records for removed keys.
*/
for (key = ISC_LIST_HEAD(*rmkeys);
key != NULL;
key = ISC_LIST_NEXT(key, link)) {
dns_rdata_t cdsrdata1 = DNS_RDATA_INIT;
dns_rdata_t cdsrdata2 = DNS_RDATA_INIT;
key = ISC_LIST_NEXT(key, link))
{
dns_rdata_t cds_sha1 = DNS_RDATA_INIT;
dns_rdata_t cds_sha256 = DNS_RDATA_INIT;
dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT;
dns_name_t *origin = dst_key_name(key->key);
@ -1990,22 +2004,25 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
if (dns_rdataset_isassociated(cds)) {
RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata,
DNS_DSDIGEST_SHA1, dsbuf1,
&cdsrdata1));
&cds_sha1));
RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata,
DNS_DSDIGEST_SHA256, dsbuf2,
&cdsrdata2));
if (exists(cds, &cdsrdata1))
RETERR(delrdata(&cdsrdata1, diff, origin,
&cds_sha256));
if (exists(cds, &cds_sha1)) {
RETERR(delrdata(&cds_sha1, diff, origin,
cds->ttl, mctx));
if (exists(cds, &cdsrdata2))
RETERR(delrdata(&cdsrdata2, diff, origin,
}
if (exists(cds, &cds_sha256)) {
RETERR(delrdata(&cds_sha256, diff, origin,
cds->ttl, mctx));
}
}
if (dns_rdataset_isassociated(cdnskey)) {
if (exists(cdnskey, &cdnskeyrdata))
if (exists(cdnskey, &cdnskeyrdata)) {
RETERR(delrdata(&cdnskeyrdata, diff, origin,
cdnskey->ttl, mctx));
}
}
}