From: Evan Hunt Date: Tue, 21 Jun 2011 20:14:48 +0000 (+0000) Subject: 3124. [bug] Use an rdataset attribute flag to indicate X-Git-Tag: v9.7.3-P3~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f619d8eb7d08ef57fa8ad3f1a6b9ea105518bc67;p=thirdparty%2Fbind9.git 3124. [bug] Use an rdataset attribute flag to indicate negative-cache records rather than using rrtype 0; this will prevent problems when that rrtype is used in actual DNS packets. [RT #24777] --- diff --git a/CHANGES b/CHANGES index e4d20884d5e..3c3655bddf2 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,10 @@ --- 9.7.3-P2 released --- +3124. [bug] Use an rdataset attribute flag to indicate + negative-cache records rather than using rrtype 0; + this will prevent problems when that rrtype is + used in actual DNS packets. [RT #24777] + 3123. [security] Change #2912 exposed a latent flaw in dns_rdataset_totext() that could cause named to crash with an assertion failure. [RT #24777] diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h index b4c5a59ffc6..a90c5e61fb5 100644 --- a/lib/dns/include/dns/rdataset.h +++ b/lib/dns/include/dns/rdataset.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdataset.h,v 1.67.186.2.48.2 2011/06/06 23:46:32 tbox Exp $ */ +/* $Id: rdataset.h,v 1.67.186.2.48.3 2011/06/21 20:14:48 each Exp $ */ #ifndef DNS_RDATASET_H #define DNS_RDATASET_H 1 @@ -203,6 +203,7 @@ struct dns_rdataset { #define DNS_RDATASETATTR_RESIGN 0x00040000 #define DNS_RDATASETATTR_CLOSEST 0x00080000 #define DNS_RDATASETATTR_OPTOUT 0x00100000 /*%< OPTOUT proof */ +#define DNS_RDATASETATTR_NEGATIVE 0x00200000 /*% * _OMITDNSSEC: diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c index 28a033c8424..6eeb9877105 100644 --- a/lib/dns/masterdump.c +++ b/lib/dns/masterdump.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: masterdump.c,v 1.99.334.2 2011/06/06 23:46:31 tbox Exp $ */ +/* $Id: masterdump.c,v 1.99.334.3 2011/06/21 20:14:46 each Exp $ */ /*! \file */ @@ -410,6 +410,7 @@ rdataset_totext(dns_rdataset_t *rdataset, isc_uint32_t current_ttl; isc_boolean_t current_ttl_valid; dns_rdatatype_t type; + unsigned int type_start; REQUIRE(DNS_RDATASET_VALID(rdataset)); @@ -491,29 +492,26 @@ rdataset_totext(dns_rdataset_t *rdataset, * Type. */ - if (rdataset->type == 0) { + if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { type = rdataset->covers; } else { type = rdataset->type; } - { - unsigned int type_start; - INDENT_TO(type_column); - type_start = target->used; - if (rdataset->type == 0) - RETERR(str_totext("\\-", target)); - result = dns_rdatatype_totext(type, target); - if (result != ISC_R_SUCCESS) - return (result); - column += (target->used - type_start); - } + INDENT_TO(type_column); + type_start = target->used; + if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) + RETERR(str_totext("\\-", target)); + result = dns_rdatatype_totext(type, target); + if (result != ISC_R_SUCCESS) + return (result); + column += (target->used - type_start); /* * Rdata. */ INDENT_TO(rdata_column); - if (rdataset->type == 0) { + if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { if (NXDOMAIN(rdataset)) RETERR(str_totext(";-$NXDOMAIN\n", target)); else @@ -876,7 +874,7 @@ dump_rdatasets_text(isc_mem_t *mctx, dns_name_t *name, if (ctx->style.flags & DNS_STYLEFLAG_TRUST) { fprintf(f, "; %s\n", dns_trust_totext(rds->trust)); } - if (rds->type == 0 && + if (((rds->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) && (ctx->style.flags & DNS_STYLEFLAG_NCACHE) == 0) { /* Omit negative cache entries */ } else { @@ -1041,7 +1039,7 @@ dump_rdatasets_raw(isc_mem_t *mctx, dns_name_t *name, dns_rdataset_init(&rdataset); dns_rdatasetiter_current(rdsiter, &rdataset); - if (rdataset.type == 0 && + if (((rdataset.attributes & DNS_RDATASETATTR_NEGATIVE) != 0) && (ctx->style.flags & DNS_STYLEFLAG_NCACHE) == 0) { /* Omit negative cache entries */ } else { diff --git a/lib/dns/message.c b/lib/dns/message.c index e2a43275da2..74fa8aeb2ac 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: message.c,v 1.249.10.4.36.2 2011/06/08 23:46:55 tbox Exp $ */ +/* $Id: message.c,v 1.249.10.4.36.3 2011/06/21 20:14:46 each Exp $ */ /*! \file */ @@ -2516,7 +2516,7 @@ dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp, isc_result_t dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) { - unsigned int first_section; + unsigned int clear_after; isc_result_t result; REQUIRE(DNS_MESSAGE_VALID(msg)); @@ -2528,15 +2528,15 @@ dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) { msg->opcode != dns_opcode_notify) want_question_section = ISC_FALSE; if (msg->opcode == dns_opcode_update) - first_section = DNS_SECTION_PREREQUISITE; + clear_after = DNS_SECTION_PREREQUISITE; else if (want_question_section) { if (!msg->question_ok) return (DNS_R_FORMERR); - first_section = DNS_SECTION_ANSWER; + clear_after = DNS_SECTION_ANSWER; } else - first_section = DNS_SECTION_QUESTION; + clear_after = DNS_SECTION_QUESTION; msg->from_to_wire = DNS_MESSAGE_INTENTRENDER; - msgresetnames(msg, first_section); + msgresetnames(msg, clear_after); msgresetopt(msg); msgresetsigs(msg, ISC_TRUE); msginitprivate(msg); diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c index 8a8b3b416af..c1b4386b8ed 100644 --- a/lib/dns/ncache.c +++ b/lib/dns/ncache.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ncache.c,v 1.43.268.7.46.2 2011/06/06 23:46:32 tbox Exp $ */ +/* $Id: ncache.c,v 1.43.268.7.46.3 2011/06/21 20:14:46 each Exp $ */ /*! \file */ @@ -294,6 +294,7 @@ dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache, RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset) == ISC_R_SUCCESS); ncrdataset.trust = trust; + ncrdataset.attributes |= DNS_RDATASETATTR_NEGATIVE; if (message->rcode == dns_rcode_nxdomain) ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN; if (optout) @@ -324,6 +325,7 @@ dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx, REQUIRE(rdataset != NULL); REQUIRE(rdataset->type == 0); + REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); savedbuffer = *target; count = 0; @@ -552,6 +554,7 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name, REQUIRE(ncacherdataset != NULL); REQUIRE(ncacherdataset->type == 0); + REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); REQUIRE(name != NULL); REQUIRE(!dns_rdataset_isassociated(rdataset)); REQUIRE(type != dns_rdatatype_rrsig); @@ -628,6 +631,7 @@ dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name, REQUIRE(ncacherdataset != NULL); REQUIRE(ncacherdataset->type == 0); + REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); REQUIRE(name != NULL); REQUIRE(!dns_rdataset_isassociated(rdataset)); @@ -727,6 +731,7 @@ dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found, REQUIRE(ncacherdataset != NULL); REQUIRE(ncacherdataset->type == 0); + REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0); REQUIRE(found != NULL); REQUIRE(!dns_rdataset_isassociated(rdataset)); diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c index 24326498a13..9dd96672886 100644 --- a/lib/dns/nsec3.c +++ b/lib/dns/nsec3.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsec3.c,v 1.13.6.6 2010/12/07 03:01:40 marka Exp $ */ +/* $Id: nsec3.c,v 1.13.6.6.12.1 2011/06/21 20:14:47 each Exp $ */ #include @@ -1579,7 +1579,7 @@ dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, isc_result_t dns_nsec3_delnsec3sx(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, - dns_rdatatype_t type, dns_diff_t *diff) + dns_rdatatype_t privatetype, dns_diff_t *diff) { dns_dbnode_t *node = NULL; dns_rdata_nsec3param_t nsec3param; @@ -1624,9 +1624,9 @@ dns_nsec3_delnsec3sx(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, dns_rdataset_disassociate(&rdataset); try_private: - if (type == 0) + if (privatetype == 0) goto success; - result = dns_db_findrdataset(db, node, version, type, 0, 0, + result = dns_db_findrdataset(db, node, version, privatetype, 0, 0, &rdataset, NULL); if (result == ISC_R_NOTFOUND) goto success; @@ -1681,7 +1681,7 @@ dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version, isc_result_t dns_nsec3_activex(dns_db_t *db, dns_dbversion_t *version, - isc_boolean_t complete, dns_rdatatype_t type, + isc_boolean_t complete, dns_rdatatype_t privatetype, isc_boolean_t *answer) { dns_dbnode_t *node = NULL; @@ -1730,11 +1730,11 @@ dns_nsec3_activex(dns_db_t *db, dns_dbversion_t *version, *answer = ISC_FALSE; try_private: - if (type == 0 || complete) { + if (privatetype == 0 || complete) { *answer = ISC_FALSE; return (ISC_R_SUCCESS); } - result = dns_db_findrdataset(db, node, version, type, 0, 0, + result = dns_db_findrdataset(db, node, version, privatetype, 0, 0, &rdataset, NULL); dns_db_detachnode(db, &node); diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 175a4ce156a..d28c82bd690 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbtdb.c,v 1.292.8.15 2010/12/02 05:07:03 marka Exp $ */ +/* $Id: rbtdb.c,v 1.292.8.15.10.1 2011/06/21 20:14:47 each Exp $ */ /*! \file */ @@ -278,6 +278,7 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t; #define RDATASET_ATTR_RESIGN 0x0020 #define RDATASET_ATTR_STATCOUNT 0x0040 #define RDATASET_ATTR_OPTOUT 0x0080 +#define RDATASET_ATTR_NEGATIVE 0x0100 typedef struct acache_cbarg { dns_rdatasetadditional_t type; @@ -316,6 +317,8 @@ struct acachectl { (((header)->attributes & RDATASET_ATTR_RESIGN) != 0) #define OPTOUT(header) \ (((header)->attributes & RDATASET_ATTR_OPTOUT) != 0) +#define NEGATIVE(header) \ + (((header)->attributes & RDATASET_ATTR_NEGATIVE) != 0) #define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */ @@ -691,11 +694,13 @@ update_rrsetstats(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, /* At the moment we count statistics only for cache DB */ INSIST(IS_CACHE(rbtdb)); - if (NXDOMAIN(header)) - statattributes = DNS_RDATASTATSTYPE_ATTR_NXDOMAIN; - else if (RBTDB_RDATATYPE_BASE(header->type) == 0) { - statattributes = DNS_RDATASTATSTYPE_ATTR_NXRRSET; - base = RBTDB_RDATATYPE_EXT(header->type); + if (NEGATIVE(header)) { + if (NXDOMAIN(header)) + statattributes = DNS_RDATASTATSTYPE_ATTR_NXDOMAIN; + else { + statattributes = DNS_RDATASTATSTYPE_ATTR_NXRRSET; + base = RBTDB_RDATATYPE_EXT(header->type); + } } else base = RBTDB_RDATATYPE_BASE(header->type); @@ -2748,6 +2753,8 @@ bind_rdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, rdataset->covers = RBTDB_RDATATYPE_EXT(header->type); rdataset->ttl = header->rdh_ttl - now; rdataset->trust = header->trust; + if (NEGATIVE(header)) + rdataset->attributes |= DNS_RDATASETATTR_NEGATIVE; if (NXDOMAIN(header)) rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN; if (OPTOUT(header)) @@ -4785,7 +4792,7 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, *nodep = node; } - if (RBTDB_RDATATYPE_BASE(found->type) == 0) { + if (NEGATIVE(found)) { /* * We found a negative cache entry. */ @@ -5454,7 +5461,7 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, if (found == NULL) return (ISC_R_NOTFOUND); - if (RBTDB_RDATATYPE_BASE(found->type) == 0) { + if (NEGATIVE(found)) { /* * We found a negative cache entry. */ @@ -5665,7 +5672,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, negtype = 0; if (rbtversion == NULL && !newheader_nx) { rdtype = RBTDB_RDATATYPE_BASE(newheader->type); - if (rdtype == 0) { + if (NEGATIVE(newheader)) { /* * We're adding a negative cache entry. */ @@ -6207,6 +6214,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, } else { newheader->serial = 1; newheader->resign = 0; + if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) + newheader->attributes |= RDATASET_ATTR_NEGATIVE; if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) newheader->attributes |= RDATASET_ATTR_NXDOMAIN; if ((rdataset->attributes & DNS_RDATASETATTR_OPTOUT) != 0) @@ -7899,7 +7908,7 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator) { type = header->type; rdtype = RBTDB_RDATATYPE_BASE(header->type); - if (rdtype == 0) { + if (NEGATIVE(header)) { covers = RBTDB_RDATATYPE_EXT(header->type); negtype = RBTDB_RDATATYPE_VALUE(covers, 0); } else diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c index ea2ac3a86e8..b1f6f37eb7e 100644 --- a/lib/dns/rdataset.c +++ b/lib/dns/rdataset.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdataset.c,v 1.84.186.2.48.2 2011/06/06 23:46:32 tbox Exp $ */ +/* $Id: rdataset.c,v 1.84.186.2.48.3 2011/06/21 20:14:47 each Exp $ */ /*! \file */ @@ -345,7 +345,7 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, count = 1; result = dns_rdataset_first(rdataset); INSIST(result == ISC_R_NOMORE); - } else if (rdataset->type == 0) { + } else if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { /* * This is a negative caching rdataset. */ diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 51bbad78a0c..7cb6027d710 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.413.14.15 2011/01/27 23:46:37 tbox Exp $ */ +/* $Id: resolver.c,v 1.413.14.15.12.1 2011/06/21 20:14:47 each Exp $ */ /*! \file */ @@ -426,6 +426,7 @@ struct dns_resolver { FCTX_ADDRINFO_TRIED) != 0) #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) +#define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) static void destroy(dns_resolver_t *res); static void empty_bucket(dns_resolver_t *res); @@ -1050,7 +1051,7 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) { * Negative results must be indicated in event->result. */ if (dns_rdataset_isassociated(event->rdataset) && - event->rdataset->type == dns_rdatatype_none) { + NEGATIVE(event->rdataset)) { INSIST(event->result == DNS_R_NCACHENXDOMAIN || event->result == DNS_R_NCACHENXRRSET); } @@ -4219,7 +4220,7 @@ validated(isc_task_t *task, isc_event_t *event) { if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) goto noanswer_response; - if (ardataset != NULL && ardataset->type == 0) { + if (ardataset != NULL && NEGATIVE(ardataset)) { if (NXDOMAIN(ardataset)) eresult = DNS_R_NCACHENXDOMAIN; else @@ -4540,7 +4541,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, result = ISC_R_SUCCESS; if (!need_validation && ardataset != NULL && - ardataset->type == 0) { + NEGATIVE(ardataset)) { /* * The answer in the cache is * better than the answer we @@ -4670,7 +4671,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, if (result == DNS_R_UNCHANGED) { if (ANSWER(rdataset) && ardataset != NULL && - ardataset->type == 0) { + NEGATIVE(ardataset)) { /* * The answer in the cache is better * than the answer we found, and is @@ -4700,7 +4701,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, * Negative results must be indicated in event->result. */ if (dns_rdataset_isassociated(event->rdataset) && - event->rdataset->type == dns_rdatatype_none) { + NEGATIVE(event->rdataset)) { INSIST(eresult == DNS_R_NCACHENXDOMAIN || eresult == DNS_R_NCACHENXRRSET); } @@ -4780,7 +4781,7 @@ ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, * care about whether it is DNS_R_NCACHENXDOMAIN or * DNS_R_NCACHENXRRSET then extract it. */ - if (ardataset->type == 0) { + if (NEGATIVE(ardataset)) { /* * The cache data is a negative cache entry. */ diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 8679a59a3fc..bb726615d93 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: validator.c,v 1.182.16.14.10.2 2011/06/06 23:46:32 tbox Exp $ */ +/* $Id: validator.c,v 1.182.16.14.10.3 2011/06/21 20:14:47 each Exp $ */ #include @@ -129,6 +129,8 @@ #define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0) #define CANCELED(v) (((v)->attributes & VALATTR_CANCELED) != 0) +#define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) + static void destroy(dns_validator_t *val); @@ -734,7 +736,7 @@ dsvalidated(isc_task_t *task, isc_event_t *event) { name = dns_fixedname_name(&val->fname); if ((val->attributes & VALATTR_INSECURITY) != 0 && val->frdataset.covers == dns_rdatatype_ds && - val->frdataset.type == 0 && + NEGATIVE(&val->frdataset) && isdelegation(name, &val->frdataset, DNS_R_NCACHENXRRSET)) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, @@ -3966,7 +3968,7 @@ validator_start(isc_task_t *task, isc_event_t *event) { val->attributes |= VALATTR_NEEDNODATA; result = nsecvalidate(val, ISC_FALSE); } else if (val->event->rdataset != NULL && - val->event->rdataset->type == 0) + NEGATIVE(val->event->rdataset)) { /* * This is a nonexistence validation.