3341. [func] New "dnssec-verify" command checks a signed zone

to ensure correctness of signatures and of NSEC/NSEC3
                        chains. [RT #23673]
This commit is contained in:
Mark Andrews 2012-06-25 13:57:32 +10:00
parent 8811ab3ca6
commit ad127d839d
26 changed files with 2578 additions and 707 deletions

View file

@ -1,3 +1,7 @@
3341. [func] New "dnssec-verify" command checks a signed zone
to ensure correctness of signatures and of NSEC/NSEC3
chains. [RT #23673]
3340. [func] Added new 'fast' zone file format, which is an image
of a zone database that can be loaded directly into
memory via mmap(), allowing much faster zone loading.

View file

@ -6,4 +6,5 @@ dnssec-revoke
dnssec-settime
dnssec-signkey
dnssec-signzone
dnssec-verify
.libs

View file

@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: Makefile.in,v 1.42 2009/12/05 23:31:40 each Exp $
# $Id: Makefile.in,v 1.42.332.1 2011/03/16 06:37:51 each Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@ -44,19 +44,23 @@ 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-revoke@EXEEXT@ dnssec-settime@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 dnssectool.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-revoke.8 dnssec-settime.8 dnssec-signzone.8 \
dnssec-verify.8
HTMLPAGES = dnssec-dsfromkey.html dnssec-keyfromlabel.html \
dnssec-keygen.html dnssec-revoke.html \
dnssec-settime.html dnssec-signzone.html
dnssec-settime.html dnssec-signzone.html \
dnssec-verify.html
MANOBJS = ${MANPAGES} ${HTMLPAGES}
@ -82,6 +86,14 @@ dnssec-signzone@EXEEXT@: dnssec-signzone.@O@ ${OBJS} ${DEPLIBS}
export BASEOBJS="dnssec-signzone.@O@ ${OBJS}"; \
${FINALBUILDCMD}
dnssec-verify.@O@: dnssec-verify.c
${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \
-c ${srcdir}/dnssec-verify.c
dnssec-verify@EXEEXT@: dnssec-verify.@O@ ${OBJS} ${DEPLIBS}
export BASEOBJS="dnssec-verify.@O@ ${OBJS}"; \
${FINALBUILDCMD}
dnssec-revoke@EXEEXT@: dnssec-revoke.@O@ ${OBJS} ${DEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
dnssec-revoke.@O@ ${OBJS} ${LIBS}

View file

@ -189,10 +189,6 @@ static isc_boolean_t output_stdout = ISC_FALSE;
static void
sign(isc_task_t *task, isc_event_t *event);
#define check_dns_dbiterator_current(result) \
check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \
"dns_dbiterator_current()")
static void
dumpnode(dns_name_t *name, dns_dbnode_t *node) {
dns_rdataset_t rds;
@ -997,26 +993,6 @@ loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
return (result);
}
static isc_boolean_t
delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) {
dns_rdataset_t nsset;
isc_result_t result;
if (dns_name_equal(name, gorigin))
return (ISC_FALSE);
dns_rdataset_init(&nsset);
result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns,
0, 0, &nsset, NULL);
if (dns_rdataset_isassociated(&nsset)) {
if (ttlp != NULL)
*ttlp = nsset.ttl;
dns_rdataset_disassociate(&nsset);
}
return (ISC_TF(result == ISC_R_SUCCESS));
}
static isc_boolean_t
secure(dns_name_t *name, dns_dbnode_t *node) {
dns_rdataset_t dsset;
@ -1052,7 +1028,7 @@ signname(dns_dbnode_t *node, dns_name_t *name) {
/*
* Determine if this is a delegation point.
*/
if (delegation(name, node, NULL))
if (is_delegation(gdb, gversion, gorigin, name, node, NULL))
isdelegation = ISC_TRUE;
/*
@ -1385,453 +1361,6 @@ postsign(void) {
dns_dbiterator_destroy(&gdbiter);
}
static isc_boolean_t
goodsig(dns_rdata_t *sigrdata, dns_name_t *name, dns_rdataset_t *keyrdataset,
dns_rdataset_t *rdataset)
{
dns_rdata_dnskey_t key;
dns_rdata_rrsig_t sig;
dst_key_t *dstkey = NULL;
isc_result_t result;
dns_rdata_tostruct(sigrdata, &sig, NULL);
for (result = dns_rdataset_first(keyrdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(keyrdataset)) {
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_current(keyrdataset, &rdata);
dns_rdata_tostruct(&rdata, &key, NULL);
result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx,
&dstkey);
if (result != ISC_R_SUCCESS)
return (ISC_FALSE);
if (sig.algorithm != key.algorithm ||
sig.keyid != dst_key_id(dstkey) ||
!dns_name_equal(&sig.signer, gorigin)) {
dst_key_free(&dstkey);
continue;
}
result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE,
mctx, sigrdata);
dst_key_free(&dstkey);
if (result == ISC_R_SUCCESS)
return(ISC_TRUE);
}
return (ISC_FALSE);
}
static void
verifyset(dns_rdataset_t *rdataset, dns_name_t *name, dns_dbnode_t *node,
dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms,
unsigned char *bad_algorithms)
{
unsigned char set_algorithms[256];
char namebuf[DNS_NAME_FORMATSIZE];
char algbuf[80];
char typebuf[80];
dns_rdataset_t sigrdataset;
dns_rdatasetiter_t *rdsiter = NULL;
isc_result_t result;
int i;
dns_rdataset_init(&sigrdataset);
result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
check_result(result, "dns_db_allrdatasets()");
for (result = dns_rdatasetiter_first(rdsiter);
result == ISC_R_SUCCESS;
result = dns_rdatasetiter_next(rdsiter)) {
dns_rdatasetiter_current(rdsiter, &sigrdataset);
if (sigrdataset.type == dns_rdatatype_rrsig &&
sigrdataset.covers == rdataset->type)
break;
dns_rdataset_disassociate(&sigrdataset);
}
if (result != ISC_R_SUCCESS) {
dns_name_format(name, namebuf, sizeof(namebuf));
type_format(rdataset->type, typebuf, sizeof(typebuf));
fprintf(stderr, "no signatures for %s/%s\n", namebuf, typebuf);
for (i = 0; i < 256; i++)
if (ksk_algorithms[i] != 0)
bad_algorithms[i] = 1;
return;
}
memset(set_algorithms, 0, sizeof(set_algorithms));
for (result = dns_rdataset_first(&sigrdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&sigrdataset)) {
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_rrsig_t sig;
dns_rdataset_current(&sigrdataset, &rdata);
dns_rdata_tostruct(&rdata, &sig, NULL);
if (rdataset->ttl != sig.originalttl) {
dns_name_format(name, namebuf, sizeof(namebuf));
type_format(rdataset->type, typebuf, sizeof(typebuf));
fprintf(stderr, "TTL mismatch for %s %s keytag %u\n",
namebuf, typebuf, sig.keyid);
continue;
}
if ((set_algorithms[sig.algorithm] != 0) ||
(ksk_algorithms[sig.algorithm] == 0))
continue;
if (goodsig(&rdata, name, keyrdataset, rdataset))
set_algorithms[sig.algorithm] = 1;
}
dns_rdatasetiter_destroy(&rdsiter);
if (memcmp(set_algorithms, ksk_algorithms, sizeof(set_algorithms))) {
dns_name_format(name, namebuf, sizeof(namebuf));
type_format(rdataset->type, typebuf, sizeof(typebuf));
for (i = 0; i < 256; i++)
if ((ksk_algorithms[i] != 0) &&
(set_algorithms[i] == 0)) {
dns_secalg_format(i, algbuf, sizeof(algbuf));
fprintf(stderr, "Missing %s signature for "
"%s %s\n", algbuf, namebuf, typebuf);
bad_algorithms[i] = 1;
}
}
dns_rdataset_disassociate(&sigrdataset);
}
static void
verifynode(dns_name_t *name, dns_dbnode_t *node, isc_boolean_t delegation,
dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms,
unsigned char *bad_algorithms)
{
dns_rdataset_t rdataset;
dns_rdatasetiter_t *rdsiter = NULL;
isc_result_t result;
result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
check_result(result, "dns_db_allrdatasets()");
result = dns_rdatasetiter_first(rdsiter);
dns_rdataset_init(&rdataset);
while (result == ISC_R_SUCCESS) {
dns_rdatasetiter_current(rdsiter, &rdataset);
if (rdataset.type != dns_rdatatype_rrsig &&
rdataset.type != dns_rdatatype_dnskey &&
(!delegation || rdataset.type == dns_rdatatype_ds ||
rdataset.type == dns_rdatatype_nsec)) {
verifyset(&rdataset, name, node, keyrdataset,
ksk_algorithms, bad_algorithms);
}
dns_rdataset_disassociate(&rdataset);
result = dns_rdatasetiter_next(rdsiter);
}
if (result != ISC_R_NOMORE)
fatal("rdataset iteration failed: %s",
isc_result_totext(result));
dns_rdatasetiter_destroy(&rdsiter);
}
/*%
* Verify that certain things are sane:
*
* The apex has a DNSKEY RRset with at least one KSK, and at least
* one ZSK if the -x flag was not used.
*
* The DNSKEY record was signed with at least one of the KSKs in
* the DNSKEY RRset.
*
* The rest of the zone was signed with at least one of the ZSKs
* present in the DNSKEY RRset.
*/
static void
verifyzone(void) {
char algbuf[80];
dns_dbiterator_t *dbiter = NULL;
dns_dbnode_t *node = NULL, *nextnode = NULL;
dns_fixedname_t fname, fnextname, fzonecut;
dns_name_t *name, *nextname, *zonecut;
dns_rdata_dnskey_t dnskey;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_t keyset, soaset;
dns_rdataset_t keysigs, soasigs;
int i;
isc_boolean_t done = ISC_FALSE;
isc_boolean_t first = ISC_TRUE;
isc_boolean_t goodksk = ISC_FALSE;
isc_result_t result;
unsigned char revoked_ksk[256];
unsigned char revoked_zsk[256];
unsigned char standby_ksk[256];
unsigned char standby_zsk[256];
unsigned char ksk_algorithms[256];
unsigned char zsk_algorithms[256];
unsigned char bad_algorithms[256];
if (disable_zone_check)
return;
result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
if (result != ISC_R_SUCCESS)
fatal("failed to find the zone's origin: %s",
isc_result_totext(result));
dns_rdataset_init(&keyset);
dns_rdataset_init(&keysigs);
dns_rdataset_init(&soaset);
dns_rdataset_init(&soasigs);
result = dns_db_findrdataset(gdb, node, gversion,
dns_rdatatype_dnskey,
0, 0, &keyset, &keysigs);
if (result != ISC_R_SUCCESS)
fatal("Zone contains no DNSSEC keys\n");
result = dns_db_findrdataset(gdb, node, gversion,
dns_rdatatype_soa,
0, 0, &soaset, &soasigs);
dns_db_detachnode(gdb, &node);
if (result != ISC_R_SUCCESS)
fatal("Zone contains no SOA record\n");
if (!dns_rdataset_isassociated(&keysigs))
fatal("DNSKEY is not signed (keys offline or inactive?)\n");
if (!dns_rdataset_isassociated(&soasigs))
fatal("SOA is not signed (keys offline or inactive?)\n");
memset(revoked_ksk, 0, sizeof(revoked_ksk));
memset(revoked_zsk, 0, sizeof(revoked_zsk));
memset(standby_ksk, 0, sizeof(standby_ksk));
memset(standby_zsk, 0, sizeof(standby_zsk));
memset(ksk_algorithms, 0, sizeof(ksk_algorithms));
memset(zsk_algorithms, 0, sizeof(zsk_algorithms));
memset(bad_algorithms, 0, sizeof(bad_algorithms));
/*
* Check that the DNSKEY RR has at least one self signing KSK
* and one ZSK per algorithm in it (or, if -x was used, one
* self-signing KSK).
*/
for (result = dns_rdataset_first(&keyset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&keyset)) {
dns_rdataset_current(&keyset, &rdata);
result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
check_result(result, "dns_rdata_tostruct");
if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0)
;
else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) {
if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
!dns_dnssec_selfsigns(&rdata, gorigin, &keyset,
&keysigs, ISC_FALSE,
mctx)) {
char namebuf[DNS_NAME_FORMATSIZE];
char buffer[1024];
isc_buffer_t buf;
dns_name_format(gorigin, namebuf,
sizeof(namebuf));
isc_buffer_init(&buf, buffer, sizeof(buffer));
result = dns_rdata_totext(&rdata, NULL, &buf);
check_result(result, "dns_rdata_totext");
fatal("revoked KSK is not self signed:\n"
"%s DNSKEY %.*s", namebuf,
(int)isc_buffer_usedlength(&buf), buffer);
}
if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
revoked_ksk[dnskey.algorithm] != 255)
revoked_ksk[dnskey.algorithm]++;
else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 &&
revoked_zsk[dnskey.algorithm] != 255)
revoked_zsk[dnskey.algorithm]++;
} else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) {
if (dns_dnssec_selfsigns(&rdata, gorigin, &keyset,
&keysigs, ISC_FALSE, mctx)) {
if (ksk_algorithms[dnskey.algorithm] != 255)
ksk_algorithms[dnskey.algorithm]++;
goodksk = ISC_TRUE;
} else {
if (standby_ksk[dnskey.algorithm] != 255)
standby_ksk[dnskey.algorithm]++;
}
} else if (dns_dnssec_selfsigns(&rdata, gorigin, &keyset,
&keysigs, ISC_FALSE,
mctx)) {
if (zsk_algorithms[dnskey.algorithm] != 255)
zsk_algorithms[dnskey.algorithm]++;
} else if (dns_dnssec_signs(&rdata, gorigin, &soaset,
&soasigs, ISC_FALSE, mctx)) {
if (zsk_algorithms[dnskey.algorithm] != 255)
zsk_algorithms[dnskey.algorithm]++;
} else {
if (standby_zsk[dnskey.algorithm] != 255)
standby_zsk[dnskey.algorithm]++;
}
dns_rdata_freestruct(&dnskey);
dns_rdata_reset(&rdata);
}
dns_rdataset_disassociate(&keysigs);
dns_rdataset_disassociate(&soaset);
dns_rdataset_disassociate(&soasigs);
if (!goodksk)
fatal("No self-signed KSK DNSKEY found. Supply an active\n"
"key with the KSK flag set, or use '-P'.");
fprintf(stderr, "Verifying the zone using the following algorithms:");
for (i = 0; i < 256; i++) {
if (ksk_algorithms[i] != 0) {
dns_secalg_format(i, algbuf, sizeof(algbuf));
fprintf(stderr, " %s", algbuf);
}
}
fprintf(stderr, ".\n");
if (!ignore_kskflag && !keyset_kskonly) {
for (i = 0; i < 256; i++) {
/*
* The counts should both be zero or both be non-zero.
* Mark the algorithm as bad if this is not met.
*/
if ((ksk_algorithms[i] != 0) ==
(zsk_algorithms[i] != 0))
continue;
dns_secalg_format(i, algbuf, sizeof(algbuf));
fprintf(stderr, "Missing %s for algorithm %s\n",
(ksk_algorithms[i] != 0)
? "ZSK"
: "self signing KSK",
algbuf);
bad_algorithms[i] = 1;
}
}
/*
* Check that all the other records were signed by keys that are
* present in the DNSKEY RRSET.
*/
dns_fixedname_init(&fname);
name = dns_fixedname_name(&fname);
dns_fixedname_init(&fnextname);
nextname = dns_fixedname_name(&fnextname);
dns_fixedname_init(&fzonecut);
zonecut = NULL;
result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
check_result(result, "dns_db_createiterator()");
result = dns_dbiterator_first(dbiter);
check_result(result, "dns_dbiterator_first()");
while (!done) {
isc_boolean_t isdelegation = ISC_FALSE;
result = dns_dbiterator_current(dbiter, &node, name);
check_dns_dbiterator_current(result);
if (!dns_name_issubdomain(name, gorigin)) {
dns_db_detachnode(gdb, &node);
result = dns_dbiterator_next(dbiter);
if (result == ISC_R_NOMORE)
done = ISC_TRUE;
else
check_result(result, "dns_dbiterator_next()");
continue;
}
if (delegation(name, node, NULL)) {
zonecut = dns_fixedname_name(&fzonecut);
dns_name_copy(name, zonecut, NULL);
isdelegation = ISC_TRUE;
}
verifynode(name, node, isdelegation, &keyset,
ksk_algorithms, bad_algorithms);
result = dns_dbiterator_next(dbiter);
nextnode = NULL;
while (result == ISC_R_SUCCESS) {
result = dns_dbiterator_current(dbiter, &nextnode,
nextname);
check_dns_dbiterator_current(result);
if (!dns_name_issubdomain(nextname, gorigin) ||
(zonecut != NULL &&
dns_name_issubdomain(nextname, zonecut)))
{
dns_db_detachnode(gdb, &nextnode);
result = dns_dbiterator_next(dbiter);
continue;
}
dns_db_detachnode(gdb, &nextnode);
break;
}
if (result == ISC_R_NOMORE) {
done = ISC_TRUE;
} else if (result != ISC_R_SUCCESS)
fatal("iterating through the database failed: %s",
isc_result_totext(result));
dns_db_detachnode(gdb, &node);
}
dns_dbiterator_destroy(&dbiter);
result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
check_result(result, "dns_db_createiterator()");
for (result = dns_dbiterator_first(dbiter);
result == ISC_R_SUCCESS;
result = dns_dbiterator_next(dbiter) ) {
result = dns_dbiterator_current(dbiter, &node, name);
check_dns_dbiterator_current(result);
verifynode(name, node, ISC_FALSE, &keyset,
ksk_algorithms, bad_algorithms);
dns_db_detachnode(gdb, &node);
}
dns_dbiterator_destroy(&dbiter);
dns_rdataset_disassociate(&keyset);
/*
* If we made it this far, we have what we consider a properly signed
* zone. Set the good flag.
*/
for (i = 0; i < 256; i++) {
if (bad_algorithms[i] != 0) {
if (first)
fprintf(stderr, "The zone is not fully signed "
"for the following algorithms:");
dns_secalg_format(i, algbuf, sizeof(algbuf));
fprintf(stderr, " %s", algbuf);
first = ISC_FALSE;
}
}
if (!first) {
fprintf(stderr, ".\n");
fatal("DNSSEC completeness test failed.");
}
if (goodksk || ignore_kskflag) {
/*
* Print the success summary.
*/
fprintf(stderr, "Zone signing complete:\n");
for (i = 0; i < 256; i++) {
if ((ksk_algorithms[i] != 0) ||
(standby_ksk[i] != 0) ||
(revoked_zsk[i] != 0) ||
(zsk_algorithms[i] != 0) ||
(standby_zsk[i] != 0) ||
(revoked_zsk[i] != 0)) {
dns_secalg_format(i, algbuf, sizeof(algbuf));
fprintf(stderr, "Algorithm: %s: KSKs: "
"%u active, %u stand-by, %u revoked\n",
algbuf, ksk_algorithms[i],
standby_ksk[i], revoked_ksk[i]);
fprintf(stderr, "%*sZSKs: "
"%u active, %u %s, %u revoked\n",
(int) strlen(algbuf) + 13, "",
zsk_algorithms[i],
standby_zsk[i],
keyset_kskonly ? "present" : "stand-by",
revoked_zsk[i]);
}
}
}
}
/*%
* Sign the apex of the zone.
* Note the origin may not be the first node if there are out of zone
@ -1929,7 +1458,7 @@ assignwork(isc_task_t *task, isc_task_t *worker) {
if (dns_name_issubdomain(name, gorigin) &&
(zonecut == NULL ||
!dns_name_issubdomain(name, zonecut))) {
if (delegation(name, node, NULL)) {
if (is_delegation(gdb, gversion, gorigin, name, node, NULL)) {
dns_fixedname_init(&fzonecut);
zonecut = dns_fixedname_name(&fzonecut);
dns_name_copy(name, zonecut, NULL);
@ -2187,7 +1716,7 @@ nsecify(void) {
if (dns_name_equal(name, gorigin))
remove_records(node, dns_rdatatype_nsec3param);
if (delegation(name, node, &nsttl)) {
if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) {
zonecut = dns_fixedname_name(&fzonecut);
dns_name_copy(name, zonecut, NULL);
if (generateds)
@ -2622,7 +2151,9 @@ nsec3ify(unsigned int hashalg, unsigned int iterations,
result = dns_dbiterator_next(dbiter);
continue;
}
if (delegation(nextname, nextnode, &nsttl)) {
if (is_delegation(gdb, gversion, gorigin,
nextname, nextnode, &nsttl))
{
zonecut = dns_fixedname_name(&fzonecut);
dns_name_copy(nextname, zonecut, NULL);
if (generateds)
@ -2750,7 +2281,9 @@ nsec3ify(unsigned int hashalg, unsigned int iterations,
result = dns_dbiterator_next(dbiter);
continue;
}
if (delegation(nextname, nextnode, NULL)) {
if (is_delegation(gdb, gversion, gorigin,
nextname, nextnode, NULL))
{
zonecut = dns_fixedname_name(&fzonecut);
dns_name_copy(nextname, zonecut, NULL);
if (OPTOUT(nsec3flags) &&
@ -3469,9 +3002,10 @@ main(int argc, char *argv[]) {
isc_boolean_t set_salt = ISC_FALSE;
isc_boolean_t set_optout = ISC_FALSE;
isc_boolean_t set_iter = ISC_FALSE;
isc_boolean_t nonsecify = ISC_FALSE;
#define CMDLINE_FLAGS \
"3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:n:N:o:O:PpRr:s:ST:tuUv:X:xz"
"3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:n:N:o:O:PpRr:s:ST:tuUv:X:xzZ:"
/*
* Process memory debugging argument first.
@ -3741,6 +3275,10 @@ main(int argc, char *argv[]) {
fprintf(stderr, "%s: unhandled option -%c\n",
program, isc_commandline_option);
exit(1);
case 'Z': /* Undocumented test options */
if (!strcmp(isc_commandline_argument, "nonsecify"))
nonsecify = ISC_TRUE;
break;
}
}
@ -3995,11 +3533,13 @@ main(int argc, char *argv[]) {
remove_duplicates();
if (IS_NSEC3)
nsec3ify(dns_hash_sha1, nsec3iter, salt, salt_length,
&hashlist);
else
nsecify();
if (!nonsecify) {
if (IS_NSEC3)
nsec3ify(dns_hash_sha1, nsec3iter, salt, salt_length,
&hashlist);
else
nsecify();
}
if (!nokeys) {
writeset("dsset-", dns_rdatatype_ds);
@ -4086,9 +3626,12 @@ main(int argc, char *argv[]) {
isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
postsign();
TIME_NOW(&sign_finish);
verifyzone();
if (outputformat == dns_masterformat_raw) {
if (!disable_zone_check)
verifyzone(gdb, gversion, gorigin, mctx,
ignore_kskflag, keyset_kskonly);
if (outputformat != dns_masterformat_text) {
dns_masterrawheader_t header;
dns_master_initrawheader(&header);
if (rawversion == 0U)

View file

@ -0,0 +1,97 @@
.\" 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.
.\"
.\" $Id$
.\"
.hy 0
.ad l
.\" Title: dnssec\-verify
.\" Author:
.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
.\" Date: April 12, 2012
.\" Manual: BIND9
.\" Source: BIND9
.\"
.TH "DNSSEC\-VERIFY" "8" "April 12, 2012" "BIND9" "BIND9"
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.SH "NAME"
dnssec\-verify \- DNSSEC zone verification tool
.SH "SYNOPSIS"
.HP 14
\fBdnssec\-verify\fR [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-I\ \fR\fB\fIinput\-format\fR\fR] [\fB\-o\ \fR\fB\fIorigin\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-x\fR] [\fB\-z\fR] {zonefile}
.SH "DESCRIPTION"
.PP
\fBdnssec\-verify\fR
verifies that a zone is fully signed for each algorithm found in the DNSKEY RRset for the zone, and that the NSEC / NSEC3 chains are complete.
.SH "OPTIONS"
.PP
\-c \fIclass\fR
.RS 4
Specifies the DNS class of the zone.
.RE
.PP
\-I \fIinput\-format\fR
.RS 4
The format of the input zone file. Possible formats are
\fB"text"\fR
(default) and
\fB"raw"\fR. This option is primarily intended to be used for dynamic signed zones so that the dumped zone file in a non\-text format containing updates can be verified independently. The use of this option does not make much sense for non\-dynamic zones.
.RE
.PP
\-o \fIorigin\fR
.RS 4
The zone origin. If not specified, the name of the zone file is assumed to be the origin.
.RE
.PP
\-v \fIlevel\fR
.RS 4
Sets the debugging level.
.RE
.PP
\-x
.RS 4
Only verify that the DNSKEY RRset is signed with key\-signing keys. Without this flag, it is assumed that the DNSKEY RRset will be signed by all active keys. When this flag is set, it will not be an error if the DNSKEY RRset is not signed by zone\-signing keys. This corresponds to the
\fB\-x\fR
option in
\fBdnssec\-signzone\fR.
.RE
.PP
\-z
.RS 4
Ignore the KSK flag on the keys when determining whether the zone if correctly signed. Without this flag it is assumed that there will be a non\-revoked, self\-signed DNSKEY with the KSK flag set for each algorithm and that RRsets other than DNSKEY RRset will be signed with a different DNSKEY without the KSK flag set.
.sp
With this flag set, we only require that for each algorithm, there will be at least one non\-revoked, self\-signed DNSKEY, regardless of the KSK flag state, and that other RRsets will be signed by a non\-revoked key for the same algorithm that includes the self\-signed key; the same key may be used for both purposes. This corresponds to the
\fB\-z\fR
option in
\fBdnssec\-signzone\fR.
.RE
.PP
zonefile
.RS 4
The file containing the zone to be signed.
.RE
.SH "SEE ALSO"
.PP
\fBdnssec\-signzone\fR(8),
BIND 9 Administrator Reference Manual,
RFC 4033.
.SH "AUTHOR"
.PP
Internet Systems Consortium
.SH "COPYRIGHT"
Copyright \(co 2012 Internet Systems Consortium, Inc. ("ISC")
.br

325
bin/dnssec/dnssec-verify.c Normal file
View file

@ -0,0 +1,325 @@
/*
* Copyright (C) 2011 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 AND NETWORK ASSOCIATES 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.
*/
/* $Id: dnssec-verify.c,v 1.1.2.1 2011/03/16 06:37:51 each Exp $ */
/*! \file */
#include <config.h>
#include <stdlib.h>
#include <time.h>
#include <isc/app.h>
#include <isc/base32.h>
#include <isc/commandline.h>
#include <isc/entropy.h>
#include <isc/event.h>
#include <isc/file.h>
#include <isc/hash.h>
#include <isc/hex.h>
#include <isc/mem.h>
#include <isc/mutex.h>
#include <isc/os.h>
#include <isc/print.h>
#include <isc/random.h>
#include <isc/rwlock.h>
#include <isc/serial.h>
#include <isc/stdio.h>
#include <isc/stdlib.h>
#include <isc/string.h>
#include <isc/time.h>
#include <isc/util.h>
#include <dns/db.h>
#include <dns/dbiterator.h>
#include <dns/diff.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/masterdump.h>
#include <dns/nsec.h>
#include <dns/nsec3.h>
#include <dns/rdata.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
#include <dns/rdataclass.h>
#include <dns/rdatasetiter.h>
#include <dns/rdatastruct.h>
#include <dns/rdatatype.h>
#include <dns/result.h>
#include <dns/soa.h>
#include <dns/time.h>
#include <dst/dst.h>
#include "dnssectool.h"
const char *program = "dnssec-verify";
int verbose;
static isc_stdtime_t now;
static isc_mem_t *mctx = NULL;
static isc_entropy_t *ectx = NULL;
static dns_masterformat_t inputformat = dns_masterformat_text;
static dns_db_t *gdb; /* The database */
static dns_dbversion_t *gversion; /* The database version */
static dns_rdataclass_t gclass; /* The class */
static dns_name_t *gorigin; /* The database origin */
static isc_boolean_t ignore_kskflag = ISC_FALSE;
static isc_boolean_t keyset_kskonly = ISC_FALSE;
/*%
* Load the zone file from disk
*/
static void
loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
isc_buffer_t b;
int len;
dns_fixedname_t fname;
dns_name_t *name;
isc_result_t result;
len = strlen(origin);
isc_buffer_init(&b, origin, len);
isc_buffer_add(&b, len);
dns_fixedname_init(&fname);
name = dns_fixedname_name(&fname);
result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS)
fatal("failed converting name '%s' to dns format: %s",
origin, isc_result_totext(result));
result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
rdclass, 0, NULL, db);
check_result(result, "dns_db_create()");
result = dns_db_load2(*db, file, inputformat);
if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
fatal("failed loading zone from '%s': %s",
file, isc_result_totext(result));
}
ISC_PLATFORM_NORETURN_PRE static void
usage(void) ISC_PLATFORM_NORETURN_POST;
static void
usage(void) {
fprintf(stderr, "Usage:\n");
fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
fprintf(stderr, "\n");
fprintf(stderr, "Version: %s\n", VERSION);
fprintf(stderr, "Options: (default value in parenthesis) \n");
fprintf(stderr, "\t-v debuglevel (0)\n");
fprintf(stderr, "\t-o origin:\n");
fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
fprintf(stderr, "\t-I format:\n");
fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
fprintf(stderr, "\t-c class (IN)\n");
fprintf(stderr, "\t-E engine:\n");
#ifdef USE_PKCS11
fprintf(stderr, "\t\tname of an OpenSSL engine to use "
"(default is \"pkcs11\")\n");
#else
fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
#endif
fprintf(stderr, "\t-x:\tDNSKEY record signed with KSKs only, "
"not ZSKs\n");
fprintf(stderr, "\t-z:\tAll records signed with KSKs\n");
exit(0);
}
int
main(int argc, char *argv[]) {
char *origin = NULL, *file = NULL;
char *inputformatstr = NULL;
isc_result_t result;
isc_log_t *log = NULL;
#ifdef USE_PKCS11
const char *engine = "pkcs11";
#else
const char *engine = NULL;
#endif
char *classname = NULL;
dns_rdataclass_t rdclass;
char ch, *endp;
#define CMDLINE_FLAGS \
"m:o:I:c:E:v:xz"
/*
* Process memory debugging argument first.
*/
while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
switch (ch) {
case 'm':
if (strcasecmp(isc_commandline_argument, "record") == 0)
isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
if (strcasecmp(isc_commandline_argument, "trace") == 0)
isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
if (strcasecmp(isc_commandline_argument, "usage") == 0)
isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
if (strcasecmp(isc_commandline_argument, "size") == 0)
isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
if (strcasecmp(isc_commandline_argument, "mctx") == 0)
isc_mem_debugging |= ISC_MEM_DEBUGCTX;
break;
default:
break;
}
}
isc_commandline_reset = ISC_TRUE;
check_result(isc_app_start(), "isc_app_start");
result = isc_mem_create(0, 0, &mctx);
if (result != ISC_R_SUCCESS)
fatal("out of memory");
dns_result_register();
isc_commandline_errprint = ISC_FALSE;
while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
switch (ch) {
case 'c':
classname = isc_commandline_argument;
break;
case 'E':
engine = isc_commandline_argument;
break;
case 'h':
usage();
break;
case 'I':
inputformatstr = isc_commandline_argument;
break;
case 'm':
break;
case 'o':
origin = isc_commandline_argument;
break;
case 'v':
endp = NULL;
verbose = strtol(isc_commandline_argument, &endp, 0);
if (*endp != '\0')
fatal("verbose level must be numeric");
break;
case 'x':
keyset_kskonly = ISC_TRUE;
break;
case 'z':
ignore_kskflag = ISC_TRUE;
break;
case '?':
if (isc_commandline_option != '?')
fprintf(stderr, "%s: invalid argument -%c\n",
program, isc_commandline_option);
usage();
break;
default:
fprintf(stderr, "%s: unhandled option -%c\n",
program, isc_commandline_option);
exit(1);
}
}
if (ectx == NULL)
setup_entropy(mctx, NULL, &ectx);
result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (result != ISC_R_SUCCESS)
fatal("could not create hash context");
result = dst_lib_init2(mctx, ectx, engine, ISC_ENTROPY_BLOCKING);
if (result != ISC_R_SUCCESS)
fatal("could not initialize dst: %s",
isc_result_totext(result));
isc_stdtime_get(&now);
rdclass = strtoclass(classname);
setup_logging(verbose, mctx, &log);
argc -= isc_commandline_index;
argv += isc_commandline_index;
if (argc < 1)
usage();
file = argv[0];
argc -= 1;
argv += 1;
if (origin == NULL)
origin = file;
if (inputformatstr != NULL) {
if (strcasecmp(inputformatstr, "text") == 0)
inputformat = dns_masterformat_text;
else if (strcasecmp(inputformatstr, "raw") == 0)
inputformat = dns_masterformat_raw;
else
fatal("unknown file format: %s\n", inputformatstr);
}
gdb = NULL;
fprintf(stderr, "Loading zone '%s' from file '%s'\n", origin, file);
loadzone(file, origin, rdclass, &gdb);
gorigin = dns_db_origin(gdb);
gclass = dns_db_class(gdb);
gversion = NULL;
result = dns_db_newversion(gdb, &gversion);
check_result(result, "dns_db_newversion()");
verifyzone(gdb, gversion, gorigin, mctx,
ignore_kskflag, keyset_kskonly);
dns_db_closeversion(gdb, &gversion, ISC_FALSE);
dns_db_detach(&gdb);
cleanup_logging(&log);
dst_lib_destroy();
isc_hash_destroy();
cleanup_entropy(&ectx);
dns_name_destroy();
if (verbose > 10)
isc_mem_stats(mctx, stdout);
isc_mem_destroy(&mctx);
(void) isc_app_finish();
return (0);
}

View file

@ -0,0 +1,186 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
[<!ENTITY mdash "&#8212;">]>
<!--
- Copyright (C) 2004-2009, 2011 Internet Systems Consortium, Inc. ("ISC")
- Copyright (C) 2000-2003 Internet Software Consortium.
-
- 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.
-->
<!-- $Id: dnssec-verify.docbook,v 1.52 2011/12/22 07:32:40 each Exp $ -->
<refentry id="man.dnssec-verify">
<refentryinfo>
<date>April 12, 2012</date>
</refentryinfo>
<refmeta>
<refentrytitle><application>dnssec-verify</application></refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo>BIND9</refmiscinfo>
</refmeta>
<refnamediv>
<refname><application>dnssec-verify</application></refname>
<refpurpose>DNSSEC zone verification tool</refpurpose>
</refnamediv>
<docinfo>
<copyright>
<year>2012</year>
<holder>Internet Systems Consortium, Inc. ("ISC")</holder>
</copyright>
</docinfo>
<refsynopsisdiv>
<cmdsynopsis>
<command>dnssec-verify</command>
<arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
<arg><option>-E <replaceable class="parameter">engine</replaceable></option></arg>
<arg><option>-I <replaceable class="parameter">input-format</replaceable></option></arg>
<arg><option>-o <replaceable class="parameter">origin</replaceable></option></arg>
<arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
<arg><option>-x</option></arg>
<arg><option>-z</option></arg>
<arg choice="req">zonefile</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para><command>dnssec-verify</command>
verifies that a zone is fully signed for each algorithm found
in the DNSKEY RRset for the zone, and that the NSEC / NSEC3
chains are complete.
</para>
</refsect1>
<refsect1>
<title>OPTIONS</title>
<variablelist>
<varlistentry>
<term>-c <replaceable class="parameter">class</replaceable></term>
<listitem>
<para>
Specifies the DNS class of the zone.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-I <replaceable class="parameter">input-format</replaceable></term>
<listitem>
<para>
The format of the input zone file.
Possible formats are <command>"text"</command> (default)
and <command>"raw"</command>.
This option is primarily intended to be used for dynamic
signed zones so that the dumped zone file in a non-text
format containing updates can be verified independently.
The use of this option does not make much sense for
non-dynamic zones.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-o <replaceable class="parameter">origin</replaceable></term>
<listitem>
<para>
The zone origin. If not specified, the name of the zone file
is assumed to be the origin.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-v <replaceable class="parameter">level</replaceable></term>
<listitem>
<para>
Sets the debugging level.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-x</term>
<listitem>
<para>
Only verify that the DNSKEY RRset is signed with key-signing
keys. Without this flag, it is assumed that the DNSKEY RRset
will be signed by all active keys. When this flag is set,
it will not be an error if the DNSKEY RRset is not signed
by zone-signing keys. This corresponds to the <option>-x</option>
option in <command>dnssec-signzone</command>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-z</term>
<listitem>
<para>
Ignore the KSK flag on the keys when determining whether
the zone if correctly signed. Without this flag it is
assumed that there will be a non-revoked, self-signed
DNSKEY with the KSK flag set for each algorithm and
that RRsets other than DNSKEY RRset will be signed with
a different DNSKEY without the KSK flag set.
</para>
<para>
With this flag set, we only require that for each algorithm,
there will be at least one non-revoked, self-signed DNSKEY,
regardless of the KSK flag state, and that other RRsets
will be signed by a non-revoked key for the same algorithm
that includes the self-signed key; the same key may be used
for both purposes. This corresponds to the <option>-z</option>
option in <command>dnssec-signzone</command>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>zonefile</term>
<listitem>
<para>
The file containing the zone to be signed.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>SEE ALSO</title>
<para>
<citerefentry>
<refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
</citerefentry>,
<citetitle>BIND 9 Administrator Reference Manual</citetitle>,
<citetitle>RFC 4033</citetitle>.
</para>
</refsect1>
<refsect1>
<title>AUTHOR</title>
<para><corpauthor>Internet Systems Consortium</corpauthor>
</para>
</refsect1>
</refentry><!--
- Local variables:
- mode: sgml
- End:
-->

View file

@ -0,0 +1,117 @@
<!--
- 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.
-->
<!-- $Id$ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>dnssec-verify</title>
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
<a name="man.dnssec-verify"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p><span class="application">dnssec-verify</span> &#8212; DNSSEC zone verification tool</p>
</div>
<div class="refsynopsisdiv">
<h2>Synopsis</h2>
<div class="cmdsynopsis"><p><code class="command">dnssec-verify</code> [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-E <em class="replaceable"><code>engine</code></em></code>] [<code class="option">-I <em class="replaceable"><code>input-format</code></em></code>] [<code class="option">-o <em class="replaceable"><code>origin</code></em></code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-x</code>] [<code class="option">-z</code>] {zonefile}</p></div>
</div>
<div class="refsect1" lang="en">
<a name="id2543390"></a><h2>DESCRIPTION</h2>
<p><span><strong class="command">dnssec-verify</strong></span>
verifies that a zone is fully signed for each algorithm found
in the DNSKEY RRset for the zone, and that the NSEC / NSEC3
chains are complete.
</p>
</div>
<div class="refsect1" lang="en">
<a name="id2543402"></a><h2>OPTIONS</h2>
<div class="variablelist"><dl>
<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
<dd><p>
Specifies the DNS class of the zone.
</p></dd>
<dt><span class="term">-I <em class="replaceable"><code>input-format</code></em></span></dt>
<dd><p>
The format of the input zone file.
Possible formats are <span><strong class="command">"text"</strong></span> (default)
and <span><strong class="command">"raw"</strong></span>.
This option is primarily intended to be used for dynamic
signed zones so that the dumped zone file in a non-text
format containing updates can be verified independently.
The use of this option does not make much sense for
non-dynamic zones.
</p></dd>
<dt><span class="term">-o <em class="replaceable"><code>origin</code></em></span></dt>
<dd><p>
The zone origin. If not specified, the name of the zone file
is assumed to be the origin.
</p></dd>
<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
<dd><p>
Sets the debugging level.
</p></dd>
<dt><span class="term">-x</span></dt>
<dd><p>
Only verify that the DNSKEY RRset is signed with key-signing
keys. Without this flag, it is assumed that the DNSKEY RRset
will be signed by all active keys. When this flag is set,
it will not be an error if the DNSKEY RRset is not signed
by zone-signing keys. This corresponds to the <code class="option">-x</code>
option in <span><strong class="command">dnssec-signzone</strong></span>.
</p></dd>
<dt><span class="term">-z</span></dt>
<dd>
<p>
Ignore the KSK flag on the keys when determining whether
the zone if correctly signed. Without this flag it is
assumed that there will be a non-revoked, self-signed
DNSKEY with the KSK flag set for each algorithm and
that RRsets other than DNSKEY RRset will be signed with
a different DNSKEY without the KSK flag set.
</p>
<p>
With this flag set, we only require that for each algorithm,
there will be at least one non-revoked, self-signed DNSKEY,
regardless of the KSK flag state, and that other RRsets
will be signed by a non-revoked key for the same algorithm
that includes the self-signed key; the same key may be used
for both purposes. This corresponds to the <code class="option">-z</code>
option in <span><strong class="command">dnssec-signzone</strong></span>.
</p>
</dd>
<dt><span class="term">zonefile</span></dt>
<dd><p>
The file containing the zone to be signed.
</p></dd>
</dl></div>
</div>
<div class="refsect1" lang="en">
<a name="id2543543"></a><h2>SEE ALSO</h2>
<p>
<span class="citerefentry"><span class="refentrytitle">dnssec-signzone</span>(8)</span>,
<em class="citetitle">BIND 9 Administrator Reference Manual</em>,
<em class="citetitle">RFC 4033</em>.
</p>
</div>
<div class="refsect1" lang="en">
<a name="id2543637"></a><h2>AUTHOR</h2>
<p><span class="corpauthor">Internet Systems Consortium</span>
</p>
</div>
</div></body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -25,6 +25,11 @@
#include <dns/rdatastruct.h>
#include <dst/dst.h>
#define check_dns_dbiterator_current(result) \
check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \
"dns_dbiterator_current()")
typedef void (fatalcallback_t)(void);
ISC_PLATFORM_NORETURN_PRE void
@ -81,4 +86,12 @@ isc_boolean_t
key_collision(dst_key_t *key, dns_name_t *name, const char *dir,
isc_mem_t *mctx, isc_boolean_t *exact);
isc_boolean_t
is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp);
void
verifyzone(dns_db_t *db, dns_dbversion_t *ver,
dns_name_t *origin, isc_mem_t *mctx,
isc_boolean_t ignore_kskflag, isc_boolean_t keyset_kskonly);
#endif /* DNSSEC_DNSSECTOOL_H */

