diff options
Diffstat (limited to 'lib/dns/validator.c')
-rw-r--r-- | lib/dns/validator.c | 428 |
1 files changed, 249 insertions, 179 deletions
diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 79c8798..6c0d38d 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: validator.c,v 1.164.12.23.4.3 2011-06-21 20:13:23 each Exp $ */ +/* $Id: validator.c,v 1.197.40.3 2011-06-21 20:15:54 each Exp $ */ #include <config.h> @@ -28,17 +28,17 @@ #include <isc/util.h> #include <dns/db.h> -#include <dns/ds.h> #include <dns/dnssec.h> +#include <dns/ds.h> #include <dns/events.h> #include <dns/keytable.h> +#include <dns/keyvalues.h> #include <dns/log.h> #include <dns/message.h> #include <dns/ncache.h> #include <dns/nsec.h> #include <dns/nsec3.h> #include <dns/rdata.h> -#include <dns/rdatastruct.h> #include <dns/rdataset.h> #include <dns/rdatatype.h> #include <dns/resolver.h> @@ -255,9 +255,17 @@ dlv_algorithm_supported(dns_validator_t *val) { dlv.algorithm)) continue; +#ifdef HAVE_OPENSSL_GOST + if (dlv.digest_type != DNS_DSDIGEST_SHA256 && + dlv.digest_type != DNS_DSDIGEST_SHA1 && + dlv.digest_type != DNS_DSDIGEST_GOST) + continue; +#else if (dlv.digest_type != DNS_DSDIGEST_SHA256 && dlv.digest_type != DNS_DSDIGEST_SHA1) continue; +#endif + return (ISC_TRUE); } @@ -383,7 +391,7 @@ isdelegation(dns_name_t *name, dns_rdataset_t *rdataset, } /*% - * We have been asked to to look for a key. + * We have been asked to look for a key. * If found resume the validation process. * If not found fail the validation process. */ @@ -582,7 +590,8 @@ dsfetched2(isc_task_t *task, isc_event_t *event) { if (isdelegation(tname, &val->frdataset, eresult)) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure, no DS" + " and this is a delegation"); validator_done(val, DNS_R_MUSTBESECURE); } else if (val->view->dlv == NULL || DLVTRIED(val)) { markanswer(val, "dsfetched2"); @@ -1089,7 +1098,7 @@ nsec3noexistnodata(dns_validator_t *val, dns_name_t* name, if (ns && !soa) { if (!atparent) { /* - * This NSEC record is from somewhere + * This NSEC3 record is from somewhere * higher in the DNS, and at the * parent of a delegation. It can not * be legitimately used here. @@ -1100,7 +1109,7 @@ nsec3noexistnodata(dns_validator_t *val, dns_name_t* name, } } else if (atparent && ns && soa) { /* - * This NSEC record is from the child. + * This NSEC3 record is from the child. * It can not be legitimately used here. */ validator_log(val, ISC_LOG_DEBUG(3), @@ -1505,8 +1514,11 @@ create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, if (dns_rdataset_isassociated(&val->fsigrdataset)) dns_rdataset_disassociate(&val->fsigrdataset); - if (check_deadlock(val, name, type, NULL, NULL)) + if (check_deadlock(val, name, type, NULL, NULL)) { + validator_log(val, ISC_LOG_DEBUG(3), + "deadlock found (create_fetch)"); return (DNS_R_NOVALIDSIG); + } validator_logcreate(val, name, type, caller, "fetch"); return (dns_resolver_createfetch(val->view->resolver, name, type, @@ -1528,8 +1540,11 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, { isc_result_t result; - if (check_deadlock(val, name, type, rdataset, sigrdataset)) + if (check_deadlock(val, name, type, rdataset, sigrdataset)) { + validator_log(val, ISC_LOG_DEBUG(3), + "deadlock found (create_validator)"); return (DNS_R_NOVALIDSIG); + } validator_logcreate(val, name, type, caller, "validator"); result = dns_validator_create(val->view, name, type, @@ -1768,16 +1783,23 @@ compute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) { */ static isc_boolean_t isselfsigned(dns_validator_t *val) { + dns_fixedname_t fixed; dns_rdataset_t *rdataset, *sigrdataset; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_t sigrdata = DNS_RDATA_INIT; dns_rdata_dnskey_t key; dns_rdata_rrsig_t sig; dns_keytag_t keytag; + dns_name_t *name; isc_result_t result; + dst_key_t *dstkey; + isc_mem_t *mctx; + isc_boolean_t answer = ISC_FALSE; rdataset = val->event->rdataset; sigrdataset = val->event->sigrdataset; + name = val->event->name; + mctx = val->view->mctx; INSIST(rdataset->type == dns_rdatatype_dnskey); @@ -1799,12 +1821,31 @@ isselfsigned(dns_validator_t *val) { result = dns_rdata_tostruct(&sigrdata, &sig, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); - if (sig.algorithm == key.algorithm && - sig.keyid == keytag) - return (ISC_TRUE); + if (sig.algorithm != key.algorithm || + sig.keyid != keytag || + !dns_name_equal(name, &sig.signer)) + continue; + + dstkey = NULL; + result = dns_dnssec_keyfromrdata(name, &rdata, mctx, + &dstkey); + if (result != ISC_R_SUCCESS) + continue; + + result = dns_dnssec_verify2(name, rdataset, dstkey, + ISC_TRUE, mctx, &sigrdata, + dns_fixedname_name(&fixed)); + dst_key_free(&dstkey); + if (result != ISC_R_SUCCESS) + continue; + if ((key.flags & DNS_KEYFLAG_REVOKE) == 0) { + answer = ISC_TRUE; + continue; + } + dns_view_untrust(val->view, name, &key, mctx); } } - return (ISC_FALSE); + return (answer); } /*% @@ -1946,6 +1987,8 @@ validate(dns_validator_t *val, isc_boolean_t resume) { break; } val->key = dns_keynode_key(val->keynode); + if (val->key == NULL) + break; } else { if (get_dst_key(val, val->siginfo, val->keyset) != ISC_R_SUCCESS) @@ -1962,8 +2005,6 @@ validate(dns_validator_t *val, isc_boolean_t resume) { isc_stdtime_get(&now); ttl = ISC_MIN(event->rdataset->ttl, val->siginfo->timeexpire - now); - if (val->keyset != NULL) - ttl = ISC_MIN(ttl, val->keyset->ttl); event->rdataset->ttl = ttl; event->sigrdataset->ttl = ttl; } @@ -1992,7 +2033,8 @@ validate(dns_validator_t *val, isc_boolean_t resume) { } else if (result == ISC_R_SUCCESS) { marksecure(event); validator_log(val, ISC_LOG_DEBUG(3), - "marking as secure"); + "marking as secure, " + "noqname proof not needed"); return (result); } else { validator_log(val, ISC_LOG_DEBUG(3), @@ -2013,25 +2055,102 @@ validate(dns_validator_t *val, isc_boolean_t resume) { } /*% + * Check whether this DNSKEY (keyrdata) signed the DNSKEY RRset + * (val->event->rdataset). + */ +static isc_result_t +checkkey(dns_validator_t *val, dns_rdata_t *keyrdata, isc_uint16_t keyid, + dns_secalg_t algorithm) +{ + dns_rdata_rrsig_t sig; + dst_key_t *dstkey = NULL; + isc_result_t result; + + for (result = dns_rdataset_first(val->event->sigrdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(val->event->sigrdataset)) + { + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_rdataset_current(val->event->sigrdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &sig, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + if (keyid != sig.keyid || algorithm != sig.algorithm) + continue; + if (dstkey == NULL) { + result = dns_dnssec_keyfromrdata(val->event->name, + keyrdata, + val->view->mctx, + &dstkey); + if (result != ISC_R_SUCCESS) + /* + * This really shouldn't happen, but... + */ + continue; + } + result = verify(val, dstkey, &rdata, sig.keyid); + if (result == ISC_R_SUCCESS) + break; + } + if (dstkey != NULL) + dst_key_free(&dstkey); + return (result); +} + +/*% + * Find the DNSKEY that corresponds to the DS. + */ +static isc_result_t +keyfromds(dns_validator_t *val, dns_rdataset_t *rdataset, dns_rdata_t *dsrdata, + isc_uint8_t digest, isc_uint16_t keyid, dns_secalg_t algorithm, + dns_rdata_t *keyrdata) +{ + dns_keytag_t keytag; + dns_rdata_dnskey_t key; + isc_result_t result; + unsigned char dsbuf[DNS_DS_BUFFERSIZE]; + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) + { + dns_rdata_t newdsrdata = DNS_RDATA_INIT; + + dns_rdata_reset(keyrdata); + dns_rdataset_current(rdataset, keyrdata); + result = dns_rdata_tostruct(keyrdata, &key, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + keytag = compute_keytag(keyrdata, &key); + if (keyid != keytag || algorithm != key.algorithm) + continue; + dns_rdata_reset(&newdsrdata); + result = dns_ds_buildrdata(val->event->name, keyrdata, digest, + dsbuf, &newdsrdata); + if (result != ISC_R_SUCCESS) { + validator_log(val, ISC_LOG_DEBUG(3), + "dns_ds_buildrdata() -> %s", + dns_result_totext(result)); + continue; + } + if (dns_rdata_compare(dsrdata, &newdsrdata) == 0) + break; + } + return (result); +} + +/*% * Validate the DNSKEY RRset by looking for a DNSKEY that matches a * DLV record and that also verifies the DNSKEY RRset. */ static isc_result_t dlv_validatezonekey(dns_validator_t *val) { - dns_keytag_t keytag; dns_rdata_dlv_t dlv; - dns_rdata_dnskey_t key; - dns_rdata_rrsig_t sig; dns_rdata_t dlvrdata = DNS_RDATA_INIT; dns_rdata_t keyrdata = DNS_RDATA_INIT; - dns_rdata_t newdsrdata = DNS_RDATA_INIT; - dns_rdata_t sigrdata = DNS_RDATA_INIT; dns_rdataset_t trdataset; - dst_key_t *dstkey; isc_boolean_t supported_algorithm; isc_result_t result; - unsigned char dsbuf[DNS_DS_BUFFERSIZE]; - isc_uint8_t digest_type; + char digest_types[256]; validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey"); @@ -2048,7 +2167,7 @@ dlv_validatezonekey(dns_validator_t *val) { * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256 * is present. */ - digest_type = DNS_DSDIGEST_SHA1; + memset(digest_types, 1, sizeof(digest_types)); for (result = dns_rdataset_first(&val->dlv); result == ISC_R_SUCCESS; result = dns_rdataset_next(&val->dlv)) { @@ -2064,7 +2183,7 @@ dlv_validatezonekey(dns_validator_t *val) { if (dlv.digest_type == DNS_DSDIGEST_SHA256 && dlv.length == ISC_SHA256_DIGESTLENGTH) { - digest_type = DNS_DSDIGEST_SHA256; + digest_types[DNS_DSDIGEST_SHA1] = 0; break; } } @@ -2082,7 +2201,7 @@ dlv_validatezonekey(dns_validator_t *val) { dlv.digest_type)) continue; - if (dlv.digest_type != digest_type) + if (digest_types[dlv.digest_type] == 0) continue; if (!dns_resolver_algorithm_supported(val->view->resolver, @@ -2095,70 +2214,27 @@ dlv_validatezonekey(dns_validator_t *val) { dns_rdataset_init(&trdataset); dns_rdataset_clone(val->event->rdataset, &trdataset); - for (result = dns_rdataset_first(&trdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(&trdataset)) - { - dns_rdata_reset(&keyrdata); - dns_rdataset_current(&trdataset, &keyrdata); - result = dns_rdata_tostruct(&keyrdata, &key, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - keytag = compute_keytag(&keyrdata, &key); - if (dlv.key_tag != keytag || - dlv.algorithm != key.algorithm) - continue; - dns_rdata_reset(&newdsrdata); - result = dns_ds_buildrdata(val->event->name, - &keyrdata, dlv.digest_type, - dsbuf, &newdsrdata); - if (result != ISC_R_SUCCESS) { - validator_log(val, ISC_LOG_DEBUG(3), - "dns_ds_buildrdata() -> %s", - dns_result_totext(result)); - continue; - } - /* Covert to DLV */ - newdsrdata.type = dns_rdatatype_dlv; - if (dns_rdata_compare(&dlvrdata, &newdsrdata) == 0) - break; - } + /* + * Convert to DLV to DS and find matching DNSKEY. + */ + dlvrdata.type = dns_rdatatype_ds; + result = keyfromds(val, &trdataset, &dlvrdata, + dlv.digest_type, dlv.key_tag, + dlv.algorithm, &keyrdata); if (result != ISC_R_SUCCESS) { dns_rdataset_disassociate(&trdataset); validator_log(val, ISC_LOG_DEBUG(3), "no DNSKEY matching DLV"); continue; } + validator_log(val, ISC_LOG_DEBUG(3), "Found matching DLV record: checking for signature"); + /* + * Check that this DNSKEY signed the DNSKEY rrset. + */ + result = checkkey(val, &keyrdata, dlv.key_tag, dlv.algorithm); - for (result = dns_rdataset_first(val->event->sigrdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(val->event->sigrdataset)) - { - dns_rdata_reset(&sigrdata); - dns_rdataset_current(val->event->sigrdataset, - &sigrdata); - result = dns_rdata_tostruct(&sigrdata, &sig, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - if (dlv.key_tag != sig.keyid || - dlv.algorithm != sig.algorithm) - continue; - dstkey = NULL; - result = dns_dnssec_keyfromrdata(val->event->name, - &keyrdata, - val->view->mctx, - &dstkey); - if (result != ISC_R_SUCCESS) - /* - * This really shouldn't happen, but... - */ - continue; - - result = verify(val, dstkey, &sigrdata, sig.keyid); - dst_key_free(&dstkey); - if (result == ISC_R_SUCCESS) - break; - } dns_rdataset_disassociate(&trdataset); if (result == ISC_R_SUCCESS) break; @@ -2167,12 +2243,13 @@ dlv_validatezonekey(dns_validator_t *val) { } if (result == ISC_R_SUCCESS) { marksecure(val->event); - validator_log(val, ISC_LOG_DEBUG(3), "marking as secure"); + validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (dlv)"); return (result); } else if (result == ISC_R_NOMORE && !supported_algorithm) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure," + "no supported algorithm/digest (dlv)"); return (DNS_R_MUSTBESECURE); } validator_log(val, ISC_LOG_DEBUG(3), @@ -2184,7 +2261,8 @@ dlv_validatezonekey(dns_validator_t *val) { } /*% - * Attempts positive response validation of an RRset containing zone keys. + * Attempts positive response validation of an RRset containing zone keys + * (i.e. a DNSKEY rrset). * * Returns: * \li ISC_R_SUCCESS Validation completed successfully @@ -2198,19 +2276,15 @@ validatezonekey(dns_validator_t *val) { dns_validatorevent_t *event; dns_rdataset_t trdataset; dns_rdata_t dsrdata = DNS_RDATA_INIT; - dns_rdata_t newdsrdata = DNS_RDATA_INIT; dns_rdata_t keyrdata = DNS_RDATA_INIT; dns_rdata_t sigrdata = DNS_RDATA_INIT; - unsigned char dsbuf[DNS_DS_BUFFERSIZE]; char namebuf[DNS_NAME_FORMATSIZE]; - dns_keytag_t keytag; dns_rdata_ds_t ds; - dns_rdata_dnskey_t key; dns_rdata_rrsig_t sig; dst_key_t *dstkey; isc_boolean_t supported_algorithm; isc_boolean_t atsep = ISC_FALSE; - isc_uint8_t digest_type; + char digest_types[256]; /* * Caller must be holding the validator lock. @@ -2259,8 +2333,7 @@ validatezonekey(dns_validator_t *val) { result = dns_keytable_findkeynode(val->keytable, val->event->name, sig.algorithm, - sig.keyid, - &keynode); + sig.keyid, &keynode); if (result == ISC_R_NOTFOUND && dns_keytable_finddeepestmatch(val->keytable, val->event->name, found) != ISC_R_SUCCESS) { @@ -2284,11 +2357,18 @@ validatezonekey(dns_validator_t *val) { while (result == ISC_R_SUCCESS) { dns_keynode_t *nextnode = NULL; dstkey = dns_keynode_key(keynode); + if (dstkey == NULL) { + dns_keytable_detachkeynode( + val->keytable, + &keynode); + break; + } result = verify(val, dstkey, &sigrdata, sig.keyid); if (result == ISC_R_SUCCESS) { - dns_keytable_detachkeynode(val->keytable, - &keynode); + dns_keytable_detachkeynode( + val->keytable, + &keynode); break; } result = dns_keytable_findnextkeynode( @@ -2318,8 +2398,8 @@ validatezonekey(dns_validator_t *val) { sizeof(namebuf)); validator_log(val, ISC_LOG_NOTICE, "unable to find a DNSKEY which verifies " - "the DNSKEY RRset and also matches one " - "of specified trusted-keys for '%s'", + "the DNSKEY RRset and also matches a " + "trusted key for '%s'", namebuf); validator_log(val, ISC_LOG_NOTICE, "please check the 'trusted-keys' for " @@ -2413,7 +2493,8 @@ validatezonekey(dns_validator_t *val) { if (val->dsset->trust < dns_trust_secure) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure," + " insecure DS"); return (DNS_R_MUSTBESECURE); } if (val->view->dlv == NULL || DLVTRIED(val)) { @@ -2437,7 +2518,7 @@ validatezonekey(dns_validator_t *val) { * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256 * is present. */ - digest_type = DNS_DSDIGEST_SHA1; + memset(digest_types, 1, sizeof(digest_types)); for (result = dns_rdataset_first(val->dsset); result == ISC_R_SUCCESS; result = dns_rdataset_next(val->dsset)) { @@ -2453,7 +2534,7 @@ validatezonekey(dns_validator_t *val) { if (ds.digest_type == DNS_DSDIGEST_SHA256 && ds.length == ISC_SHA256_DIGESTLENGTH) { - digest_type = DNS_DSDIGEST_SHA256; + digest_types[DNS_DSDIGEST_SHA1] = 0; break; } } @@ -2471,7 +2552,7 @@ validatezonekey(dns_validator_t *val) { ds.digest_type)) continue; - if (ds.digest_type != digest_type) + if (digest_types[ds.digest_type] == 0) continue; if (!dns_resolver_algorithm_supported(val->view->resolver, @@ -2485,29 +2566,10 @@ validatezonekey(dns_validator_t *val) { dns_rdataset_clone(val->event->rdataset, &trdataset); /* - * Look for the KEY that matches the DS record. + * Find matching DNSKEY from DS. */ - for (result = dns_rdataset_first(&trdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(&trdataset)) - { - dns_rdata_reset(&keyrdata); - dns_rdataset_current(&trdataset, &keyrdata); - result = dns_rdata_tostruct(&keyrdata, &key, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - keytag = compute_keytag(&keyrdata, &key); - if (ds.key_tag != keytag || - ds.algorithm != key.algorithm) - continue; - dns_rdata_reset(&newdsrdata); - result = dns_ds_buildrdata(val->event->name, - &keyrdata, ds.digest_type, - dsbuf, &newdsrdata); - if (result != ISC_R_SUCCESS) - continue; - if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0) - break; - } + result = keyfromds(val, &trdataset, &dsrdata, ds.digest_type, + ds.key_tag, ds.algorithm, &keyrdata); if (result != ISC_R_SUCCESS) { dns_rdataset_disassociate(&trdataset); validator_log(val, ISC_LOG_DEBUG(3), @@ -2515,38 +2577,11 @@ validatezonekey(dns_validator_t *val) { continue; } - for (result = dns_rdataset_first(val->event->sigrdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(val->event->sigrdataset)) - { - dns_rdata_reset(&sigrdata); - dns_rdataset_current(val->event->sigrdataset, - &sigrdata); - result = dns_rdata_tostruct(&sigrdata, &sig, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - if (ds.key_tag != sig.keyid || - ds.algorithm != sig.algorithm) - continue; - if (!dns_name_equal(val->event->name, &sig.signer)) { - validator_log(val, ISC_LOG_DEBUG(3), - "DNSKEY signer mismatch"); - continue; - } - dstkey = NULL; - result = dns_dnssec_keyfromrdata(val->event->name, - &keyrdata, - val->view->mctx, - &dstkey); - if (result != ISC_R_SUCCESS) - /* - * This really shouldn't happen, but... - */ - continue; - result = verify(val, dstkey, &sigrdata, sig.keyid); - dst_key_free(&dstkey); - if (result == ISC_R_SUCCESS) - break; - } + /* + * Check that this DNSKEY signed the DNSKEY rrset. + */ + result = checkkey(val, &keyrdata, ds.key_tag, ds.algorithm); + dns_rdataset_disassociate(&trdataset); if (result == ISC_R_SUCCESS) break; @@ -2555,20 +2590,24 @@ validatezonekey(dns_validator_t *val) { } if (result == ISC_R_SUCCESS) { marksecure(event); - validator_log(val, ISC_LOG_DEBUG(3), "marking as secure"); + validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)"); return (result); } else if (result == ISC_R_NOMORE && !supported_algorithm) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure, " + "no supported algorithm/digest (DS)"); return (DNS_R_MUSTBESECURE); } validator_log(val, ISC_LOG_DEBUG(3), "no supported algorithm/digest (DS)"); markanswer(val, "validatezonekey (3)"); return (ISC_R_SUCCESS); - } else + } else { + validator_log(val, ISC_LOG_INFO, + "no valid signature found (DS)"); return (DNS_R_NOVALIDSIG); + } } /*% @@ -3094,9 +3133,7 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) { findnsec3proofs(val); if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val)) { validator_log(val, ISC_LOG_DEBUG(3), - "noqname proof found"); - validator_log(val, ISC_LOG_DEBUG(3), - "marking as secure"); + "marking as secure, noqname proof found"); marksecure(val->event); return (ISC_R_SUCCESS); } else if (FOUNDOPTOUT(val) && @@ -3143,7 +3180,6 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) { marksecure(val->event); return (ISC_R_SUCCESS); } - findnsec3proofs(val); if (val->authfail != 0 && val->authcount == val->authfail) return (DNS_R_BROKENCHAIN); @@ -3345,7 +3381,8 @@ startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) { namebuf); if (dns_name_issubdomain(val->event->name, val->view->dlv)) { - validator_log(val, ISC_LOG_WARNING, "must be secure failure"); + validator_log(val, ISC_LOG_WARNING, "must be secure failure, " + " %s is under DLV (startfinddlvsep)", namebuf); return (DNS_R_MUSTBESECURE); } @@ -3397,10 +3434,12 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) { INSIST(val->view->dlv != NULL); if (!resume) { - if (dns_name_issubdomain(val->event->name, val->view->dlv)) { + dns_name_format(val->event->name, namebuf, + sizeof(namebuf)); validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure, " + "%s is under DLV (finddlvsep)", namebuf); return (DNS_R_MUSTBESECURE); } @@ -3468,8 +3507,11 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) { return (result); return (DNS_R_WAIT); } - if (val->frdataset.trust < dns_trust_secure) + if (val->frdataset.trust < dns_trust_secure) { + validator_log(val, ISC_LOG_DEBUG(3), + "DLV not validated"); return (DNS_R_NOVALIDSIG); + } val->havedlvsep = ISC_TRUE; dns_rdataset_clone(&val->frdataset, &val->dlv); return (ISC_R_SUCCESS); @@ -3554,10 +3596,13 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) if (result == ISC_R_NOTFOUND) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure, " + "not beneath secure root"); result = DNS_R_MUSTBESECURE; goto out; - } + } else + validator_log(val, ISC_LOG_DEBUG(3), + "not beneath secure root"); if (val->view->dlv == NULL || DLVTRIED(val)) { markanswer(val, "proveunsecure (1)"); return (ISC_R_SUCCESS); @@ -3577,7 +3622,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) /* * If we have a DS rdataset and it is secure then check if * the DS rdataset has a supported algorithm combination. - * If not this is a insecure delegation as far as this + * If not this is an insecure delegation as far as this * resolver is concerned. Fall back to DLV if available. */ if (have_ds && val->frdataset.trust >= dns_trust_secure && @@ -3588,7 +3633,8 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) if ((val->view->dlv == NULL || DLVTRIED(val)) && val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure at '%s'", + "must be secure failure at '%s', " + "can't fall back to DLV", namebuf); result = DNS_R_MUSTBESECURE; goto out; @@ -3630,7 +3676,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) { /* * There is no DS. If this is a delegation, - * we maybe done. + * we may be done. */ /* * If we have "trust == answer" then this namespace @@ -3643,7 +3689,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) &val->frdataset, NULL, dsvalidated, "proveunsecure"); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) goto out; return (DNS_R_WAIT); } @@ -3655,12 +3701,13 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) if (result == DNS_R_NXRRSET && !dns_rdataset_isassociated(&val->frdataset) && dns_view_findzonecut2(val->view, tname, found, - 0, 0, ISC_FALSE, ISC_FALSE, - NULL, NULL) == ISC_R_SUCCESS && + 0, 0, ISC_FALSE, ISC_FALSE, + NULL, NULL) == ISC_R_SUCCESS && dns_name_equal(tname, found)) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure, " + "no DS at zone cut"); return (DNS_R_MUSTBESECURE); } if (val->view->dlv == NULL || DLVTRIED(val)) { @@ -3676,13 +3723,18 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) * there's no way of validating existing * negative response blobs, give up. */ + validator_log(val, ISC_LOG_WARNING, + "can't validate existing " + "negative responses (no DS)"); result = DNS_R_NOVALIDSIG; goto out; } if (isdelegation(tname, &val->frdataset, result)) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure, " + "%s is a delegation", + namebuf); return (DNS_R_MUSTBESECURE); } if (val->view->dlv == NULL || DLVTRIED(val)) { @@ -3705,7 +3757,10 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure, " + "no supported algorithm/" + "digest (%s/DS)", + namebuf); result = DNS_R_MUSTBESECURE; goto out; } @@ -3723,6 +3778,8 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) } else if (!dns_rdataset_isassociated(&val->fsigrdataset)) { + validator_log(val, ISC_LOG_DEBUG(3), + "DS is unsigned"); result = DNS_R_NOVALIDSIG; goto out; } @@ -3771,6 +3828,10 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) * there's no way of validating existing * negative response blobs, give up. */ + validator_log(val, ISC_LOG_WARNING, + "can't validate existing " + "negative responses " + "(not a zone cut)"); result = DNS_R_NOVALIDSIG; goto out; } @@ -3790,7 +3851,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) /* Couldn't complete insecurity proof */ validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed"); - return (DNS_R_NOTINSECURE); /* Couldn't complete insecurity proof */ + return (DNS_R_NOTINSECURE); out: if (dns_rdataset_isassociated(&val->frdataset)) @@ -3829,7 +3890,7 @@ dlv_validator_start(dns_validator_t *val) { * \li 3. a negative answer (secure or unsecure). * * Note a answer that appears to be a secure positive answer may actually - * be a unsecure positive answer. + * be an unsecure positive answer. */ static void validator_start(isc_task_t *task, isc_event_t *event) { @@ -3895,6 +3956,10 @@ validator_start(isc_task_t *task, isc_event_t *event) { val->attributes |= VALATTR_INSECURITY; result = proveunsecure(val, ISC_FALSE, ISC_FALSE); + if (result == DNS_R_NOTINSECURE) + validator_log(val, ISC_LOG_INFO, + "got insecure response; " + "parent indicates it should be secure"); } else if (val->event->rdataset == NULL && val->event->sigrdataset == NULL) { @@ -3967,6 +4032,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, return (ISC_R_NOMEMORY); val->view = NULL; dns_view_weakattach(view, &val->view); + event = (dns_validatorevent_t *) isc_event_allocate(view->mctx, task, DNS_EVENT_VALIDATORSTART, @@ -3995,8 +4061,12 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, val->fetch = NULL; val->subvalidator = NULL; val->parent = NULL; + val->keytable = NULL; - dns_keytable_attach(val->view->secroots, &val->keytable); + result = dns_view_getsecroots(val->view, &val->keytable); + if (result != ISC_R_SUCCESS) + return (result); + val->keynode = NULL; val->key = NULL; val->siginfo = NULL; |