2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 14:35:26 +00:00

1328. [func] DS (delegation signer) support.

This commit is contained in:
Mark Andrews
2002-06-17 04:01:37 +00:00
parent 6a3c86ff43
commit 0b09763c35
24 changed files with 1628 additions and 976 deletions

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.c,v 1.219 2002/03/28 04:03:50 marka Exp $ */
/* $Id: query.c,v 1.220 2002/06/17 04:01:08 marka Exp $ */
#include <config.h>
@@ -2045,6 +2045,70 @@ query_addbestns(ns_client_t *client) {
}
}
static void
query_addds(ns_client_t *client, dns_db_t *db, dns_dbnode_t *node) {
dns_name_t *rname;
dns_rdataset_t *rdataset, *sigrdataset;
isc_result_t result;
CTRACE("query_addds");
rname = NULL;
rdataset = NULL;
sigrdataset = NULL;
/*
* We'll need some resources...
*/
rdataset = query_newrdataset(client);
sigrdataset = query_newrdataset(client);
if (rdataset == NULL || sigrdataset == NULL)
return;
/*
* Look for the DS record, which may or may not be present.
*/
result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0,
client->now, rdataset, sigrdataset);
/*
* If we didn't find it, look for an NXT. */
if (result == ISC_R_NOTFOUND)
result = dns_db_findrdataset(db, node, NULL,
dns_rdatatype_nxt, 0, client->now,
rdataset, sigrdataset);
if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
goto cleanup;
if (!dns_rdataset_isassociated(rdataset) ||
!dns_rdataset_isassociated(sigrdataset))
goto cleanup;
/*
* We've already added the NS record, so if the name's not there,
* we have other problems. Use this name rather than calling
* query_addrrset().
*/
result = dns_message_firstname(client->message, DNS_SECTION_AUTHORITY);
if (result != ISC_R_SUCCESS)
goto cleanup;
rname = NULL;
dns_message_currentname(client->message, DNS_SECTION_AUTHORITY,
&rname);
result = dns_message_findtype(rname, dns_rdatatype_ns, 0, NULL);
if (result != ISC_R_SUCCESS)
goto cleanup;
ISC_LIST_APPEND(rname->list, rdataset, link);
ISC_LIST_APPEND(rname->list, sigrdataset, link);
rdataset = NULL;
sigrdataset = NULL;
cleanup:
if (rdataset != NULL)
query_putrdataset(client, &rdataset);
if (sigrdataset != NULL)
query_putrdataset(client, &sigrdataset);
}
static void
query_resume(isc_task_t *task, isc_event_t *event) {
dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
@@ -2206,98 +2270,6 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
return (result);
}
static inline isc_result_t
query_findparentkey(ns_client_t *client, dns_name_t *name,
dns_zone_t **zonep, dns_db_t **dbp,
dns_dbversion_t **versionp, dns_dbnode_t **nodep,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
{
dns_db_t *pdb;
dns_dbnode_t *pnode;
dns_dbversion_t *pversion;
dns_rdataset_t prdataset, psigrdataset;
dns_rdataset_t *psigrdatasetp;
isc_result_t result;
dns_zone_t *pzone;
isc_boolean_t is_zone;
dns_fixedname_t pfoundname;
/*
* 'name' is at a zone cut. Try to find a KEY for 'name' in
* the deepest ancestor zone of 'name' (if any). If it exists,
* update *zonep, *dbp, *nodep, rdataset, and sigrdataset and
* return ISC_R_SUCCESS. If not, leave them alone and return a
* non-success status.
*/
pzone = NULL;
pdb = NULL;
pnode = NULL;
pversion = NULL;
dns_rdataset_init(&prdataset);
if (sigrdataset != NULL)
dns_rdataset_init(&psigrdataset);
is_zone = ISC_FALSE;
dns_fixedname_init(&pfoundname);
result = query_getdb(client, name, DNS_GETDB_NOEXACT,
&pzone, &pdb, &pversion, &is_zone);
if (result != ISC_R_SUCCESS)
goto cleanup;
if (!is_zone) {
result = ISC_R_FAILURE;
goto cleanup;
}
if (sigrdataset != NULL)
psigrdatasetp = &psigrdataset;
else
psigrdatasetp = NULL;
result = dns_db_find(pdb, name, pversion, dns_rdatatype_key,
client->query.dboptions,
client->now, &pnode,
dns_fixedname_name(&pfoundname),
&prdataset, psigrdatasetp);
if (result == ISC_R_SUCCESS) {
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
dns_rdataset_clone(&prdataset, rdataset);
if (sigrdataset != NULL) {
if (dns_rdataset_isassociated(sigrdataset))
dns_rdataset_disassociate(sigrdataset);
if (dns_rdataset_isassociated(&psigrdataset))
dns_rdataset_clone(&psigrdataset, sigrdataset);
}
if (*nodep != NULL)
dns_db_detachnode(*dbp, nodep);
*nodep = pnode;
pnode = NULL;
*versionp = pversion;
if (*dbp != NULL)
dns_db_detach(dbp);
*dbp = pdb;
pdb = NULL;
if (*zonep != NULL)
dns_zone_detach(zonep);
*zonep = pzone;
pzone = NULL;
}
cleanup:
if (dns_rdataset_isassociated(&prdataset))
dns_rdataset_disassociate(&prdataset);
if (sigrdataset != NULL && dns_rdataset_isassociated(&psigrdataset))
dns_rdataset_disassociate(&psigrdataset);
if (pnode != NULL)
dns_db_detachnode(pdb, &pnode);
if (pdb != NULL)
dns_db_detach(&pdb);
if (pzone != NULL)
dns_zone_detach(&pzone);
return (result);
}
#define MAX_RESTARTS 16
#define QUERY_ERROR(r) \
@@ -2419,6 +2391,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_zone_t *zone;
dns_rdata_cname_t cname;
dns_rdata_dname_t dname;
unsigned int options;
CTRACE("query_find");
@@ -2508,7 +2481,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
/*
* First we must find the right database.
*/
result = query_getdb(client, client->query.qname, 0, &zone, &db,
options = 0;
if (dns_rdatatype_atparent(qtype) &&
!dns_name_equal(client->query.qname, dns_rootname))
options |= DNS_GETDB_NOEXACT;
result = query_getdb(client, client->query.qname, options, &zone, &db,
&version, &is_zone);
if (result != ISC_R_SUCCESS) {
if (result == DNS_R_REFUSED)
@@ -2560,63 +2537,6 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
client->query.dboptions, client->now,
&node, fname, rdataset, sigrdataset);
/*
* We interrupt our normal query processing to bring you this special
* case...
*
* RFC 2535 (DNSSEC), section 2.3.4, discusses various special
* cases that can occur at delegation points.
*
* One of these cases is that the NULL KEY for an unsecure zone
* may occur in the delegating zone instead of in the delegated zone.
* If we're authoritative for both zones, we need to look for the
* key in the delegator if we didn't find it in the delegatee. If
* we didn't do this, a client doing DNSSEC validation could fail
* because it couldn't get the NULL KEY.
*/
if (type == dns_rdatatype_key &&
is_zone &&
result == DNS_R_NXRRSET &&
!dns_db_issecure(db) &&
dns_name_equal(client->query.qname, dns_db_origin(db))) {
/*
* We're looking for a KEY at the top of an unsecure zone,
* and we didn't find it.
*/
result = query_findparentkey(client, client->query.qname,
&zone, &db, &version, &node,
rdataset, sigrdataset);
if (result == ISC_R_SUCCESS) {
/*
* We found the parent KEY.
*
* zone, db, version, node, rdataset, and sigrdataset
* have all been updated to refer to the parent's
* data. We will resume query processing as if
* we had looked for the KEY in the parent zone in
* the first place.
*
* We need to set fname correctly. We do this here
* instead of in query_findparentkey() because
* dns_name_copy() can fail (though it shouldn't
* ever do so since we should have enough space).
*/
result = dns_name_copy(client->query.qname,
fname, NULL);
if (result != ISC_R_SUCCESS) {
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
} else {
/*
* We couldn't find the KEY in a parent zone.
* Continue with processing of the original
* results of dns_db_find().
*/
result = DNS_R_NXRRSET;
}
}
resume:
CTRACE("query_find: resume");
switch (result) {
@@ -2730,6 +2650,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
&rdataset, sigrdatasetp,
dbuf, DNS_SECTION_AUTHORITY);
client->query.gluedb = NULL;
if (WANTDNSSEC(client) && dns_db_issecure(db))
query_addds(client, db, node);
} else {
/*
* We might have a better answer or delegation
@@ -2789,6 +2711,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
/*
* Recurse!
*/
/* XXXBEW look at this? */
if (type == dns_rdatatype_key)
result = query_recurse(client, qtype,
NULL, NULL);
@@ -2826,6 +2749,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
client->query.gluedb = NULL;
client->query.attributes &=
~NS_QUERYATTR_CACHEGLUEOK;
if (WANTDNSSEC(client) &&
!dns_rdataset_isassociated(sigrdataset))
query_addds(client, db, node);
}
}
goto cleanup;
@@ -2857,8 +2783,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
/*
* Add NXT record if we found one.
*/
if (dns_rdataset_isassociated(rdataset)) {
if (WANTDNSSEC(client))
if (WANTDNSSEC(client)) {
if (dns_rdataset_isassociated(rdataset))
query_addrrset(client, &fname, &rdataset,
&sigrdataset,
NULL, DNS_SECTION_AUTHORITY);