View file

@ -21,256 +21,228 @@ SYSTEMTESTTOP=../..
RANDFILE=../random.data
zone=secure.example
zonefile="${zone}.db"
infile="${zonefile}.in"
dumpit () {
echo "D:${debug}: dumping ${1}"
cat "${1}" | sed 's/^/D:/'
}
setup () {
echo "I:setting up zone: $1"
debug="$1"
zone="$1"
zonefile="${zone}.db"
infile="${zonefile}.in"
n=`expr ${n:-0} + 1`
}
setup secure.example
cp $infile $zonefile
ksk=`$KEYGEN -3 -q -r $RANDFILE -fk $zone`
$KEYGEN -3 -q -r $RANDFILE $zone > /dev/null
ksk=`$KEYGEN -3 -q -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
$KEYGEN -3 -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$DSFROMKEY $ksk.key > dsset-${zone}.
#
# NSEC3/NSEC test zone
#
zone=secure.nsec3.example
zonefile="${zone}.db"
infile="${zonefile}.in"
setup secure.nsec3.example
cp $infile $zonefile
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
$KEYGEN -q -3 -r $RANDFILE $zone > /dev/null
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$DSFROMKEY $ksk.key > dsset-${zone}.
#
# NSEC3/NSEC3 test zone
#
zone=nsec3.nsec3.example
zonefile="${zone}.db"
infile="${zonefile}.in"
setup nsec3.nsec3.example
cp $infile $zonefile
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
$KEYGEN -q -3 -r $RANDFILE $zone > /dev/null
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$DSFROMKEY $ksk.key > dsset-${zone}.
#
# OPTOUT/NSEC3 test zone
#
zone=optout.nsec3.example
zonefile="${zone}.db"
infile="${zonefile}.in"
setup optout.nsec3.example
cp $infile $zonefile
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
$KEYGEN -q -3 -r $RANDFILE $zone > /dev/null
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$DSFROMKEY $ksk.key > dsset-${zone}.
#
# A nsec3 zone (non-optout).
#
zone=nsec3.example
zonefile="${zone}.db"
infile="${zonefile}.in"
setup nsec3.example
cat $infile dsset-*.${zone}. > $zonefile
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
$KEYGEN -q -3 -r $RANDFILE $zone > /dev/null
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$DSFROMKEY $ksk.key > dsset-${zone}.
#
# An NSEC3 zone, with NSEC3 parameters set prior to signing
#
zone=autonsec3.example
zonefile="${zone}.db"
infile="${zonefile}.in"
setup autonsec3.example
cat $infile > $zonefile
ksk=`$KEYGEN -G -q -3 -r $RANDFILE -fk $zone`
ksk=`$KEYGEN -G -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
echo $ksk > ../autoksk.key
zsk=`$KEYGEN -G -q -3 -r $RANDFILE $zone`
zsk=`$KEYGEN -G -q -3 -r $RANDFILE $zone 2> kg.out` || dumpit kg.out
echo $zsk > ../autozsk.key
$DSFROMKEY $ksk.key > dsset-${zone}.
#
# OPTOUT/NSEC test zone
#
zone=secure.optout.example
zonefile="${zone}.db"
infile="${zonefile}.in"
setup secure.optout.example
cp $infile $zonefile
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
$KEYGEN -q -3 -r $RANDFILE $zone > /dev/null
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$DSFROMKEY $ksk.key > dsset-${zone}.
#
# OPTOUT/NSEC3 test zone
#
zone=nsec3.optout.example
zonefile="${zone}.db"
infile="${zonefile}.in"
setup nsec3.optout.example
cp $infile $zonefile
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
$KEYGEN -q -3 -r $RANDFILE $zone > /dev/null
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$DSFROMKEY $ksk.key > dsset-${zone}.
#
# OPTOUT/OPTOUT test zone
#
zone=optout.optout.example
zonefile="${zone}.db"
infile="${zonefile}.in"
setup optout.optout.example
cp $infile $zonefile
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
$KEYGEN -q -3 -r $RANDFILE $zone > /dev/null
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$DSFROMKEY $ksk.key > dsset-${zone}.
#
# A optout nsec3 zone.
#
zone=optout.example
zonefile="${zone}.db"
infile="${zonefile}.in"
setup optout.example
cat $infile dsset-*.${zone}. > $zonefile
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
$KEYGEN -q -3 -r $RANDFILE $zone > /dev/null
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$DSFROMKEY $ksk.key > dsset-${zone}.
#
# A RSASHA256 zone.
#
zone=rsasha256.example
zonefile="${zone}.db"
infile="${zonefile}.in"
setup rsasha256.example
cp $infile $zonefile
ksk=`$KEYGEN -q -a RSASHA256 -b 2048 -r $RANDFILE -fk $zone`
$KEYGEN -q -a RSASHA256 -b 1024 -r $RANDFILE $zone > /dev/null
ksk=`$KEYGEN -q -a RSASHA256 -b 2048 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
$KEYGEN -q -a RSASHA256 -b 1024 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$DSFROMKEY $ksk.key > dsset-${zone}.
#
# A RSASHA512 zone.
#
zone=rsasha512.example
zonefile="${zone}.db"
infile="${zonefile}.in"
setup rsasha512.example
cp $infile $zonefile
ksk=`$KEYGEN -q -a RSASHA512 -b 2048 -r $RANDFILE -fk $zone`
$KEYGEN -q -a RSASHA512 -b 1024 -r $RANDFILE $zone > /dev/null
ksk=`$KEYGEN -q -a RSASHA512 -b 2048 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
$KEYGEN -q -a RSASHA512 -b 1024 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$DSFROMKEY $ksk.key > dsset-${zone}.
#
# NSEC-only zone.
#
zone=nsec.example
zonefile="${zone}.db"
infile="${zonefile}.in"
setup nsec.example
cp $infile $zonefile
ksk=`$KEYGEN -q -r $RANDFILE -fk $zone`
$KEYGEN -q -r $RANDFILE $zone > /dev/null
ksk=`$KEYGEN -q -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
$KEYGEN -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$DSFROMKEY $ksk.key > dsset-${zone}.
#
# Signature refresh test zone. Signatures are set to expire long
# in the past; they should be updated by autosign.
#
zone=oldsigs.example
zonefile="${zone}.db"
infile="${zonefile}.in"
setup oldsigs.example
cp $infile $zonefile
ksk=`$KEYGEN -q -r $RANDFILE -fk $zone`
$KEYGEN -q -r $RANDFILE $zone > /dev/null
$SIGNER -PS -s now-1y -e now-6mo -o $zone -f $zonefile $infile > /dev/null 2>&1
$KEYGEN -q -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
$KEYGEN -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$SIGNER -PS -s now-1y -e now-6mo -o $zone -f $zonefile $infile > s.out 2>&1 || dumpit s.out
#
# NSEC3->NSEC transition test zone.
#
zone=nsec3-to-nsec.example
zonefile="${zone}.db"
infile="${zonefile}.in"
#cp $infile $zonefile
ksk=`$KEYGEN -q -a RSASHA512 -b 2048 -r $RANDFILE -fk $zone`
$KEYGEN -q -a RSASHA512 -b 1024 -r $RANDFILE $zone > /dev/null
$SIGNER -S -3 beef -A -o $zone -f $zonefile $infile > /dev/null 2>&1
setup nsec3-to-nsec.example
$KEYGEN -q -a RSASHA512 -b 2048 -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
$KEYGEN -q -a RSASHA512 -b 1024 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$SIGNER -S -3 beef -A -o $zone -f $zonefile $infile > s.out 2>&1 || dumpit s.out
#
# secure-to-insecure transition test zone; used to test removal of
# keys via nsupdate
#
zone=secure-to-insecure.example
zonefile="${zone}.db"
infile="${zonefile}.in"
ksk=`$KEYGEN -q -r $RANDFILE -fk $zone`
$KEYGEN -q -r $RANDFILE $zone > /dev/null
$SIGNER -S -o $zone -f $zonefile $infile > /dev/null 2>&1
setup secure-to-insecure.example
$KEYGEN -q -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
$KEYGEN -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$SIGNER -S -o $zone -f $zonefile $infile > s.out 2>&1 || dumpit s.out
#
# another secure-to-insecure transition test zone; used to test
# removal of keys on schedule.
#
zone=secure-to-insecure2.example
zonefile="${zone}.db"
infile="${zonefile}.in"
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
setup secure-to-insecure2.example
ksk=`$KEYGEN -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
echo $ksk > ../del1.key
zsk=`$KEYGEN -q -3 -r $RANDFILE $zone`
zsk=`$KEYGEN -q -3 -r $RANDFILE $zone 2> kg.out` || dumpit kg.out
echo $zsk > ../del2.key
$SIGNER -S -3 beef -o $zone -f $zonefile $infile > /dev/null 2>&1
$SIGNER -S -3 beef -o $zone -f $zonefile $infile > s.out 2>&1 || dumpit s.out
#
# Introducing a pre-published key test.
#
zone=prepub.example
zonefile="${zone}.db"
$KEYGEN -3 -q -r $RANDFILE -fk $zone > /dev/null
$KEYGEN -3 -q -r $RANDFILE $zone > /dev/null
$SIGNER -S -3 beef -o $zone -f $zonefile $infile > /dev/null 2>&1
setup prepub.example
infile="secure-to-insecure2.example.db.in"
$KEYGEN -3 -q -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
$KEYGEN -3 -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$SIGNER -S -3 beef -o $zone -f $zonefile $infile > s.out 2>&1 || dumpit s.out
#
# Key TTL tests.
#
# no default key TTL; DNSKEY should get SOA TTL
zone=ttl1.example
zonefile="${zone}.db"
infile="${zonefile}.in"
$KEYGEN -3 -q -r $RANDFILE -fk $zone > /dev/null
$KEYGEN -3 -q -r $RANDFILE $zone > /dev/null
setup ttl1.example
$KEYGEN -3 -q -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
$KEYGEN -3 -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
cp $infile $zonefile
# default key TTL should be used
zone=ttl2.example
zonefile="${zone}.db"
$KEYGEN -3 -q -r $RANDFILE -fk -L 60 $zone > /dev/null
$KEYGEN -3 -q -r $RANDFILE -L 60 $zone > /dev/null
setup ttl2.example
$KEYGEN -3 -q -r $RANDFILE -fk -L 60 $zone > kg.out 2>&1 || dumpit kg.out
$KEYGEN -3 -q -r $RANDFILE -L 60 $zone > kg.out 2>&1 || dumpit kg.out
cp $infile $zonefile
# mismatched key TTLs, should use shortest
zone=ttl3.example
zonefile="${zone}.db"
$KEYGEN -3 -q -r $RANDFILE -fk -L 30 $zone > /dev/null
$KEYGEN -3 -q -r $RANDFILE -L 60 $zone > /dev/null
setup ttl3.example
$KEYGEN -3 -q -r $RANDFILE -fk -L 30 $zone > kg.out 2>&1 || dumpit kg.out
$KEYGEN -3 -q -r $RANDFILE -L 60 $zone > kg.out 2>&1 || dumpit kg.out
cp $infile $zonefile
# existing DNSKEY RRset, should retain TTL
zone=ttl4.example
zonefile="${zone}.db"
$KEYGEN -3 -q -r $RANDFILE -L 30 -fk $zone > /dev/null
setup ttl4.example
$KEYGEN -3 -q -r $RANDFILE -L 30 -fk $zone > kg.out 2>&1 || dumpit kg.out
cat ${infile} K${zone}.+*.key > $zonefile
$KEYGEN -3 -q -r $RANDFILE -L 180 $zone > /dev/null
$KEYGEN -3 -q -r $RANDFILE -L 180 $zone > kg.out 2>&1 || dumpit kg.out
#
# A zone with a DNSKEY RRset that is published before it's activated
#
zone=delay.example
zonefile="${zone}.db"
ksk=`$KEYGEN -G -q -3 -r $RANDFILE -fk $zone`
setup delay.example
ksk=`$KEYGEN -G -q -3 -r $RANDFILE -fk $zone 2> kg.out` || dumpit kg.out
echo $ksk > ../delayksk.key
zsk=`$KEYGEN -G -q -3 -r $RANDFILE $zone`
zsk=`$KEYGEN -G -q -3 -r $RANDFILE $zone 2> kg.out` || dumpit kg.out
echo $zsk > ../delayzsk.key
#
# A zone with signatures that are already expired, and the private ZSK
# is missing.
#
zone=nozsk.example
zonefile="${zone}.db"
$KEYGEN -q -3 -r $RANDFILE -fk $zone > /dev/null
setup nozsk.example
$KEYGEN -q -3 -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
zsk=`$KEYGEN -q -3 -r $RANDFILE $zone`
$SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > /dev/null 2>&1
$SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > s.out 2>&1 || dumpit s.out
echo $zsk > ../missingzsk.key
rm -f ${zsk}.private
@ -278,19 +250,17 @@ rm -f ${zsk}.private
# A zone with signatures that are already expired, and the private ZSK
# is inactive.
#
zone=inaczsk.example
zonefile="${zone}.db"
$KEYGEN -q -3 -r $RANDFILE -fk $zone > /dev/null
setup inaczsk.example
$KEYGEN -q -3 -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
zsk=`$KEYGEN -q -3 -r $RANDFILE $zone`
$SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > /dev/null 2>&1
$SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in > s.out 2>&1 || dumpit s.out
echo $zsk > ../inactivezsk.key
$SETTIME -I now $zsk > /dev/null
$SETTIME -I now $zsk > st.out 2>&1 || dumpit st.out
#
# A zone that is set to 'auto-dnssec maintain' during a recofnig
#
zone=reconf.example
zonefile="${zone}.db"
setup reconf.example
cp secure.example.db.in $zonefile
$KEYGEN -q -3 -r $RANDFILE -fk $zone > /dev/null
$KEYGEN -q -3 -r $RANDFILE $zone > /dev/null
$KEYGEN -q -3 -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
$KEYGEN -q -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out

