aboutsummaryrefslogtreecommitdiff
path: root/share/security/patches/SA-10:01/bind9-64.patch
diff options
context:
space:
mode:
Diffstat (limited to 'share/security/patches/SA-10:01/bind9-64.patch')
-rw-r--r--share/security/patches/SA-10:01/bind9-64.patch317
1 files changed, 317 insertions, 0 deletions
diff --git a/share/security/patches/SA-10:01/bind9-64.patch b/share/security/patches/SA-10:01/bind9-64.patch
new file mode 100644
index 0000000000..3fe56e9374
--- /dev/null
+++ b/share/security/patches/SA-10:01/bind9-64.patch
@@ -0,0 +1,317 @@
+Index: contrib/bind9/lib/dns/rbtdb.c
+===================================================================
+--- contrib/bind9/lib/dns/rbtdb.c (revision 200669)
++++ contrib/bind9/lib/dns/rbtdb.c (working copy)
+@@ -2667,7 +2667,7 @@ cache_zonecut_callback(dns_rbtnode_t *node, dns_na
+ }
+
+ if (dname_header != NULL &&
+- (dname_header->trust != dns_trust_pending ||
++ (!DNS_TRUST_PENDING(dname_header->trust) ||
+ (search->options & DNS_DBFIND_PENDINGOK) != 0)) {
+ /*
+ * We increment the reference count on node to ensure that
+@@ -3129,7 +3129,7 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbv
+ if (found == NULL ||
+ (found->trust == dns_trust_glue &&
+ ((options & DNS_DBFIND_GLUEOK) == 0)) ||
+- (found->trust == dns_trust_pending &&
++ (DNS_TRUST_PENDING(found->trust) &&
+ ((options & DNS_DBFIND_PENDINGOK) == 0))) {
+ /*
+ * If there is an NS rdataset at this node, then this is the
+Index: contrib/bind9/lib/dns/include/dns/types.h
+===================================================================
+--- contrib/bind9/lib/dns/include/dns/types.h (revision 200669)
++++ contrib/bind9/lib/dns/include/dns/types.h (working copy)
+@@ -226,40 +226,51 @@ enum {
+ dns_trust_none = 0,
+ #define dns_trust_none ((dns_trust_t)dns_trust_none)
+
+- /* Subject to DNSSEC validation but has not yet been validated */
+- dns_trust_pending = 1,
+-#define dns_trust_pending ((dns_trust_t)dns_trust_pending)
++ /*%
++ * Subject to DNSSEC validation but has not yet been validated
++ * dns_trust_pending_additional (from the additional section).
++ */
++ dns_trust_pending_additional = 1,
++#define dns_trust_pending_additional \
++ ((dns_trust_t)dns_trust_pending_additional)
+
+- /* Received in the additional section of a response. */
+- dns_trust_additional = 2,
++ dns_trust_pending_answer = 2,
++#define dns_trust_pending_answer ((dns_trust_t)dns_trust_pending_answer)
++
++ /*% Received in the additional section of a response. */
++ dns_trust_additional = 3,
+ #define dns_trust_additional ((dns_trust_t)dns_trust_additional)
+
+- /* Received in a referral response. */
+- dns_trust_glue = 3,
++ /* Received in a referral response. */
++ dns_trust_glue = 4,
+ #define dns_trust_glue ((dns_trust_t)dns_trust_glue)
+
+- /* Answser from a non-authoritative server */
+- dns_trust_answer = 4,
++ /* Answer from a non-authoritative server */
++ dns_trust_answer = 5,
+ #define dns_trust_answer ((dns_trust_t)dns_trust_answer)
+
+ /* Received in the authority section as part of an
+ authoritative response */
+- dns_trust_authauthority = 5,
++ dns_trust_authauthority = 6,
+ #define dns_trust_authauthority ((dns_trust_t)dns_trust_authauthority)
+
+- /* Answser from an authoritative server */
+- dns_trust_authanswer = 6,
++ /* Answer from an authoritative server */
++ dns_trust_authanswer = 7,
+ #define dns_trust_authanswer ((dns_trust_t)dns_trust_authanswer)
+
+- /* Successfully DNSSEC validated */
+- dns_trust_secure = 7,
++ /* Successfully DNSSEC validated */
++ dns_trust_secure = 8,
+ #define dns_trust_secure ((dns_trust_t)dns_trust_secure)
+
+ /* This server is authoritative */
+- dns_trust_ultimate = 8
++ dns_trust_ultimate = 9
+ #define dns_trust_ultimate ((dns_trust_t)dns_trust_ultimate)
+ };
+
++#define DNS_TRUST_PENDING(x) ((x) == dns_trust_pending_answer || \
++ (x) == dns_trust_pending_additional)
++#define DNS_TRUST_GLUE(x) ((x) == dns_trust_glue)
++
+ /*
+ * Name checking severites.
+ */
+Index: contrib/bind9/lib/dns/resolver.c
+===================================================================
+--- contrib/bind9/lib/dns/resolver.c (revision 200669)
++++ contrib/bind9/lib/dns/resolver.c (working copy)
+@@ -3657,6 +3657,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns
+ * for it, unless it is glue.
+ */
+ if (secure_domain && rdataset->trust != dns_trust_glue) {
++ dns_trust_t trust;
+ /*
+ * RRSIGs are validated as part of validating the
+ * type they cover.
+@@ -3693,12 +3694,34 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns
+ }
+
+ /*
++ * Reject out of bailiwick additional records
++ * without RRSIGs as they can't possibly validate
++ * as "secure" and as we will never never want to
++ * store these as "answers" after validation.
++ */
++ if (rdataset->trust == dns_trust_additional &&
++ sigrdataset == NULL && EXTERNAL(rdataset))
++ continue;
++
++ /*
++ * XXXMPA: If we store as "answer" after validating
++ * then we need to do bailiwick processing and
++ * also need to track whether RRsets are in or
++ * out of bailiwick. This will require a another
++ * pending trust level.
++ *
+ * Cache this rdataset/sigrdataset pair as
+- * pending data.
++ * pending data. Track whether it was additional
++ * or not.
+ */
+- rdataset->trust = dns_trust_pending;
++ if (rdataset->trust == dns_trust_additional)
++ trust = dns_trust_pending_additional;
++ else
++ trust = dns_trust_pending_answer;
++
++ rdataset->trust = trust;
+ if (sigrdataset != NULL)
+- sigrdataset->trust = dns_trust_pending;
++ sigrdataset->trust = trust;
+ if (!need_validation)
+ addedrdataset = ardataset;
+ else
+@@ -4044,7 +4067,7 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t
+ for (trdataset = ISC_LIST_HEAD(tname->list);
+ trdataset != NULL;
+ trdataset = ISC_LIST_NEXT(trdataset, link))
+- trdataset->trust = dns_trust_pending;
++ trdataset->trust = dns_trust_pending_answer;
+ result = dns_message_nextname(fctx->rmessage,
+ DNS_SECTION_AUTHORITY);
+ }
+Index: contrib/bind9/lib/dns/masterdump.c
+===================================================================
+--- contrib/bind9/lib/dns/masterdump.c (revision 200669)
++++ contrib/bind9/lib/dns/masterdump.c (working copy)
+@@ -763,7 +763,8 @@ dump_order_compare(const void *a, const void *b) {
+
+ static const char *trustnames[] = {
+ "none",
+- "pending",
++ "pending-additional",
++ "pending-answer",
+ "additional",
+ "glue",
+ "answer",
+Index: contrib/bind9/lib/dns/validator.c
+===================================================================
+--- contrib/bind9/lib/dns/validator.c (revision 200669)
++++ contrib/bind9/lib/dns/validator.c (working copy)
+@@ -238,7 +238,7 @@ auth_nonpending(dns_message_t *message) {
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+- if (rdataset->trust == dns_trust_pending)
++ if (DNS_TRUST_PENDING(rdataset->trust))
+ rdataset->trust = dns_trust_authauthority;
+ }
+ }
+@@ -1175,7 +1175,7 @@ get_key(dns_validator_t *val, dns_rdata_rrsig_t *s
+ * We have an rrset for the given keyname.
+ */
+ val->keyset = &val->frdataset;
+- if (val->frdataset.trust == dns_trust_pending &&
++ if (DNS_TRUST_PENDING(val->frdataset.trust) &&
+ dns_rdataset_isassociated(&val->fsigrdataset))
+ {
+ /*
+@@ -1190,7 +1190,7 @@ get_key(dns_validator_t *val, dns_rdata_rrsig_t *s
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (DNS_R_WAIT);
+- } else if (val->frdataset.trust == dns_trust_pending) {
++ } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
+ /*
+ * Having a pending key with no signature means that
+ * something is broken.
+@@ -1758,7 +1758,7 @@ validatezonekey(dns_validator_t *val) {
+ * We have DS records.
+ */
+ val->dsset = &val->frdataset;
+- if (val->frdataset.trust == dns_trust_pending &&
++ if (DNS_TRUST_PENDING(val->frdataset.trust) &&
+ dns_rdataset_isassociated(&val->fsigrdataset))
+ {
+ result = create_validator(val,
+@@ -1771,7 +1771,7 @@ validatezonekey(dns_validator_t *val) {
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (DNS_R_WAIT);
+- } else if (val->frdataset.trust == dns_trust_pending) {
++ } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
+ /*
+ * There should never be an unsigned DS.
+ */
+@@ -2564,7 +2564,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t
+ * There is no DS. If this is a delegation,
+ * we maybe done.
+ */
+- if (val->frdataset.trust == dns_trust_pending) {
++ if (DNS_TRUST_PENDING(val->frdataset.trust)) {
+ result = create_fetch(val, tname,
+ dns_rdatatype_ds,
+ dsfetched2,
+Index: contrib/bind9/bin/named/query.c
+===================================================================
+--- contrib/bind9/bin/named/query.c (revision 200669)
++++ contrib/bind9/bin/named/query.c (working copy)
+@@ -92,6 +92,8 @@
+ #define DNS_GETDB_NOLOG 0x02U
+ #define DNS_GETDB_PARTIAL 0x04U
+
++#define PENDINGOK(x) (((x) & DNS_DBFIND_PENDINGOK) != 0)
++
+ static void
+ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype);
+
+@@ -1698,14 +1700,14 @@ query_addbestns(ns_client_t *client) {
+ zsigrdataset = NULL;
+ }
+
+- if ((client->query.dboptions & DNS_DBFIND_PENDINGOK) == 0 &&
+- (rdataset->trust == dns_trust_pending ||
+- (sigrdataset != NULL && sigrdataset->trust == dns_trust_pending)))
++ if ((DNS_TRUST_PENDING(rdataset->trust) ||
++ (sigrdataset != NULL && DNS_TRUST_PENDING(sigrdataset->trust))) &&
++ !PENDINGOK(client->query.dboptions))
+ goto cleanup;
+
+- if (WANTDNSSEC(client) && SECURE(client) &&
+- (rdataset->trust == dns_trust_glue ||
+- (sigrdataset != NULL && sigrdataset->trust == dns_trust_glue)))
++ if ((DNS_TRUST_GLUE(rdataset->trust) ||
++ (sigrdataset != NULL && DNS_TRUST_GLUE(sigrdataset->trust))) &&
++ SECURE(client) && WANTDNSSEC(client))
+ goto cleanup;
+
+ query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
+@@ -2367,6 +2369,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *
+ unsigned int options;
+ isc_boolean_t empty_wild;
+ dns_rdataset_t *noqname;
++ dns_rdataset_t tmprdataset;
++ unsigned int dboptions;
+
+ CTRACE("query_find");
+
+@@ -2566,9 +2570,47 @@ query_find(ns_client_t *client, dns_fetchevent_t *
+ /*
+ * Now look for an answer in the database.
+ */
++ dboptions = client->query.dboptions;
++ if (sigrdataset == NULL && client->view->enablednssec) {
++ /*
++ * If the client doesn't want DNSSEC we still want to
++ * look for any data pending validation to save a remote
++ * lookup if possible.
++ */
++ dns_rdataset_init(&tmprdataset);
++ sigrdataset = &tmprdataset;
++ dboptions |= DNS_DBFIND_PENDINGOK;
++ }
++ refind:
+ result = dns_db_find(db, client->query.qname, version, type,
+- client->query.dboptions, client->now,
+- &node, fname, rdataset, sigrdataset);
++ dboptions, client->now, &node, fname,
++ rdataset, sigrdataset);
++ /*
++ * If we have found pending data try to validate it.
++ * If the data does not validate as secure and we can't
++ * use the unvalidated data requery the database with
++ * pending disabled to prevent infinite looping.
++ */
++ if (result != ISC_R_SUCCESS || !DNS_TRUST_PENDING(rdataset->trust))
++ goto validation_done;
++ if (rdataset->trust != dns_trust_pending_answer ||
++ !PENDINGOK(client->query.dboptions)) {
++ dns_rdataset_disassociate(rdataset);
++ if (sigrdataset != NULL &&
++ dns_rdataset_isassociated(sigrdataset))
++ dns_rdataset_disassociate(sigrdataset);
++ if (sigrdataset == &tmprdataset)
++ sigrdataset = NULL;
++ dns_db_detachnode(db, &node);
++ dboptions &= ~DNS_DBFIND_PENDINGOK;
++ goto refind;
++ }
++ validation_done:
++ if (sigrdataset == &tmprdataset) {
++ if (dns_rdataset_isassociated(sigrdataset))
++ dns_rdataset_disassociate(sigrdataset);
++ sigrdataset = NULL;
++ }
+
+ resume:
+ CTRACE("query_find: resume");