📄 validator.c
字号:
} isc_event_free(&event); want_destroy = exit_check(val); UNLOCK(&val->lock); if (want_destroy) destroy(val);}/*% * Callback from when a DNSKEY RRset has been validated. * * Resumes the stalled validation process. */static voidkeyvalidated(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); validator_log(val, ISC_LOG_DEBUG(3), "in keyvalidated"); LOCK(&val->lock); if (eresult == ISC_R_SUCCESS) { validator_log(val, ISC_LOG_DEBUG(3), "keyset with trust %d", val->frdataset.trust); /* * Only extract the dst key if the keyset is secure. */ if (val->frdataset.trust >= dns_trust_secure) (void) get_dst_key(val, val->siginfo, &val->frdataset); result = validate(val, ISC_TRUE); if (result != DNS_R_WAIT) validator_done(val, result); } else { validator_log(val, ISC_LOG_DEBUG(3), "keyvalidated: got %s", isc_result_totext(eresult)); validator_done(val, eresult); } want_destroy = exit_check(val); UNLOCK(&val->lock); if (want_destroy) destroy(val);}/*% * Callback when the DS record has been validated. * * Resumes validation of the zone key or the unsecure zone proof. */static voiddsvalidated(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); validator_log(val, ISC_LOG_DEBUG(3), "in dsvalidated"); LOCK(&val->lock); if (eresult == ISC_R_SUCCESS) { validator_log(val, ISC_LOG_DEBUG(3), "dsset with trust %d", val->frdataset.trust); if ((val->attributes & VALATTR_INSECURITY) != 0) result = proveunsecure(val, ISC_TRUE); else result = validatezonekey(val); if (result != DNS_R_WAIT) validator_done(val, result); } else { validator_log(val, ISC_LOG_DEBUG(3), "dsvalidated: got %s", isc_result_totext(eresult)); validator_done(val, eresult); } 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. * * Return ISC_R_IGNORE when the NSEC is not the appropriate one. */static isc_result_tnsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname, dns_rdataset_t *nsecset, isc_boolean_t *exists, isc_boolean_t *data, dns_name_t *wild){ int order; dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; dns_namereln_t relation; unsigned int olabels, nlabels, labels; dns_rdata_nsec_t nsec; isc_boolean_t atparent; isc_boolean_t ns; isc_boolean_t soa; REQUIRE(exists != NULL); REQUIRE(data != NULL); REQUIRE(nsecset != NULL && nsecset->type == dns_rdatatype_nsec); result = dns_rdataset_first(nsecset); if (result != ISC_R_SUCCESS) { validator_log(val, ISC_LOG_DEBUG(3), "failure processing NSEC set"); return (result); } dns_rdataset_current(nsecset, &rdata); validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant nsec"); relation = dns_name_fullcompare(name, nsecname, &order, &olabels); if (order < 0) { /* * The name is not within the NSEC range. */ validator_log(val, ISC_LOG_DEBUG(3), "NSEC does not cover name, before NSEC"); return (ISC_R_IGNORE); } if (order == 0) { /* * The names are the same. */ atparent = dns_rdatatype_atparent(val->event->type); ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns); soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa); if (ns && !soa) { if (!atparent) { /* * This NSEC record is from somewhere higher in * the DNS, and at the parent of a delegation. * It can not be legitimately used here. */ validator_log(val, ISC_LOG_DEBUG(3), "ignoring parent nsec"); return (ISC_R_IGNORE); } } else if (atparent && ns && soa) { /* * This NSEC record is from the child. * It can not be legitimately used here. */ validator_log(val, ISC_LOG_DEBUG(3), "ignoring child nsec"); return (ISC_R_IGNORE); } if (val->event->type == dns_rdatatype_cname || val->event->type == dns_rdatatype_nxt || val->event->type == dns_rdatatype_nsec || val->event->type == dns_rdatatype_key || !dns_nsec_typepresent(&rdata, dns_rdatatype_cname)) { *exists = ISC_TRUE; *data = dns_nsec_typepresent(&rdata, val->event->type); validator_log(val, ISC_LOG_DEBUG(3), "nsec proves name exists (owner) data=%d", *data); return (ISC_R_SUCCESS); } validator_log(val, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists"); return (ISC_R_IGNORE); } if (relation == dns_namereln_subdomain && dns_nsec_typepresent(&rdata, dns_rdatatype_ns) && !dns_nsec_typepresent(&rdata, dns_rdatatype_soa)) { /* * This NSEC record is from somewhere higher in * the DNS, and at the parent of a delegation. * It can not be legitimately used here. */ validator_log(val, ISC_LOG_DEBUG(3), "ignoring parent nsec"); return (ISC_R_IGNORE); } result = dns_rdata_tostruct(&rdata, &nsec, NULL); if (result != ISC_R_SUCCESS) return (result); relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels); if (order == 0) { dns_rdata_freestruct(&nsec); validator_log(val, ISC_LOG_DEBUG(3), "ignoring nsec matches next name"); return (ISC_R_IGNORE); } if (order < 0 && !dns_name_issubdomain(nsecname, &nsec.next)) { /* * The name is not within the NSEC range. */ dns_rdata_freestruct(&nsec); validator_log(val, ISC_LOG_DEBUG(3), "ignoring nsec because name is past end of range"); return (ISC_R_IGNORE); } if (order > 0 && relation == dns_namereln_subdomain) { validator_log(val, ISC_LOG_DEBUG(3), "nsec proves name exist (empty)"); dns_rdata_freestruct(&nsec); *exists = ISC_TRUE; *data = ISC_FALSE; return (ISC_R_SUCCESS); } if (wild != NULL) { dns_name_t common; dns_name_init(&common, NULL); if (olabels > nlabels) { labels = dns_name_countlabels(nsecname); dns_name_getlabelsequence(nsecname, labels - olabels, olabels, &common); } else { labels = dns_name_countlabels(&nsec.next); dns_name_getlabelsequence(&nsec.next, labels - nlabels, nlabels, &common); } result = dns_name_concatenate(dns_wildcardname, &common, wild, NULL); if (result != ISC_R_SUCCESS) { dns_rdata_freestruct(&nsec); validator_log(val, ISC_LOG_DEBUG(3), "failure generating wildcard name"); return (result); } } dns_rdata_freestruct(&nsec); validator_log(val, ISC_LOG_DEBUG(3), "nsec range ok"); *exists = ISC_FALSE; return (ISC_R_SUCCESS);}/*% * Callback for when NSEC records have been validated. * * Looks for NOQNAME and NODATA proofs. * * Resumes nsecvalidate. */static voidauthvalidated(isc_task_t *task, isc_event_t *event) { dns_validatorevent_t *devent; dns_validator_t *val; dns_rdataset_t *rdataset; isc_boolean_t want_destroy; isc_result_t result; isc_boolean_t exists, data; UNUSED(task); INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE); devent = (dns_validatorevent_t *)event; rdataset = devent->rdataset; val = devent->ev_arg; result = devent->result; dns_validator_destroy(&val->subvalidator); INSIST(val->event != NULL); validator_log(val, ISC_LOG_DEBUG(3), "in authvalidated"); LOCK(&val->lock); if (result != ISC_R_SUCCESS) { validator_log(val, ISC_LOG_DEBUG(3), "authvalidated: got %s", isc_result_totext(result)); if (result == ISC_R_CANCELED) validator_done(val, result); else { result = nsecvalidate(val, ISC_TRUE); if (result != DNS_R_WAIT) validator_done(val, result); } } else { dns_name_t **proofs = val->event->proofs; dns_name_t *wild = dns_fixedname_name(&val->wild); if (rdataset->trust == dns_trust_secure) val->seensig = ISC_TRUE; if (rdataset->type == dns_rdatatype_nsec && rdataset->trust == dns_trust_secure && ((val->attributes & VALATTR_NEEDNODATA) != 0 || (val->attributes & VALATTR_NEEDNOQNAME) != 0) && (val->attributes & VALATTR_FOUNDNODATA) == 0 && (val->attributes & VALATTR_FOUNDNOQNAME) == 0 && nsecnoexistnodata(val, val->event->name, devent->name, rdataset, &exists, &data, wild) == ISC_R_SUCCESS) { if (exists && !data) { val->attributes |= VALATTR_FOUNDNODATA; if (NEEDNODATA(val)) proofs[DNS_VALIDATOR_NODATAPROOF] = devent->name; } if (!exists) { val->attributes |= VALATTR_FOUNDNOQNAME; if (NEEDNOQNAME(val)) proofs[DNS_VALIDATOR_NOQNAMEPROOF] = devent->name; } } result = nsecvalidate(val, ISC_TRUE); if (result != DNS_R_WAIT) validator_done(val, result); } want_destroy = exit_check(val); UNLOCK(&val->lock); if (want_destroy) destroy(val); /* * Free stuff from the event. */ isc_event_free(&event);}/*% * Looks for the requested name and type in the view (zones and cache). * * When looking for a DLV record also checks to make sure the NSEC record * returns covers the query name as part of aggressive negative caching. * * Returns: * \li ISC_R_SUCCESS * \li ISC_R_NOTFOUND * \li DNS_R_NCACHENXDOMAIN * \li DNS_R_NCACHENXRRSET * \li DNS_R_NXRRSET * \li DNS_R_NXDOMAIN */static inline isc_result_tview_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) { dns_fixedname_t fixedname; dns_name_t *foundname; dns_rdata_nsec_t nsec; dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; unsigned int options; char buf1[DNS_NAME_FORMATSIZE]; char buf2[DNS_NAME_FORMATSIZE]; char buf3[DNS_NAME_FORMATSIZE]; if (dns_rdataset_isassociated(&val->frdataset)) dns_rdataset_disassociate(&val->frdataset); if (dns_rdataset_isassociated(&val->fsigrdataset)) dns_rdataset_disassociate(&val->fsigrdataset); if (val->view->zonetable == NULL) return (ISC_R_CANCELED); options = DNS_DBFIND_PENDINGOK; if (type == dns_rdatatype_dlv) options |= DNS_DBFIND_COVERINGNSEC; dns_fixedname_init(&fixedname); foundname = dns_fixedname_name(&fixedname); result = dns_view_find(val->view, name, type, 0, options, ISC_FALSE, NULL, NULL, foundname, &val->frdataset, &val->fsigrdataset); if (result == DNS_R_NXDOMAIN) { if (dns_rdataset_isassociated(&val->frdataset)) dns_rdataset_disassociate(&val->frdataset); if (dns_rdataset_isassociated(&val->fsigrdataset)) dns_rdataset_disassociate(&val->fsigrdataset); } else if (result == DNS_R_COVERINGNSEC) { validator_log(val, ISC_LOG_DEBUG(3), "DNS_R_COVERINGNSEC"); /* * Check if the returned NSEC covers the name. */ INSIST(type == dns_rdatatype_dlv); if (val->frdataset.trust != dns_trust_secure) { validator_log(val, ISC_LOG_DEBUG(3), "covering nsec: trust %u", val->frdataset.trust); goto notfound; } result = dns_rdataset_first(&val->frdataset); if (result != ISC_R_SUCCESS) goto notfound; dns_rdataset_current(&val->frdataset, &rdata); if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) && !dns_nsec_typepresent(&rdata, dns_rdatatype_soa)) { /* Parent NSEC record. */ if (dns_name_issubdomain(name, foundname)) { validator_log(val, ISC_LOG_DEBUG(3), "covering nsec: for parent"); goto notfound; } } result = dns_rdata_tostruct(&rdata, &nsec, NULL); if (result != ISC_R_SUCCESS) goto notfound; if (dns_name_compare(foundname, &nsec.next) >= 0) { /* End of zone chain. */ if (!dns_name_issubdomain(name, &nsec.next)) { /* * XXXMPA We could look for a parent NSEC * at nsec.next and if found retest with * this NSEC. */ dns_rdata_freestruct(&nsec); validator_log(val, ISC_LOG_DEBUG(3), "covering nsec: not in zone"); goto notfound; } } else if (dns_name_compare(name, &nsec.next) >= 0) { /* * XXXMPA We could check if this NSEC is at a zone * apex and if the qname is not below it and look for * a parent NSEC with the same name. This requires * that we can cache both NSEC records which we * currently don't support. */ dns_rdata_freestruct(&nsec); validator_log(val, ISC_LOG_DEBUG(3), "covering nsec: not in range"); goto notfound; } if (isc_log_wouldlog(dns_lctx,ISC_LOG_DEBUG(3))) { dns_name_format(name, buf1, sizeof buf1); dns_name_format(foundname, buf2, sizeof buf2); dns_name_format(&nsec.next, buf3, sizeof buf3); validator_log(val, ISC_LOG_DEBUG(3),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -