From d930eaf77bf81539896cfdfd769eb9f99cb06f5b Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Mon, 18 Aug 2003 07:35:54 +0000 Subject: [PATCH] 1331. [func] Generate DNSSEC wildcard proofs. --- CHANGES | 2 + README | 4 +- bin/dnssec/dnssec-signzone.c | 8 +-- bin/named/query.c | 129 +++++++++++++++++++++++++++++++++-- doc/misc/dnssec | 10 +-- lib/dns/include/dns/db.h | 11 ++- lib/dns/include/dns/result.h | 3 +- lib/dns/rbtdb.c | 7 +- lib/dns/result.c | 4 +- 9 files changed, 151 insertions(+), 27 deletions(-) diff --git a/CHANGES b/CHANGES index 76ca75dbe3..b19b7c8cc2 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ 1332. [func] Report the current serial with periodic commits when rolling forward the journal. +1331. [func] Generate DNSSEC wildcard proofs. + 1329. [func] named-checkzone will now check if nameservers that appear to be IP addresses. Available modes "fail", "warn" (default) and "ignore" the results of the diff --git a/README b/README index f0b777ad90..bcf6b5d8a8 100644 --- a/README +++ b/README @@ -125,8 +125,8 @@ BIND 9.2.0 BIND 9.2 is capable of acting as an authoritative server for DNSSEC secured zones. This functionality is believed to - be stable and complete except for lacking support for wildcard - records in secure zones. + be stable and complete except for lacking support for + verifications involving wildcard records in secure zones. When acting as a caching server, BIND 9.2 can be configured to perform DNSSEC secure resolution on behalf of its clients. diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index fc99aa88ae..fe3b54a363 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -17,7 +17,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-signzone.c,v 1.139.2.2.4.3 2003/08/11 05:28:08 marka Exp $ */ +/* $Id: dnssec-signzone.c,v 1.139.2.2.4.4 2003/08/18 07:35:48 marka Exp $ */ #include @@ -794,12 +794,8 @@ signname(dns_dbnode_t *node, dns_name_t *name) { dns_name_format(name, namestr, sizeof namestr); if (warnwild++ == 0) { fprintf(stderr, "%s: warning: BIND 9 doesn't properly " - "handle wildcards in secure zones:\n", + "validate responses containing wildcards.\n", program); - fprintf(stderr, "\t- wildcard nonexistence proof is " - "not generated by the server\n"); - fprintf(stderr, "\t- wildcard nonexistence proof is " - "not required by the resolver\n"); } fprintf(stderr, "%s: warning: wildcard name seen: %s\n", program, namestr); diff --git a/bin/named/query.c b/bin/named/query.c index b8395b6379..e590172763 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: query.c,v 1.198.2.13.4.6 2003/08/15 03:22:42 marka Exp $ */ +/* $Id: query.c,v 1.198.2.13.4.7 2003/08/18 07:35:49 marka Exp $ */ #include @@ -2033,6 +2033,114 @@ query_addbestns(ns_client_t *client) { } } +static void +query_addwildcardproof(ns_client_t *client, dns_db_t *db, + isc_boolean_t ispositive) +{ + isc_buffer_t *dbuf, b; + dns_name_t *fname; + dns_rdataset_t *rdataset, *sigrdataset; + dns_fixedname_t tfixed; + dns_name_t *tname; + dns_dbnode_t *node; + unsigned int options; + unsigned int odepth, ndepth, i; + isc_result_t result; + + CTRACE("query_addwildcardproof"); + fname = NULL; + rdataset = NULL; + sigrdataset = NULL; + node = NULL; + + options = client->query.dboptions | DNS_DBFIND_NOWILD; + + if (ispositive) { + /* + * We'll need some resources... + */ + dbuf = query_getnamebuf(client); + if (dbuf == NULL) + goto cleanup; + fname = query_newname(client, dbuf, &b); + rdataset = query_newrdataset(client); + sigrdataset = query_newrdataset(client); + if (fname == NULL || rdataset == NULL || sigrdataset == NULL) + goto cleanup; + + result = dns_db_find(db, client->query.qname, NULL, + dns_rdatatype_nxt, options, 0, &node, + fname, rdataset, sigrdataset); + if (node != NULL) + dns_db_detachnode(db, &node); + if (result == DNS_R_NXDOMAIN) + query_addrrset(client, &fname, &rdataset, &sigrdataset, + dbuf, DNS_SECTION_AUTHORITY); + if (rdataset != NULL) + query_putrdataset(client, &rdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); + if (fname != NULL) + query_releasename(client, &fname); + } + + odepth = dns_name_depth(dns_db_origin(db)); + ndepth = dns_name_depth(client->query.qname); + + for (i = ndepth - 1; i >= odepth; i--) { + /* + * We'll need some resources... + */ + dbuf = query_getnamebuf(client); + if (dbuf == NULL) + goto cleanup; + fname = query_newname(client, dbuf, &b); + rdataset = query_newrdataset(client); + sigrdataset = query_newrdataset(client); + if (fname == NULL || rdataset == NULL || sigrdataset == NULL) + goto cleanup; + + dns_fixedname_init(&tfixed); + tname = dns_fixedname_name(&tfixed); + result = dns_name_splitatdepth(client->query.qname, + i, NULL, tname); + if (result != ISC_R_SUCCESS) + continue; + result = dns_name_concatenate(dns_wildcardname, tname, tname, + NULL); + if (result != ISC_R_SUCCESS) + continue; + + result = dns_db_find(db, tname, NULL, dns_rdatatype_nxt, + client->query.dboptions, 0, &node, + fname, rdataset, sigrdataset); + if (node != NULL) + dns_db_detachnode(db, &node); + /* + * If this returns success, we've found the wildcard for a + * successful answer, so we're done. + */ + if (result == ISC_R_SUCCESS && ispositive) + break; + if (result == DNS_R_NXDOMAIN) + query_addrrset(client, &fname, &rdataset, &sigrdataset, + dbuf, DNS_SECTION_AUTHORITY); + if (rdataset != NULL) + query_putrdataset(client, &rdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); + if (fname != NULL) + query_releasename(client, &fname); + } + cleanup: + if (rdataset != NULL) + query_putrdataset(client, &rdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); + if (fname != NULL) + query_releasename(client, &fname); +} + static void query_resume(isc_task_t *task, isc_event_t *event) { dns_fetchevent_t *devent = (dns_fetchevent_t *)event; @@ -2380,7 +2488,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) dns_rdataset_t **sigrdatasetp; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdatasetiter_t *rdsiter; - isc_boolean_t want_restart, authoritative, is_zone; + isc_boolean_t want_restart, authoritative, is_zone, need_wildcardproof; unsigned int n, nlabels, nbits; dns_namereln_t namereln; int order; @@ -2392,6 +2500,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; isc_boolean_t empty_wild; CTRACE("query_find"); @@ -2416,6 +2525,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) version = NULL; zone = NULL; empty_wild = ISC_FALSE; + options = 0; if (event != NULL) { /* @@ -2528,11 +2638,15 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) } } + options = client->query.dboptions; + if (WANTDNSSEC(client) && is_zone && dns_db_issecure(db)) + options |= DNS_DBFIND_INDICATEWILD; + /* * Now look for an answer in the database. */ result = dns_db_find(db, client->query.qname, version, type, - client->query.dboptions, client->now, + options, client->now, &node, fname, rdataset, sigrdataset); /* @@ -2596,6 +2710,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) CTRACE("query_find: resume"); switch (result) { case ISC_R_SUCCESS: + case DNS_R_WILDCARD: /* * This case is handled in the main line below. */ @@ -2882,10 +2997,12 @@ 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)) { query_addrrset(client, &fname, &rdataset, &sigrdataset, NULL, DNS_SECTION_AUTHORITY); + query_addwildcardproof(client, db, ISC_FALSE); + } } /* * Set message rcode. @@ -3089,6 +3206,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) goto cleanup; } + need_wildcardproof = ISC_TF(result == DNS_R_WILDCARD); + if (type == dns_rdatatype_any) { /* * XXXRTH Need to handle zonecuts with special case @@ -3198,6 +3317,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) */ INSIST(rdataset == NULL); } + if (need_wildcardproof) + query_addwildcardproof(client, db, ISC_TRUE); addauth: CTRACE("query_find: addauth"); diff --git a/doc/misc/dnssec b/doc/misc/dnssec index 44d2369263..5eed90f09f 100644 --- a/doc/misc/dnssec +++ b/doc/misc/dnssec @@ -38,14 +38,6 @@ When acting as an authoritative name server, BIND9 includes KEY, SIG and NXT records in responses as specified in RFC2535 when the request has the DO flag set in the query. -Response generation for wildcard records in secure zones is not fully -supported. Responses indicating the nonexistence of a name include a -NXT record proving the nonexistence of the name itself, but do not -include any NXT records to prove the nonexistence of a matching -wildcard record. Positive responses resulting from wildcard expansion -do not include the NXT records to prove the nonexistence of a -non-wildcard match or a more specific wildcard match. - Secure Resolution @@ -89,4 +81,4 @@ future as we consider them inferior to the use of TSIG or SIG(0) to ensure the integrity of zone transfers. -$Id: dnssec,v 1.14.2.6 2003/03/06 04:38:20 marka Exp $ +$Id: dnssec,v 1.14.2.6.4.1 2003/08/18 07:35:49 marka Exp $ diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index 7b26afcf83..e95713befd 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: db.h,v 1.67 2001/08/28 03:58:13 marka Exp $ */ +/* $Id: db.h,v 1.67.12.1 2003/08/18 07:35:54 marka Exp $ */ #ifndef DNS_DB_H #define DNS_DB_H 1 @@ -186,6 +186,7 @@ struct dns_db { #define DNS_DBFIND_NOWILD 0x04 #define DNS_DBFIND_PENDINGOK 0x08 #define DNS_DBFIND_NOEXACT 0x10 +#define DNS_DBFIND_INDICATEWILD 0x40 /* * Options that can be specified for dns_db_addrdataset(). @@ -684,6 +685,14 @@ dns_db_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, * ISC_R_SUCCESS The desired node and type were * found. * + * DNS_R_WILDCARD The desired node and type were + * found after performing + * wildcard matching. This is + * only returned if the + * DNS_DBFIND_INDICATEWILD + * option is set; otherwise + * ISC_R_SUCCESS is returned. + * * DNS_R_GLUE The desired node and type were * found, but are glue. This * result can only occur if diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h index e4bbb91ccc..8936548f55 100644 --- a/lib/dns/include/dns/result.h +++ b/lib/dns/include/dns/result.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.h,v 1.81.2.7.2.1 2003/08/18 05:56:58 marka Exp $ */ +/* $Id: result.h,v 1.81.2.7.2.2 2003/08/18 07:35:54 marka Exp $ */ #ifndef DNS_RESULT_H #define DNS_RESULT_H 1 @@ -121,6 +121,7 @@ #define DNS_R_UNKNOWNFLAG (ISC_RESULTCLASS_DNS + 82) #define DNS_R_EXPECTEDRESPONSE (ISC_RESULTCLASS_DNS + 83) #define DNS_R_NSISADDRESS (ISC_RESULTCLASS_DNS + 85) +#define DNS_R_WILDCARD (ISC_RESULTCLASS_DNS + 86) #define DNS_R_EMPTYNAME (ISC_RESULTCLASS_DNS + 92) #define DNS_R_EMPTYWILD (ISC_RESULTCLASS_DNS + 93) #define DNS_R_BADBITMAP (ISC_RESULTCLASS_DNS + 94) diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 67d04f0440..91e93cbd35 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbtdb.c,v 1.168.2.11 2003/07/22 04:03:43 marka Exp $ */ +/* $Id: rbtdb.c,v 1.168.2.11.2.1 2003/08/18 07:35:53 marka Exp $ */ /* * Principal Author: Bob Halley @@ -2286,7 +2286,10 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, /* * An ordinary successful query! */ - result = ISC_R_SUCCESS; + if (wild && (search.options & DNS_DBFIND_INDICATEWILD) != 0) + result = DNS_R_WILDCARD; + else + result = ISC_R_SUCCESS; } if (nodep != NULL) { diff --git a/lib/dns/result.c b/lib/dns/result.c index ace7769f92..c06f9646c1 100644 --- a/lib/dns/result.c +++ b/lib/dns/result.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.c,v 1.90.2.9.2.1 2003/08/18 05:56:56 marka Exp $ */ +/* $Id: result.c,v 1.90.2.9.2.2 2003/08/18 07:35:53 marka Exp $ */ #include @@ -129,7 +129,7 @@ static const char *text[DNS_R_NRESULTS] = { "", "NS is an address", /* 85 DNS_R_NSISADDRESS */ - "", + "wildcard", /* 86 DNS_R_WILDCARD */ "", "", "",