View file

@ -48,6 +48,7 @@ PK11GEN="$TOP/bin/pkcs11/pkcs11-keygen -s 0 -p 1234"
PK11LIST="$TOP/bin/pkcs11/pkcs11-list -s 0 -p 1234"
PK11DEL="$TOP/bin/pkcs11/pkcs11-destroy -s 0 -p 1234"
JOURNALPRINT=$TOP/bin/tools/named-journalprint
VERIFY=$TOP/bin/dnssec/dnssec-verify
# The "stress" test is not run by default since it creates enough
# load on the machine to make it unusable to other users.

7
bin/tests/system/verify/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
random.data
verify.out.*
zones/*.good
zones/*.bad
zones/K*
zones/dsset-*
zones/s.out*

View file

@ -0,0 +1,9 @@
rm -f zones/*.good
rm -f zones/*.good.tmp
rm -f zones/*.bad
rm -f zones/*.bad.tmp
rm -f zones/*.out*
rm -f zones/dsset-*
rm -f zones/K*
rm -f random.data
rm -f verify.out*

View file

@ -0,0 +1,23 @@
#!/bin/sh -e
#
# 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.
# $Id: setup.sh,v 1.20 2011/02/15 22:02:36 marka Exp $
sh clean.sh
../../../tools/genrandom 400 random.data
(cd zones && sh genzones.sh)

View file

@ -0,0 +1,81 @@
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
failed () {
cat verify.out.$n | sed 's/^/D:/';
echo "I:failed";
status=1;
}
n=0
status=0
for file in zones/*.good
do
n=`expr $n + 1`
zone=`expr "$file" : 'zones/\(.*\).good'`
echo "I:checking supposedly good zone: $zone ($n)"
ret=0
case $zone in
zsk-only.*) only=-z;;
ksk-only.*) only=-z;;
*) only=;;
esac
$VERIFY ${only} -o $zone $file > verify.out.$n 2>&1 || ret=1
[ $ret = 0 ] || failed
done
for file in zones/*.bad
do
n=`expr $n + 1`
zone=`expr "$file" : 'zones/\(.*\).bad'`
echo "I:checking supposedly bad zone: $zone ($n)"
ret=0
dumpit=0
case $zone in
zsk-only.*) only=-z;;
ksk-only.*) only=-z;;
*) only=;;
esac
expect1= expect2=
case $zone in
*.dnskeyonly)
expect1="DNSKEY is not signed"
;;
*.expired)
expect1="signature has expired"
expect2="No self-signed .*DNSKEY found"
;;
*.ksk-expired)
expect1="signature has expired"
expect2="No self-signed .*DNSKEY found"
;;
*.out-of-zone-nsec|*.below-bottom-of-zone-nsec)
expect1="unexpected NSEC RRset at"
;;
*.nsec.broken-chain)
expect1="Bad record NSEC record for.*, next name mismatch"
;;
*.bad-bitmap)
expect1="bit map mismatch"
;;
*.missing-empty)
expect1="Missing NSEC3 record for";
;;
unsigned)
expect1="Zone contains no DNSSEC keys"
;;
*.extra-nsec3)
expect1="Expected and found NSEC3 chains not equal";
;;
*)
dumpit=1
;;
esac
$VERIFY ${only} -o $zone $file > verify.out.$n 2>&1 && ret=1
grep "${expect1:-.}" verify.out.$n > /dev/null || ret=1
grep "${expect2:-.}" verify.out.$n > /dev/null || ret=1
[ $ret = 0 ] || failed
[ $dumpit = 1 ] && cat verify.out.$n
done
exit $status

View file

@ -0,0 +1,175 @@
SYSTEMTESTTOP=../..
. $SYSTEMTESTTOP/conf.sh
RANDFILE=../random.data
dumpit () {
echo "D:${debug}: dumping ${1}"
cat "${1}" | sed 's/^/D:/'
}
setup () {
echo "I:setting up $2 zone: $1"
debug="$1"
zone="$1"
file="$1.$2"
n=`expr ${n:-0} + 1`
}
# A unsigned zone should fail validation.
setup unsigned bad
cp unsigned.db unsigned.bad
# A set of nsec zones.
setup zsk-only.nsec good
$KEYGEN -r $RANDFILE ${zone}> kg.out$n 2>&1 || dumpit kg.out$n
$SIGNER -SP -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
setup ksk-only.nsec good
$KEYGEN -r $RANDFILE -fK ${zone} > kg.out$n 2>&1 || dumpit kg.out$n
$SIGNER -SPz -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
setup ksk+zsk.nsec good
$KEYGEN -r $RANDFILE ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
$KEYGEN -r $RANDFILE -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
$SIGNER -SPx -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
# A set of nsec3 zones.
setup zsk-only.nsec3 good
$KEYGEN -3 -r $RANDFILE ${zone}> kg.out$n 2>&1 || dumpit kg.out$n
$SIGNER -3 - -SP -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
setup ksk-only.nsec3 good
$KEYGEN -3 -r $RANDFILE -fK ${zone} > kg.out$n 2>&1 || dumpit kg.out$n
$SIGNER -3 - -SPz -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
setup ksk+zsk.nsec3 good
$KEYGEN -3 -r $RANDFILE ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
$KEYGEN -3 -r $RANDFILE -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
$SIGNER -3 - -SPx -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
setup ksk+zsk.outout good
$KEYGEN -3 -r $RANDFILE ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
$KEYGEN -3 -r $RANDFILE -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
$SIGNER -3 - -A -SPx -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
# A set of zones with only DNSKEY records.
setup zsk-only.dnskeyonly bad
key1=`$KEYGEN -r $RANDFILE ${zone} 2>kg.out` || dumpit kg.out$n
cat unsigned.db $key1.key > ${file}
setup ksk-only.dnskeyonly bad
key1=`$KEYGEN -r $RANDFILE -fK ${zone} 2>kg.out` || dumpit kg.out$n
cat unsigned.db $key1.key > ${file}
setup ksk+zsk.dnskeyonly bad
key1=`$KEYGEN -r $RANDFILE ${zone} 2>kg.out` || dumpit kg.out$n
key2=`$KEYGEN -r $RANDFILE -fK ${zone} 2>kg.out` || dumpit kg.out$n
cat unsigned.db $key1.key $key2.key > ${file}
# A set of zones with expired records
s="-s -2678400"
setup zsk-only.nsec.expired bad
$KEYGEN -r $RANDFILE ${zone}> kg.out$n 2>&1 || dumpit kg.out$n
$SIGNER -SP ${s} -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
setup ksk-only.nsec.expired bad
$KEYGEN -r $RANDFILE -fK ${zone} > kg.out$n 2>&1 || dumpit kg.out$n
$SIGNER -SPz ${s} -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
setup ksk+zsk.nsec.expired bad
$KEYGEN -r $RANDFILE ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
$KEYGEN -r $RANDFILE -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
$SIGNER -SP ${s} -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
setup zsk-only.nsec3.expired bad
$KEYGEN -3 -r $RANDFILE ${zone}> kg.out$n 2>&1 || dumpit kg.out$n
$SIGNER -3 - ${s} -SP -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
setup ksk-only.nsec3.expired bad
$KEYGEN -3 -r $RANDFILE -fK ${zone} > kg.out$n 2>&1 || dumpit kg.out$n
$SIGNER -3 - ${s} -SPz -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
setup ksk+zsk.nsec3.expired bad
$KEYGEN -3 -r $RANDFILE ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
$KEYGEN -3 -r $RANDFILE -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
$SIGNER -3 - ${s} -SPx -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
# ksk expired
setup ksk+zsk.nsec.ksk-expired bad
zsk=`$KEYGEN -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
ksk=`$KEYGEN -r $RANDFILE -fK ${zone} 2> kg2.out$n` || dumpit kg2.out$n
cat unsigned.db $ksk.key $zsk.key > $file
$SIGNER -Px -o ${zone} -f ${file} ${file} $zsk > s.out$n 2>&1 || dumpit s.out$n
$SIGNER ${s} -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n 2>&1 || dumpit s.out$n
now=`date -u +%Y%m%d%H%M%S`
exp=`awk '$4 == "RRSIG" && $5 == "DNSKEY" { print $9;}' ${file}`
[ "${exp:-40001231246060}" -lt ${now:-0} ] || dumpit $file
setup ksk+zsk.nsec3.ksk-expired bad
zsk=`$KEYGEN -3 -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
ksk=`$KEYGEN -3 -r $RANDFILE -fK ${zone} 2> kg2.out$n` || dumpit kg2.out$n
cat unsigned.db $ksk.key $zsk.key > $file
$SIGNER -3 - -Px -o ${zone} -f ${file} ${file} $zsk > s.out$n 2>&1 || dumpit s.out$n
$SIGNER -3 - ${s} -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n 2>&1 || dumpit s.out$n
now=`date -u +%Y%m%d%H%M%S`
exp=`awk '$4 == "RRSIG" && $5 == "DNSKEY" { print $9;}' ${file}`
[ "${exp:-40001231246060}" -lt ${now:-0} ] || dumpit $file
# broken nsec chain
setup ksk+zsk.nsec.broken-chain bad
zsk=`$KEYGEN -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
ksk=`$KEYGEN -r $RANDFILE -fK ${zone} 2> kg2.out$n` || dumpit kg2.out$n
cat unsigned.db $ksk.key $zsk.key > $file
$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n 2>&1 || dumpit s.out$n
awk '$4 == "NSEC" { $5 = "'$zone'."; print } { print }' ${file} > ${file}.tmp
$SIGNER -Px -Z nonsecify -o ${zone} -f ${file} ${file}.tmp $zsk > s.out$n 2>&1 || dumpit s.out$n
# bad nsec bitmap
setup ksk+zsk.nsec.bad-bitmap bad
zsk=`$KEYGEN -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
ksk=`$KEYGEN -r $RANDFILE -fK ${zone} 2> kg2.out$n` || dumpit kg2.out$n
cat unsigned.db $ksk.key $zsk.key > $file
$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n 2>&1 || dumpit s.out$n
awk '$4 == "NSEC" && /SOA/ { $6=""; print } { print }' ${file} > ${file}.tmp
$SIGNER -Px -Z nonsecify -o ${zone} -f ${file} ${file}.tmp $zsk > s.out$n 2>&1 || dumpit s.out$n
# extra NSEC record out side of zone
setup ksk+zsk.nsec.out-of-zone-nsec bad
zsk=`$KEYGEN -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
ksk=`$KEYGEN -r $RANDFILE -fK ${zone} 2> kg2.out$n` || dumpit kg2.out$n
cat unsigned.db $ksk.key $zsk.key > $file
$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n 2>&1 || dumpit s.out$n
echo "out-of-zone. 3600 IN NSEC ${zone}. A" >> ${file}
$SIGNER -Px -Z nonsecify -O full -o ${zone} -f ${file} ${file} $zsk > s.out$n 2>&1 || dumpit s.out$n
# extra NSEC record below bottom of one
setup ksk+zsk.nsec.below-bottom-of-zone-nsec bad
zsk=`$KEYGEN -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
ksk=`$KEYGEN -r $RANDFILE -fK ${zone} 2> kg2.out$n` || dumpit kg2.out$n
cat unsigned.db $ksk.key $zsk.key > $file
$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n 2>&1 || dumpit s.out$n
echo "ns.sub.${zone}. 3600 IN NSEC ${zone}. A AAAA" >> ${file}
$SIGNER -Px -Z nonsecify -O full -o ${zone} -f ${file}.tmp ${file} $zsk > s.out$n 2>&1 || dumpit s.out$n
# dnssec-signzone signs any node with a NSEC record.
awk '$1 ~ /^ns.sub/ && $4 == "RRSIG" && $5 != "NSEC" { next; } { print; }' ${file}.tmp > ${file}
# missing NSEC3 record at empty node
setup ksk+zsk.nsec3.missing-empty bad
zsk=`$KEYGEN -3 -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
ksk=`$KEYGEN -3 -r $RANDFILE -fK ${zone} 2> kg2.out$n` || dumpit kg2.out$n
cat unsigned.db $ksk.key $zsk.key > $file
$SIGNER -3 - -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n 2>&1 || dumpit s.out$n
awk '$4 == "NSEC3" && NF == 9 { next; } { print; }' ${file} > ${file}.tmp
$SIGNER -3 - -Px -Z nonsecify -O full -o ${zone} -f ${file} ${file}.tmp $zsk > s.out$n 2>&1 || dumpit s.out$n
# extra NSEC3 record
setup ksk+zsk.nsec3.extra-nsec3 bad
zsk=`$KEYGEN -3 -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
ksk=`$KEYGEN -3 -r $RANDFILE -fK ${zone} 2> kg2.out$n` || dumpit kg2.out$n
cat unsigned.db $ksk.key $zsk.key > $file
$SIGNER -3 - -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n 2>&1 || dumpit s.out$n
awk -v ZONE=${zone}. '$4 == "NSEC3" && NF == 9 {
$1 = "H9P7U7TR2U91D0V0LJS9L1GIDNP90U3H." ZONE;
$9 = "H9P7U7TR2U91D0V0LJS9L1GIDNP90U3I";
print; }' ${file} >> ${file}
$SIGNER -3 - -Px -Z nonsecify -O full -o ${zone} -f ${file} ${file} $zsk > s.out$n 2>&1 || dumpit s.out$n

View file

@ -0,0 +1,17 @@
$TTL 3600
@ SOA . . 0 0 0 2419200 3600 ; 28 day expire
@ NS .
data A 1.2.3.4
dname DNAME data
longttl 2419200 A 1.2.3.4
sub.dname TXT sub.dname
sub.empty TXT sub.empty
sub NS ns.sub
ns.sub A 1.2.3.4
ns.sub AAAA 2002::1.2.3.4
other.sub TXT other.sub
secure NS secure
secure DS 1312 50 100 96EEB2FFD9B00CD4694E78278B5EFDAB0A80446567B69F634DA078F0
secure A 1.2.3.4
secure AAAA 2002::1.2.3.4
out-of-zone. A 1.2.3.4

View file

@ -3022,7 +3022,7 @@ AC_ARG_WITH(docbook-xsl,
case "$docbook_path" in
auto)
AC_MSG_RESULT(auto)
docbook_xsl_trees="/usr/pkg/share/xsl/docbook /usr/local/share/xsl/docbook /usr/share/xsl/docbook"
docbook_xsl_trees="/usr/pkg/share/xsl/docbook /usr/local/share/xsl/docbook /usr/share/xsl/docbook /opt/local/share/xsl/docbook-xsl/"
;;
*)
docbook_xsl_trees="$withval"

View file

@ -16879,6 +16879,7 @@ zone "example.com" {
<xi:include href="../../bin/dnssec/dnssec-revoke.docbook"/>
<xi:include href="../../bin/dnssec/dnssec-settime.docbook"/>
<xi:include href="../../bin/dnssec/dnssec-signzone.docbook"/>
<xi:include href="../../bin/dnssec/dnssec-verify.docbook"/>
<xi:include href="../../bin/check/named-checkconf.docbook"/>
<xi:include href="../../bin/check/named-checkzone.docbook"/>
<xi:include href="../../bin/named/named.docbook"/>

25
doc/design/verify Normal file
View file

@ -0,0 +1,25 @@
dnssec-verify a tool to verify a zone is correctly signed.
* check that every record that should be signed has a valid RRSIG set.
* check that every record that shouldn't be signed isn't.
* check that each RRSIG set has a valid RRSIG and that all DNSKEY algorithms
in use are checked.
* provide a mechanism to mark DNSKEY algorithms to be ignored to support
verification of zones that are in the processs of adding/removing
support for a algorithm.
* provide a mechanism to check the zone as of a specified date and time.
* check that RRSIG won't expire within the TTL interval.
* check that original TTL matches.
NSEC:
* check that every node with data within the zone has a NSEC RRset.
* check that empty nodes don't have a NSEC record.
* check that nodes outside the zone do not have a NSEC record.
* check that the NSEC chain is valid.
NSEC3: for each NSEC3 chain
* check that every node with data within the zone has a NSEC3 RRset.
* check that empty nodes within the zone have a NSEC3 record.
* check that nodes outside the zone do not have a NSEC3 record.
* check that each NSEC3 in the NSEC3PARAM record is valid.

View file

@ -799,6 +799,10 @@ dns_db_findext(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* that it is correct. This only affects answers returned from the
* cache.
*
* \li In the #DNS_DBFIND_FORCENSEC3 option is set, then we are looking
* in the NSEC3 tree and not the main tree. Without this option being
* set NSEC3 records will not be found.
*
* \li To respond to a query for SIG records, the caller should create a
* rdataset iterator and extract the signatures from each rdataset.
*

View file

@ -76,6 +76,28 @@ dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version,
* 'answer' to be non NULL.
*/
unsigned int
dns_nsec_compressbitmap(unsigned char *map, const unsigned char *raw,
unsigned int max_type);
/*%<
* Convert a raw bitmap into a compressed windowed bit map. 'map' and 'raw'
* may overlap.
*
* Returns the length of the compressed windowed bit map.
*/
void
dns_nsec_setbit(unsigned char *array, unsigned int type, unsigned int bit);
/*%<
* Set type bit in raw 'array' to 'bit'.
*/
isc_boolean_t
dns_nsec_isset(const unsigned char *array, unsigned int type);
/*%<
* Test if the corresponding 'type' bit is set in 'array'.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_NSEC_H */

