diff options
Diffstat (limited to 'lib/dns/validator.c')
-rw-r--r-- | lib/dns/validator.c | 112 |
1 files changed, 90 insertions, 22 deletions
diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 6c0d38dc71a5c..9c532a24541f9 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: validator.c,v 1.197.40.3 2011-06-21 20:15:54 each Exp $ */ +/* $Id: validator.c,v 1.197.14.7 2011-06-08 23:02:43 each Exp $ */ #include <config.h> @@ -330,7 +330,6 @@ isdelegation(dns_name_t *name, dns_rdataset_t *rdataset, dns_fixedname_init(&fixed); dns_name_downcase(name, dns_fixedname_name(&fixed), NULL); name = dns_fixedname_name(&fixed); - result = dns_rdataset_first(rdataset); for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) @@ -514,7 +513,8 @@ dsfetched(isc_task_t *task, isc_event_t *event) { result = validatezonekey(val); if (result != DNS_R_WAIT) validator_done(val, result); - } else if (eresult == DNS_R_NXRRSET || + } else if (eresult == DNS_R_CNAME || + eresult == DNS_R_NXRRSET || eresult == DNS_R_NCACHENXRRSET || eresult == DNS_R_SERVFAIL) /* RFC 1034 parent? */ { @@ -582,12 +582,16 @@ dsfetched2(isc_task_t *task, isc_event_t *event) { LOCK(&val->lock); if (CANCELED(val)) { validator_done(val, ISC_R_CANCELED); - } else if (eresult == DNS_R_NXRRSET || eresult == DNS_R_NCACHENXRRSET) { + } else if (eresult == DNS_R_CNAME || + eresult == DNS_R_NXRRSET || + eresult == DNS_R_NCACHENXRRSET) + { /* * There is no DS. If this is a delegation, we're done. */ tname = dns_fixedname_name(&devent->foundname); - if (isdelegation(tname, &val->frdataset, eresult)) { + if (eresult != DNS_R_CNAME && + isdelegation(tname, &val->frdataset, eresult)) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, "must be secure failure, no DS" @@ -781,6 +785,60 @@ dsvalidated(isc_task_t *task, isc_event_t *event) { } /*% + * Callback when the CNAME record has been validated. + * + * Resumes validation of the unsecure zone proof. + */ +static void +cnamevalidated(isc_task_t *task, isc_event_t *event) { + dns_validatorevent_t *devent; + dns_validator_t *val; + isc_boolean_t want_destroy; + isc_result_t result; + isc_result_t eresult; + + UNUSED(task); + INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE); + + devent = (dns_validatorevent_t *)event; + val = devent->ev_arg; + eresult = devent->result; + + isc_event_free(&event); + dns_validator_destroy(&val->subvalidator); + + INSIST(val->event != NULL); + INSIST((val->attributes & VALATTR_INSECURITY) != 0); + + validator_log(val, ISC_LOG_DEBUG(3), "in cnamevalidated"); + LOCK(&val->lock); + if (CANCELED(val)) { + validator_done(val, ISC_R_CANCELED); + } else if (eresult == ISC_R_SUCCESS) { + validator_log(val, ISC_LOG_DEBUG(3), "cname with trust %s", + dns_trust_totext(val->frdataset.trust)); + result = proveunsecure(val, ISC_FALSE, ISC_TRUE); + if (result != DNS_R_WAIT) + validator_done(val, result); + } else { + if (eresult != DNS_R_BROKENCHAIN) { + if (dns_rdataset_isassociated(&val->frdataset)) + dns_rdataset_expire(&val->frdataset); + if (dns_rdataset_isassociated(&val->fsigrdataset)) + dns_rdataset_expire(&val->fsigrdataset); + } + validator_log(val, ISC_LOG_DEBUG(3), + "cnamevalidated: got %s", + isc_result_totext(eresult)); + validator_done(val, DNS_R_BROKENCHAIN); + } + want_destroy = exit_check(val); + UNLOCK(&val->lock); + if (want_destroy) + destroy(val); +} + +/*% * Return ISC_R_SUCCESS if we can determine that the name doesn't exist * or we can determine whether there is data or not at the name. * If the name does not exist return the wildcard name. @@ -1236,7 +1294,6 @@ authvalidated(isc_task_t *task, isc_event_t *event) { dns_validatorevent_t *devent; dns_validator_t *val; dns_rdataset_t *rdataset; - dns_rdataset_t *sigrdataset; isc_boolean_t want_destroy; isc_result_t result; isc_boolean_t exists, data; @@ -1246,7 +1303,6 @@ authvalidated(isc_task_t *task, isc_event_t *event) { devent = (dns_validatorevent_t *)event; rdataset = devent->rdataset; - sigrdataset = devent->sigrdataset; val = devent->ev_arg; result = devent->result; dns_validator_destroy(&val->subvalidator); @@ -2004,7 +2060,8 @@ validate(dns_validator_t *val, isc_boolean_t resume) { isc_stdtime_get(&now); ttl = ISC_MIN(event->rdataset->ttl, - val->siginfo->timeexpire - now); + ISC_MIN(val->siginfo->originalttl, + val->siginfo->timeexpire - now)); event->rdataset->ttl = ttl; event->sigrdataset->ttl = ttl; } @@ -2454,8 +2511,10 @@ validatezonekey(dns_validator_t *val) { validator_log(val, ISC_LOG_DEBUG(2), "unsigned DS record"); return (DNS_R_NOVALIDSIG); - } else + } else { result = ISC_R_SUCCESS; + POST(result); + } } else if (result == ISC_R_NOTFOUND) { /* * We don't have the DS. Find it. @@ -2466,11 +2525,12 @@ validatezonekey(dns_validator_t *val) { if (result != ISC_R_SUCCESS) return (result); return (DNS_R_WAIT); - } else if (result == DNS_R_NCACHENXDOMAIN || + } else if (result == DNS_R_NCACHENXDOMAIN || result == DNS_R_NCACHENXRRSET || result == DNS_R_EMPTYNAME || result == DNS_R_NXDOMAIN || - result == DNS_R_NXRRSET) + result == DNS_R_NXRRSET || + result == DNS_R_CNAME) { /* * The DS does not exist. @@ -2855,6 +2915,7 @@ findnsec3proofs(dns_validator_t *val) { } if (result != ISC_R_NOMORE) result = ISC_R_SUCCESS; + POST(result); if (dns_name_countlabels(zonename) == 0) return (ISC_R_SUCCESS); @@ -2987,13 +3048,11 @@ validate_authority(dns_validator_t *val, isc_boolean_t resume) { * infinite loop. Avoid that. */ if (val->event->type == dns_rdatatype_dnskey && + rdataset->type == dns_rdatatype_nsec && dns_name_equal(name, val->event->name)) { dns_rdata_t nsec = DNS_RDATA_INIT; - if (rdataset->type != dns_rdatatype_nsec) - continue; - result = dns_rdataset_first(rdataset); if (result != ISC_R_SUCCESS) return (result); @@ -3067,13 +3126,11 @@ validate_ncache(dns_validator_t *val, isc_boolean_t resume) { * infinite loop. Avoid that. */ if (val->event->type == dns_rdatatype_dnskey && + rdataset->type == dns_rdatatype_nsec && dns_name_equal(name, val->event->name)) { dns_rdata_t nsec = DNS_RDATA_INIT; - if (rdataset->type != dns_rdatatype_nsec) - continue; - result = dns_rdataset_first(rdataset); if (result != ISC_R_SUCCESS) return (result); @@ -3744,6 +3801,20 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) return (startfinddlvsep(val, tname)); } continue; + } else if (result == DNS_R_CNAME) { + if (DNS_TRUST_PENDING(val->frdataset.trust) || + DNS_TRUST_ANSWER(val->frdataset.trust)) { + result = create_validator(val, tname, + dns_rdatatype_cname, + &val->frdataset, + NULL, cnamevalidated, + "proveunsecure " + "(cname)"); + if (result != ISC_R_SUCCESS) + goto out; + return (DNS_R_WAIT); + } + continue; } else if (result == ISC_R_SUCCESS) { /* * There is a DS here. Verify that it's secure and @@ -4014,9 +4085,9 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, isc_task_t *task, isc_taskaction_t action, void *arg, dns_validator_t **validatorp) { - isc_result_t result; + isc_result_t result = ISC_R_FAILURE; dns_validator_t *val; - isc_task_t *tclone; + isc_task_t *tclone = NULL; dns_validatorevent_t *event; REQUIRE(name != NULL); @@ -4024,9 +4095,6 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, (rdataset == NULL && sigrdataset == NULL && message != NULL)); REQUIRE(validatorp != NULL && *validatorp == NULL); - tclone = NULL; - result = ISC_R_FAILURE; - val = isc_mem_get(view->mctx, sizeof(*val)); if (val == NULL) return (ISC_R_NOMEMORY); |