Description: <short summary of the patch>
 TODO: Put a short summary on the line above and replace this paragraph
 with a longer explanation of this change. Complete the meta-information
 with other relevant fields (see below for details). To make it easier, the
 information below has been extracted from the changelog. Adjust it or drop
 it.
 .
 unbound (1.4.22-3+deb8u3) jessie; urgency=high
 .
   * Cherry-pick upstream commit svn r4301, "Fix install of trust anchor
     when two anchors are present, makes both valid.  Checks hash of DS but
     not signature of new key.  This fixes installs between sep11 and oct11
     2017."
   * Cherry-pick upstream commit svn r4000, "Include root trust anchor id
     20326 in unbound-anchor".
Author: Robert Edmonds <edmonds@debian.org>

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: https://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: 2017-08-28

--- unbound-1.4.22.orig/acx_python.m4
+++ unbound-1.4.22/acx_python.m4
@@ -90,7 +90,12 @@ $ac_distutils_result])
                 if test -n "${python_path}"; then
                         python_path="-I$python_path"
                 fi
-                PYTHON_CPPFLAGS=$python_path
+                python_multiarch_path=`$PYTHON -c "import distutils.sysconfig; \
+                        print distutils.sysconfig.get_python_inc(plat_specific=1);"`
+                if test -n "${python_multiarch_path}"; then
+                        python_multiarch_path="-I$python_multiarch_path"
+                fi
+                PYTHON_CPPFLAGS="$python_path $python_multiarch_path"
         fi
         AC_MSG_RESULT([$PYTHON_CPPFLAGS])
         AC_SUBST([PYTHON_CPPFLAGS])
--- unbound-1.4.22.orig/daemon/unbound.c
+++ unbound-1.4.22/daemon/unbound.c
@@ -280,8 +280,6 @@ checkrlimits(struct config_file* cfg)
 				"ports in config to remove this warning");
 			return;
 		}
-		log_warn("increased limit(open files) from %u to %u",
-			(unsigned)avail, (unsigned)total+10);
 	}
 #else	
 	(void)cfg;
--- unbound-1.4.22.orig/doc/unbound.conf.5.in
+++ unbound-1.4.22/doc/unbound.conf.5.in
@@ -948,7 +948,7 @@ section for options.  To setup the corre
 \fIunbound\-control\-setup\fR(8) utility.
 .TP 5
 .B control\-enable:     \fI<yes or no>
-The option is used to enable remote control, default is "no".
+The option is used to enable remote control, default is "yes".
 If turned off, the server does not listen for control commands.
 .TP 5
 .B control\-interface: <ip address>
--- unbound-1.4.22.orig/iterator/iter_hints.c
+++ unbound-1.4.22/iterator/iter_hints.c
@@ -135,7 +135,7 @@ compile_time_root_prime(int do_ip4, int
 	if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) goto failed;
 	if(!ah(dp, "F.ROOT-SERVERS.NET.", "192.5.5.241"))	goto failed;
 	if(!ah(dp, "G.ROOT-SERVERS.NET.", "192.112.36.4"))	goto failed;
-	if(!ah(dp, "H.ROOT-SERVERS.NET.", "128.63.2.53"))	goto failed;
+	if(!ah(dp, "H.ROOT-SERVERS.NET.", "198.97.190.53"))	goto failed;
 	if(!ah(dp, "I.ROOT-SERVERS.NET.", "192.36.148.17"))	goto failed;
 	if(!ah(dp, "J.ROOT-SERVERS.NET.", "192.58.128.30"))	goto failed;
 	if(!ah(dp, "K.ROOT-SERVERS.NET.", "193.0.14.129"))	goto failed;
@@ -146,7 +146,7 @@ compile_time_root_prime(int do_ip4, int
 	if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) goto failed;
 	if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
 	if(!ah(dp, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) goto failed;
-	if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::803f:235")) goto failed;
+	if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::53")) goto failed;
 	if(!ah(dp, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) goto failed;
 	if(!ah(dp, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) goto failed;
 	if(!ah(dp, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) goto failed;
--- unbound-1.4.22.orig/iterator/iterator.c
+++ unbound-1.4.22/iterator/iterator.c
@@ -120,6 +120,7 @@ iter_new(struct module_qstate* qstate, i
 	iq->query_restart_count = 0;
 	iq->referral_count = 0;
 	iq->sent_count = 0;
+	iq->target_count = NULL;
 	iq->wait_priming_stub = 0;
 	iq->refetch_glue = 0;
 	iq->dnssec_expected = 0;
@@ -445,6 +446,26 @@ handle_cname_response(struct module_qsta
 	return 1;
 }
 
+/** create target count structure for this query */
+static void
+target_count_create(struct iter_qstate* iq)
+{
+	if(!iq->target_count) {
+		iq->target_count = (int*)calloc(2, sizeof(int));
+		/* if calloc fails we simply do not track this number */
+		if(iq->target_count)
+			iq->target_count[0] = 1;
+	}
+}
+
+static void
+target_count_increase(struct iter_qstate* iq, int num)
+{
+	target_count_create(iq);
+	if(iq->target_count)
+		iq->target_count[1] += num;
+}
+
 /**
  * Generate a subrequest.
  * Generate a local request event. Local events are tied to this module, and
@@ -516,6 +537,10 @@ generate_sub_request(uint8_t* qname, siz
 		subiq = (struct iter_qstate*)subq->minfo[id];
 		memset(subiq, 0, sizeof(*subiq));
 		subiq->num_target_queries = 0;
+		target_count_create(iq);
+		subiq->target_count = iq->target_count;
+		if(iq->target_count)
+			iq->target_count[0] ++; /* extra reference */
 		subiq->num_current_queries = 0;
 		subiq->depth = iq->depth+1;
 		outbound_list_init(&subiq->outlist);
@@ -1342,6 +1367,12 @@ query_for_targets(struct module_qstate*
 
 	if(iq->depth == ie->max_dependency_depth)
 		return 0;
+	if(iq->depth > 0 && iq->target_count &&
+		iq->target_count[1] > MAX_TARGET_COUNT) {
+		verbose(VERB_QUERY, "request has exceeded the maximum "
+			"number of glue fetches %d", iq->target_count[1]);
+		return 0;
+	}
 
 	iter_mark_cycle_targets(qstate, iq->dp);
 	missing = (int)delegpt_count_missing_targets(iq->dp);
@@ -1524,6 +1555,7 @@ processLastResort(struct module_qstate*
 			return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
 		}
 		iq->num_target_queries += qs;
+		target_count_increase(iq, qs);
 		if(qs != 0) {
 			qstate->ext_state[id] = module_wait_subquery;
 			return 0; /* and wait for them */
@@ -1533,6 +1565,12 @@ processLastResort(struct module_qstate*
 		verbose(VERB_QUERY, "maxdepth and need more nameservers, fail");
 		return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
 	}
+	if(iq->depth > 0 && iq->target_count &&
+		iq->target_count[1] > MAX_TARGET_COUNT) {
+		verbose(VERB_QUERY, "request has exceeded the maximum "
+			"number of glue fetches %d", iq->target_count[1]);
+		return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
+	}
 	/* mark cycle targets for parent-side lookups */
 	iter_mark_pside_cycle_targets(qstate, iq->dp);
 	/* see if we can issue queries to get nameserver addresses */
@@ -1562,6 +1600,7 @@ processLastResort(struct module_qstate*
 		if(query_count != 0) { /* suspend to await results */
 			verbose(VERB_ALGO, "try parent-side glue lookup");
 			iq->num_target_queries += query_count;
+			target_count_increase(iq, query_count);
 			qstate->ext_state[id] = module_wait_subquery;
 			return 0;
 		}
@@ -1717,6 +1756,7 @@ processQueryTargets(struct module_qstate
 			return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
 		}
 		iq->num_target_queries += extra;
+		target_count_increase(iq, extra);
 		if(iq->num_target_queries > 0) {
 			/* wait to get all targets, we want to try em */
 			verbose(VERB_ALGO, "wait for all targets for fallback");
@@ -1757,6 +1797,7 @@ processQueryTargets(struct module_qstate
 		/* errors ignored, these targets are not strictly necessary for
 		 * this result, we do not have to reply with SERVFAIL */
 		iq->num_target_queries += extra;
+		target_count_increase(iq, extra);
 	}
 
 	/* Add the current set of unused targets to our queue. */
@@ -1802,6 +1843,7 @@ processQueryTargets(struct module_qstate
 					return 1;
 				}
 				iq->num_target_queries += qs;
+				target_count_increase(iq, qs);
 			}
 			/* Since a target query might have been made, we 
 			 * need to check again. */
@@ -2894,6 +2936,8 @@ iter_clear(struct module_qstate* qstate,
 	iq = (struct iter_qstate*)qstate->minfo[id];
 	if(iq) {
 		outbound_list_clear(&iq->outlist);
+		if(iq->target_count && --iq->target_count[0] == 0)
+			free(iq->target_count);
 		iq->num_current_queries = 0;
 	}
 	qstate->minfo[id] = NULL;
--- unbound-1.4.22.orig/iterator/iterator.h
+++ unbound-1.4.22/iterator/iterator.h
@@ -52,6 +52,8 @@ struct iter_donotq;
 struct iter_prep_list;
 struct iter_priv;
 
+/** max number of targets spawned for a query and its subqueries */
+#define MAX_TARGET_COUNT	32
 /** max number of query restarts. Determines max number of CNAME chain. */
 #define MAX_RESTART_COUNT       8
 /** max number of referrals. Makes sure resolver does not run away */
@@ -254,6 +256,10 @@ struct iter_qstate {
 
 	/** number of queries fired off */
 	int sent_count;
+	
+	/** number of target queries spawned in [1], for this query and its
+	 * subqueries, the malloced-array is shared, [0] refcount. */
+	int* target_count;
 
 	/**
 	 * The query must store NS records from referrals as parentside RRs
--- unbound-1.4.22.orig/smallapp/unbound-anchor.c
+++ unbound-1.4.22/smallapp/unbound-anchor.c
@@ -239,7 +239,10 @@ static const char*
 get_builtin_ds(void)
 {
 	return
-". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n";
+/* anchor 19036 is from 2010 */
+/* anchor 20326 is from 2017 */
+". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n"
+". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D\n";
 }
 
 /** print hex data */
--- unbound-1.4.22.orig/smallapp/unbound-control-setup.sh
+++ unbound-1.4.22/smallapp/unbound-control-setup.sh
@@ -157,6 +157,6 @@ chmod o-rw $SVR_BASE.pem $SVR_BASE.key $
 rm -f request.cfg
 rm -f $CTL_BASE"_trust.pem" $SVR_BASE"_trust.pem" $SVR_BASE"_trust.srl"
 
-echo "Setup success. Certificates created. Enable in unbound.conf file to use"
+echo "Setup success. Certificates created."
 
 exit 0
--- unbound-1.4.22.orig/util/config_file.c
+++ unbound-1.4.22/util/config_file.c
@@ -144,7 +144,7 @@ config_create(void)
 	init_outgoing_availports(cfg->outgoing_avail_ports, 65536);
 	if(!(cfg->username = strdup(UB_USERNAME))) goto error_exit;
 #ifdef HAVE_CHROOT
-	if(!(cfg->chrootdir = strdup(CHROOT_DIR))) goto error_exit;
+	if(!(cfg->chrootdir = strdup(""))) goto error_exit;
 #endif
 	if(!(cfg->directory = strdup(RUN_DIR))) goto error_exit;
 	if(!(cfg->logfile = strdup(""))) goto error_exit;
@@ -204,7 +204,7 @@ config_create(void)
 	cfg->local_zones_nodefault = NULL;
 	cfg->local_data = NULL;
 	cfg->python_script = NULL;
-	cfg->remote_control_enable = 0;
+	cfg->remote_control_enable = 1;
 	cfg->control_ifs = NULL;
 	cfg->control_port = UNBOUND_CONTROL_PORT;
 	cfg->minimal_responses = 0;
--- unbound-1.4.22.orig/validator/autotrust.c
+++ unbound-1.4.22/validator/autotrust.c
@@ -1557,6 +1557,11 @@ key_matches_a_ds(struct module_env* env,
 			verbose(VERB_ALGO, "DS match attempt failed");
 			continue;
 		}
+		/* match of hash is sufficient for bootstrap of trust point */
+		(void)reason;
+		(void)ve;
+		return 1;
+		/* no need to check RRSIG, DS hash already matched with source
 		if(dnskey_verify_rrset(env, ve, dnskey_rrset, 
 			dnskey_rrset, key_idx, &reason) == sec_status_secure) {
 			return 1;
@@ -1564,6 +1569,7 @@ key_matches_a_ds(struct module_env* env,
 			verbose(VERB_ALGO, "DS match failed because the key "
 				"does not verify the keyset: %s", reason);
 		}
+		*/
 	}
 	return 0;
 }
