diff --git a/lib/dns/zoneverify.c b/lib/dns/zoneverify.c index 4219a710e5..a7780aa87e 100644 --- a/lib/dns/zoneverify.c +++ b/lib/dns/zoneverify.c @@ -161,37 +161,22 @@ has_dname(const vctx_t *vctx, dns_dbnode_t *node) { static bool goodsig(const vctx_t *vctx, dns_rdata_t *sigrdata, const dns_name_t *name, - dns_rdataset_t *keyrdataset, dns_rdataset_t *rdataset) { - dns_rdata_dnskey_t key; + dst_key_t **dstkeys, size_t nkeys, dns_rdataset_t *rdataset) { dns_rdata_rrsig_t sig; - dst_key_t *dstkey = NULL; isc_result_t result; result = dns_rdata_tostruct(sigrdata, &sig, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); - 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); - result = dns_rdata_tostruct(&rdata, &key, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - result = dns_dnssec_keyfromrdata(vctx->origin, &rdata, - vctx->mctx, &dstkey); - if (result != ISC_R_SUCCESS) { - return (false); - } - if (sig.algorithm != key.algorithm || - sig.keyid != dst_key_id(dstkey) || + for (size_t key = 0; key < nkeys; key++) { + if (sig.algorithm != dst_key_alg(dstkeys[key]) || + sig.keyid != dst_key_id(dstkeys[key]) || !dns_name_equal(&sig.signer, vctx->origin)) { - dst_key_free(&dstkey); continue; } - result = dns_dnssec_verify(name, rdataset, dstkey, false, 0, - vctx->mctx, sigrdata, NULL); - dst_key_free(&dstkey); + result = dns_dnssec_verify(name, rdataset, dstkeys[key], false, + 0, vctx->mctx, sigrdata, NULL); if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) { return (true); } @@ -816,7 +801,7 @@ verifynsec3s(const vctx_t *vctx, const dns_name_t *name, static isc_result_t verifyset(vctx_t *vctx, dns_rdataset_t *rdataset, const dns_name_t *name, - dns_dbnode_t *node, dns_rdataset_t *keyrdataset) { + dns_dbnode_t *node, dst_key_t **dstkeys, size_t nkeys) { unsigned char set_algorithms[256]; char namebuf[DNS_NAME_FORMATSIZE]; char algbuf[DNS_SECALG_FORMATSIZE]; @@ -883,7 +868,7 @@ verifyset(vctx_t *vctx, dns_rdataset_t *rdataset, const dns_name_t *name, { continue; } - if (goodsig(vctx, &rdata, name, keyrdataset, rdataset)) { + if (goodsig(vctx, &rdata, name, dstkeys, nkeys, rdataset)) { dns_rdataset_settrust(rdataset, dns_trust_secure); dns_rdataset_settrust(&sigrdataset, dns_trust_secure); set_algorithms[sig.algorithm] = 1; @@ -919,7 +904,7 @@ done: static isc_result_t verifynode(vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node, - bool delegation, dns_rdataset_t *keyrdataset, + bool delegation, dst_key_t **dstkeys, size_t nkeys, dns_rdataset_t *nsecset, dns_rdataset_t *nsec3paramset, const dns_name_t *nextname, isc_result_t *vresult) { unsigned char types[8192]; @@ -953,8 +938,8 @@ verifynode(vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node, (!delegation || rdataset.type == dns_rdatatype_ds || rdataset.type == dns_rdatatype_nsec)) { - result = verifyset(vctx, &rdataset, name, node, - keyrdataset); + result = verifyset(vctx, &rdataset, name, node, dstkeys, + nkeys); if (result != ISC_R_SUCCESS) { dns_rdataset_disassociate(&rdataset); dns_rdatasetiter_destroy(&rdsiter); @@ -1724,6 +1709,8 @@ verify_nodes(vctx_t *vctx, isc_result_t *vresult) { dns_name_t *name, *nextname, *prevname, *zonecut; dns_dbnode_t *node = NULL, *nextnode; dns_dbiterator_t *dbiter = NULL; + dst_key_t **dstkeys; + size_t count, nkeys = 0; bool done = false; isc_result_t tvresult = ISC_R_UNSET; isc_result_t result; @@ -1735,11 +1722,27 @@ verify_nodes(vctx_t *vctx, isc_result_t *vresult) { dns_fixedname_init(&fzonecut); zonecut = NULL; + count = dns_rdataset_count(&vctx->keyset); + dstkeys = isc_mem_get(vctx->mctx, sizeof(*dstkeys) * count); + + for (result = dns_rdataset_first(&vctx->keyset); + result == ISC_R_SUCCESS; result = dns_rdataset_next(&vctx->keyset)) + { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(&vctx->keyset, &rdata); + dstkeys[nkeys] = NULL; + result = dns_dnssec_keyfromrdata(vctx->origin, &rdata, + vctx->mctx, &dstkeys[nkeys]); + if (result == ISC_R_SUCCESS) { + nkeys++; + } + } + result = dns_db_createiterator(vctx->db, DNS_DB_NONSEC3, &dbiter); if (result != ISC_R_SUCCESS) { zoneverify_log_error(vctx, "dns_db_createiterator(): %s", isc_result_totext(result)); - return (result); + goto done; } result = dns_dbiterator_first(dbiter); @@ -1839,9 +1842,9 @@ verify_nodes(vctx_t *vctx, isc_result_t *vresult) { dns_db_detachnode(vctx->db, &node); goto done; } - result = verifynode(vctx, name, node, isdelegation, - &vctx->keyset, &vctx->nsecset, - &vctx->nsec3paramset, nextname, &tvresult); + result = verifynode(vctx, name, node, isdelegation, dstkeys, + nkeys, &vctx->nsecset, &vctx->nsec3paramset, + nextname, &tvresult); if (result != ISC_R_SUCCESS) { dns_db_detachnode(vctx->db, &node); goto done; @@ -1889,7 +1892,7 @@ verify_nodes(vctx_t *vctx, isc_result_t *vresult) { isc_result_totext(result)); goto done; } - result = verifynode(vctx, name, node, false, &vctx->keyset, + result = verifynode(vctx, name, node, false, dstkeys, nkeys, NULL, NULL, NULL, NULL); if (result != ISC_R_SUCCESS) { zoneverify_log_error(vctx, "verifynode: %s", @@ -1907,7 +1910,13 @@ verify_nodes(vctx_t *vctx, isc_result_t *vresult) { result = ISC_R_SUCCESS; done: - dns_dbiterator_destroy(&dbiter); + while (nkeys-- > 0U) { + dst_key_free(&dstkeys[nkeys]); + } + isc_mem_put(vctx->mctx, dstkeys, sizeof(*dstkeys) * count); + if (dbiter != NULL) { + dns_dbiterator_destroy(&dbiter); + } return (result); }