View file

@ -41,28 +41,61 @@
goto failure; \
} while (0)
static void
set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
void
dns_nsec_setbit(unsigned char *array, unsigned int type, unsigned int bit) {
unsigned int shift, mask;
shift = 7 - (index % 8);
shift = 7 - (type % 8);
mask = 1 << shift;
if (bit != 0)
array[index / 8] |= mask;
array[type / 8] |= mask;
else
array[index / 8] &= (~mask & 0xFF);
array[type / 8] &= (~mask & 0xFF);
}
static unsigned int
bit_isset(unsigned char *array, unsigned int index) {
isc_boolean_t
dns_nsec_isset(const unsigned char *array, unsigned int type) {
unsigned int byte, shift, mask;
byte = array[index / 8];
shift = 7 - (index % 8);
byte = array[type / 8];
shift = 7 - (type % 8);
mask = 1 << shift;
return ((byte & mask) != 0);
return (ISC_TF(byte & mask));
}
unsigned int
dns_nsec_compressbitmap(unsigned char *map, const unsigned char *raw,
unsigned int max_type)
{
unsigned char *start = map;
unsigned int window;
int octet;
if (raw == NULL)
return (0);
for (window = 0; window < 256; window++) {
if (window * 256 > max_type)
break;
for (octet = 31; octet >= 0; octet--)
if (*(raw + octet) != 0)
break;
if (octet < 0) {
raw += 32;
continue;
}
*map++ = window;
*map++ = octet + 1;
/*
* Note: potential overlapping move.
*/
memmove(map, raw, octet + 1);
map += octet + 1;
raw += 32;
}
return (map - start);
}
isc_result_t
@ -73,8 +106,7 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version,
isc_result_t result;
dns_rdataset_t rdataset;
isc_region_t r;
unsigned int i, window;
int octet;
unsigned int i;
unsigned char *nsec_bits, *bm;
unsigned int max_type;
@ -90,8 +122,8 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version,
*/
bm = r.base + r.length + 512;
nsec_bits = r.base + r.length;
set_bit(bm, dns_rdatatype_rrsig, 1);
set_bit(bm, dns_rdatatype_nsec, 1);
dns_nsec_setbit(bm, dns_rdatatype_rrsig, 1);
dns_nsec_setbit(bm, dns_rdatatype_nsec, 1);
max_type = dns_rdatatype_nsec;
dns_rdataset_init(&rdataset);
rdsiter = NULL;
@ -108,7 +140,7 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version,
rdataset.type != dns_rdatatype_rrsig) {
if (rdataset.type > max_type)
max_type = rdataset.type;
set_bit(bm, rdataset.type, 1);
dns_nsec_setbit(bm, rdataset.type, 1);
}
dns_rdataset_disassociate(&rdataset);
}
@ -116,12 +148,12 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version,
/*
* At zone cuts, deny the existence of glue in the parent zone.
*/
if (bit_isset(bm, dns_rdatatype_ns) &&
! bit_isset(bm, dns_rdatatype_soa)) {
if (dns_nsec_isset(bm, dns_rdatatype_ns) &&
! dns_nsec_isset(bm, dns_rdatatype_soa)) {
for (i = 0; i <= max_type; i++) {
if (bit_isset(bm, i) &&
if (dns_nsec_isset(bm, i) &&
! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i))
set_bit(bm, i, 0);
dns_nsec_setbit(bm, i, 0);
}
}
@ -129,22 +161,8 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version,
if (result != ISC_R_NOMORE)
return (result);
for (window = 0; window < 256; window++) {
if (window * 256 > max_type)
break;
for (octet = 31; octet >= 0; octet--)
if (bm[window * 32 + octet] != 0)
break;
if (octet < 0)
continue;
nsec_bits[0] = window;
nsec_bits[1] = octet + 1;
/*
* Note: potential overlapping move.
*/
memmove(&nsec_bits[2], &bm[window * 32], octet + 1);
nsec_bits += 3 + octet;
}
nsec_bits += dns_nsec_compressbitmap(nsec_bits, bm, max_type);
r.length = nsec_bits - r.base;
INSIST(r.length <= DNS_NSEC_BUFFERSIZE);
dns_rdata_fromregion(rdata,
@ -155,7 +173,6 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version,
return (ISC_R_SUCCESS);
}
isc_result_t
dns_nsec_build(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node,
dns_name_t *target, dns_ttl_t ttl)
@ -216,8 +233,8 @@ dns_nsec_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type) {
if ((window + 1) * 256 <= type)
continue;
if (type < (window * 256) + len * 8)
present = ISC_TF(bit_isset(&nsecstruct.typebits[i],
type % 256));
present = ISC_TF(dns_nsec_isset(&nsecstruct.typebits[i],
type % 256));
break;
}
dns_rdata_freestruct(&nsecstruct);

View file

@ -33,6 +33,7 @@
#include <dns/dbiterator.h>
#include <dns/diff.h>
#include <dns/fixedname.h>
#include <dns/nsec.h>
#include <dns/nsec3.h>
#include <dns/rdata.h>
#include <dns/rdatalist.h>
@ -52,30 +53,6 @@
#define INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 0)
#define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
static void
set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
unsigned int shift, mask;
shift = 7 - (index % 8);
mask = 1 << shift;
if (bit != 0)
array[index / 8] |= mask;
else
array[index / 8] &= (~mask & 0xFF);
}
static unsigned int
bit_isset(unsigned char *array, unsigned int index) {
unsigned int byte, shift, mask;
byte = array[index / 8];
shift = 7 - (index % 8);
mask = 1 << shift;
return ((byte & mask) != 0);
}
isc_result_t
dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
dns_dbnode_t *node, unsigned int hashalg,
@ -87,8 +64,7 @@ dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
isc_result_t result;
dns_rdataset_t rdataset;
isc_region_t r;
unsigned int i, window;
int octet;
unsigned int i;
isc_boolean_t found;
isc_boolean_t found_ns;
isc_boolean_t need_rrsig;
@ -156,7 +132,7 @@ dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
rdataset.type != dns_rdatatype_rrsig) {
if (rdataset.type > max_type)
max_type = rdataset.type;
set_bit(bm, rdataset.type, 1);
dns_nsec_setbit(bm, rdataset.type, 1);
/*
* Work out if we need to set the RRSIG bit for
* this node. We set the RRSIG bit if either of
@ -179,18 +155,18 @@ dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
if ((found && !found_ns) || need_rrsig) {
if (dns_rdatatype_rrsig > max_type)
max_type = dns_rdatatype_rrsig;
set_bit(bm, dns_rdatatype_rrsig, 1);
dns_nsec_setbit(bm, dns_rdatatype_rrsig, 1);
}
/*
* At zone cuts, deny the existence of glue in the parent zone.
*/
if (bit_isset(bm, dns_rdatatype_ns) &&
! bit_isset(bm, dns_rdatatype_soa)) {
if (dns_nsec_isset(bm, dns_rdatatype_ns) &&
! dns_nsec_isset(bm, dns_rdatatype_soa)) {
for (i = 0; i <= max_type; i++) {
if (bit_isset(bm, i) &&
if (dns_nsec_isset(bm, i) &&
! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i))
set_bit(bm, i, 0);
dns_nsec_setbit(bm, i, 0);
}
}
@ -199,22 +175,7 @@ dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
return (result);
collapse_bitmap:
for (window = 0; window < 256; window++) {
if (window * 256 > max_type)
break;
for (octet = 31; octet >= 0; octet--)
if (bm[window * 32 + octet] != 0)
break;
if (octet < 0)
continue;
nsec_bits[0] = window;
nsec_bits[1] = octet + 1;
/*
* Note: potentially overlapping move.
*/
memmove(&nsec_bits[2], &bm[window * 32], octet + 1);
nsec_bits += 3 + octet;
}
nsec_bits += dns_nsec_compressbitmap(nsec_bits, bm, max_type);
r.length = nsec_bits - r.base;
INSIST(r.length <= DNS_NSEC3_BUFFERSIZE);
dns_rdata_fromregion(rdata, dns_db_class(db), dns_rdatatype_nsec3, &r);
@ -249,8 +210,8 @@ dns_nsec3_typepresent(dns_rdata_t *rdata, dns_rdatatype_t type) {
if ((window + 1) * 256 <= type)
continue;
if (type < (window * 256) + len * 8)
present = ISC_TF(bit_isset(&nsec3.typebits[i],
type % 256));
present = ISC_TF(dns_nsec_isset(&nsec3.typebits[i],
type % 256));
break;
}
dns_rdata_freestruct(&nsec3);

View file

@ -60,6 +60,8 @@ isc_heap_create(isc_mem_t *mctx, isc_heapcompare_t compare,
* storage method. When the heap elements are deleted space is not freed
* but will be reused when new elements are inserted.
*
* Heap elements are indexed from 1.
*
* Requires:
*\li "mctx" is valid.
*\li "compare" is a function which takes two void * arguments and