📄 validator.c
字号:
proofs[DNS_VALIDATOR_NODATAPROOF] = name; if (!exists) val->attributes |= VALATTR_FOUNDNOWILDCARD; if (!exists && NEEDNOQNAME(val)) proofs[DNS_VALIDATOR_NOWILDCARDPROOF] = name; return (ISC_R_SUCCESS); } } } if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; return (result);}static isc_result_tnsecvalidate(dns_validator_t *val, isc_boolean_t resume) { dns_name_t *name; dns_message_t *message = val->event->message; isc_result_t result; if (!resume) result = dns_message_firstname(message, DNS_SECTION_AUTHORITY); else { result = ISC_R_SUCCESS; validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate"); } for (; result == ISC_R_SUCCESS; result = dns_message_nextname(message, DNS_SECTION_AUTHORITY)) { dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; name = NULL; dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name); if (resume) { rdataset = ISC_LIST_NEXT(val->currentset, link); val->currentset = NULL; resume = ISC_FALSE; } else rdataset = ISC_LIST_HEAD(name->list); for (; rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { if (rdataset->type == dns_rdatatype_rrsig) continue; if (rdataset->type == dns_rdatatype_soa) { val->soaset = rdataset; val->soaname = name; } else if (rdataset->type == dns_rdatatype_nsec) val->nsecset = rdataset; for (sigrdataset = ISC_LIST_HEAD(name->list); sigrdataset != NULL; sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) { if (sigrdataset->type == dns_rdatatype_rrsig && sigrdataset->covers == rdataset->type) break; } if (sigrdataset == NULL) continue; /* * If a signed zone is missing the zone key, bad * things could happen. A query for data in the zone * would lead to a query for the zone key, which * would return a negative answer, which would contain * an SOA and an NSEC signed by the missing key, which * would trigger another query for the DNSKEY (since * the first one is still in progress), and go into an * infinite loop. Avoid that. */ if (val->event->type == dns_rdatatype_dnskey && 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); dns_rdataset_current(rdataset, &nsec); if (dns_nsec_typepresent(&nsec, dns_rdatatype_soa)) continue; } val->currentset = rdataset; result = create_validator(val, name, rdataset->type, rdataset, sigrdataset, authvalidated, "nsecvalidate"); if (result != ISC_R_SUCCESS) return (result); return (DNS_R_WAIT); } } if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; if (result != ISC_R_SUCCESS) return (result); /* * Do we only need to check for NOQNAME? */ if ((val->attributes & VALATTR_NEEDNODATA) == 0 && (val->attributes & VALATTR_NEEDNOWILDCARD) == 0 && (val->attributes & VALATTR_NEEDNOQNAME) != 0) { if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0) { validator_log(val, ISC_LOG_DEBUG(3), "noqname proof found"); validator_log(val, ISC_LOG_DEBUG(3), "marking as secure"); val->event->rdataset->trust = dns_trust_secure; val->event->sigrdataset->trust = dns_trust_secure; return (ISC_R_SUCCESS); } validator_log(val, ISC_LOG_DEBUG(3), "noqname proof not found"); return (DNS_R_NOVALIDNSEC); } /* * Do we need to check for the wildcard? */ if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0 && (((val->attributes & VALATTR_NEEDNODATA) != 0 && (val->attributes & VALATTR_FOUNDNODATA) == 0) || (val->attributes & VALATTR_NEEDNOWILDCARD) != 0)) { result = checkwildcard(val); if (result != ISC_R_SUCCESS) return (result); } if (((val->attributes & VALATTR_NEEDNODATA) != 0 && (val->attributes & VALATTR_FOUNDNODATA) != 0) || ((val->attributes & VALATTR_NEEDNOQNAME) != 0 && (val->attributes & VALATTR_FOUNDNOQNAME) != 0 && (val->attributes & VALATTR_NEEDNOWILDCARD) != 0 && (val->attributes & VALATTR_FOUNDNOWILDCARD) != 0)) val->attributes |= VALATTR_FOUNDNONEXISTENCE; if ((val->attributes & VALATTR_FOUNDNONEXISTENCE) == 0) { if (!val->seensig && val->soaset != NULL) { result = create_validator(val, val->soaname, dns_rdatatype_soa, val->soaset, NULL, negauthvalidated, "nsecvalidate"); if (result != ISC_R_SUCCESS) return (result); return (DNS_R_WAIT); } validator_log(val, ISC_LOG_DEBUG(3), "nonexistence proof not found"); return (DNS_R_NOVALIDNSEC); } else { validator_log(val, ISC_LOG_DEBUG(3), "nonexistence proof found"); return (ISC_R_SUCCESS); }}static isc_boolean_tcheck_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) { dns_rdata_t dsrdata = DNS_RDATA_INIT; dns_rdata_ds_t ds; isc_result_t result; for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { dns_rdataset_current(rdataset, &dsrdata); (void)dns_rdata_tostruct(&dsrdata, &ds, NULL); if (ds.digest_type == DNS_DSDIGEST_SHA1 && dns_resolver_algorithm_supported(val->view->resolver, name, ds.algorithm)) { dns_rdata_reset(&dsrdata); return (ISC_TRUE); } dns_rdata_reset(&dsrdata); } return (ISC_FALSE);}static voiddlvfetched(isc_task_t *task, isc_event_t *event) { char namebuf[DNS_NAME_FORMATSIZE]; dns_fetchevent_t *devent; dns_validator_t *val; isc_boolean_t want_destroy; isc_result_t eresult; isc_result_t result; UNUSED(task); INSIST(event->ev_type == DNS_EVENT_FETCHDONE); devent = (dns_fetchevent_t *)event; val = devent->ev_arg; eresult = devent->result; /* Free resources which are not of interest. */ if (devent->node != NULL) dns_db_detachnode(devent->db, &devent->node); if (devent->db != NULL) dns_db_detach(&devent->db); if (dns_rdataset_isassociated(&val->fsigrdataset)) dns_rdataset_disassociate(&val->fsigrdataset); isc_event_free(&event); dns_resolver_destroyfetch(&val->fetch); INSIST(val->event != NULL); validator_log(val, ISC_LOG_DEBUG(3), "in dlvfetched: %s", dns_result_totext(eresult)); LOCK(&val->lock); if (eresult == ISC_R_SUCCESS) { dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf, sizeof(namebuf)); dns_rdataset_clone(&val->frdataset, &val->dlv); val->havedlvsep = ISC_TRUE; validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf); result = dlv_validator_start(val); if (result != DNS_R_WAIT) validator_done(val, result); } else if (eresult == DNS_R_NXRRSET || eresult == DNS_R_NXDOMAIN || eresult == DNS_R_NCACHENXRRSET || eresult == DNS_R_NCACHENXDOMAIN) { result = finddlvsep(val, ISC_TRUE); if (result == ISC_R_SUCCESS) { dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf, sizeof(namebuf)); validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf); result = dlv_validator_start(val); if (result != DNS_R_WAIT) validator_done(val, result); } else if (result == ISC_R_NOTFOUND) { validator_log(val, ISC_LOG_DEBUG(3), "DLV not found"); markanswer(val); validator_done(val, ISC_R_SUCCESS); } else { validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s", dns_result_totext(result)); if (result != DNS_R_WAIT) validator_done(val, result); } } else { validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s", dns_result_totext(eresult)); } want_destroy = exit_check(val); UNLOCK(&val->lock); if (want_destroy) destroy(val);}static isc_result_tstartfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) { char namebuf[DNS_NAME_FORMATSIZE]; isc_result_t result; INSIST(!DLVTRIED(val)); val->attributes |= VALATTR_DLVTRIED; dns_name_format(unsecure, namebuf, sizeof(namebuf)); validator_log(val, ISC_LOG_DEBUG(3), "plain DNSSEC returns unsecure (%s): looking for DLV", namebuf); if (dns_name_issubdomain(val->event->name, val->view->dlv)) { validator_log(val, ISC_LOG_WARNING, "must be secure failure"); return (DNS_R_MUSTBESECURE); } val->dlvlabels = dns_name_countlabels(unsecure) - 1; result = finddlvsep(val, ISC_FALSE); if (result == ISC_R_NOTFOUND) { validator_log(val, ISC_LOG_DEBUG(3), "DLV not found"); markanswer(val); return (ISC_R_SUCCESS); } if (result != ISC_R_SUCCESS) { validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s", dns_result_totext(result)); return (result); } dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf, sizeof(namebuf)); validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf); return (dlv_validator_start(val));}static isc_result_tfinddlvsep(dns_validator_t *val, isc_boolean_t resume) { char namebuf[DNS_NAME_FORMATSIZE]; dns_fixedname_t dlvfixed; dns_name_t *dlvname; dns_name_t *dlvsep; dns_name_t noroot; isc_result_t result; unsigned int labels; INSIST(val->view->dlv != NULL); if (!resume) { if (dns_name_issubdomain(val->event->name, val->view->dlv)) { validator_log(val, ISC_LOG_WARNING, "must be secure failure"); return (DNS_R_MUSTBESECURE); } dns_fixedname_init(&val->dlvsep); dlvsep = dns_fixedname_name(&val->dlvsep); dns_name_copy(val->event->name, dlvsep, NULL); if (val->event->type == dns_rdatatype_ds) { labels = dns_name_countlabels(dlvsep); if (labels == 0) return (ISC_R_NOTFOUND); dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep); } } else { dlvsep = dns_fixedname_name(&val->dlvsep); labels = dns_name_countlabels(dlvsep); dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep); } dns_name_init(&noroot, NULL); dns_fixedname_init(&dlvfixed); dlvname = dns_fixedname_name(&dlvfixed); labels = dns_name_countlabels(dlvsep); if (labels == 0) return (ISC_R_NOTFOUND); dns_name_getlabelsequence(dlvsep, 0, labels - 1, &noroot); result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL); while (result == ISC_R_NOSPACE) { labels = dns_name_countlabels(dlvsep); dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep); dns_name_getlabelsequence(dlvsep, 0, labels - 2, &noroot); result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL); } if (result != ISC_R_SUCCESS) { validator_log(val, ISC_LOG_DEBUG(2), "DLV concatenate failed"); return (DNS_R_NOVALIDSIG); } while (dns_name_countlabels(dlvname) >= dns_name_countlabels(val->view->dlv) + val->dlvlabels) { dns_name_format(dlvname, namebuf, sizeof(namebuf)); validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV %s", namebuf); result = view_find(val, dlvname, dns_rdatatype_dlv); if (result == ISC_R_SUCCESS) { if (val->frdataset.trust < dns_trust_secure) return (DNS_R_NOVALIDSIG); val->havedlvsep = ISC_TRUE; dns_rdataset_clone(&val->frdataset, &val->dlv); return (ISC_R_SUCCESS); } if (result == ISC_R_NOTFOUND) { result = create_fetch(val, dlvname, dns_rdatatype_dlv, dlvfetched, "finddlvsep"); if (result != ISC_R_SUCCESS) return (result); return (DNS_R_WAIT); } if (result != DNS_R_NXRRSET && result != DNS_R_NXDOMAIN && result != DNS_R_NCACHENXRRSET && result != DNS_R_NCACHENXDOMAIN) return (result); /* * Strip first labels from both dlvsep and dlvname. */ labels = dns_name_countlabels(dlvsep); if (labels == 0) break; dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep); labels = dns_name_countlabels(dlvname); dns_name_getlabelsequence(dlvname, 1, labels - 1, dlvname); } return (ISC_R_NOTFOUND);}/* * proveunsecure walks down from the SEP looking for a break in the * chain of trust. That occurs when we can prove the DS record does * not exist at a delegation point or the DS exists at a delegation * but we don't support the algorithm/digest. */static isc_result_tproveunsecure(dns_validator_t *val, isc_boolean_t resume) { isc_result_t result; dns_fixedname_t fixedsecroot; dns_name_t *secroot; dns_name_t *tname; char namebuf[DNS_NAME_FORMATSIZE]; dns_fixedname_init(&fixedsecroot); secroot = dns_fixedname_name(&fixedsecroot); if (val->havedlvsep) dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL); else { result = dns_keytable_finddeepestmatch(val->keytable, val->event->name, secroot); if (result == ISC_R_NOTFOUND) { validator_log(val, ISC_LOG_DEBUG(3), "not beneath secure root"); if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, "must be secure failure"); result = DNS_R_MUSTBESECURE; goto out; } if (val->view->dlv == NULL || DLVTRIED(val)) { markanswer(val); return (ISC_R_SUCCESS); } return (startfinddlvsep(val, dns_rootname)); } else if (result != ISC_R_SUCCESS) return (result); } if (!resume) { /* * We are looking for breaks below the SEP so add a label. */ val->labels = dns_name_countlabels(secroot) + 1; } else { validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure"); if (val->frdataset.trust >= dns_trust_secure && !check_ds(val, dns_fixedname_name(&val->fname), &val->frdataset)) { dns_name_format(dns_fixedname_name(&val->fname), namebuf, sizeof(namebuf)); if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, "must be secure failure at '%s'", namebuf); result = DNS_R_MUSTBESECURE; goto out; } validator_log(val, ISC_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -