Blame SOURCES/unbound-1.7.3-anchor-fallback.patch

8ba890
From 81e9f82a8ddd811d7ebafe2fd0ee5af836d0b405 Mon Sep 17 00:00:00 2001
8ba890
From: Wouter Wijngaards <wouter@nlnetlabs.nl>
8ba890
Date: Wed, 4 Jul 2018 10:02:16 +0000
8ba890
Subject: [PATCH] - Fix #4112: Fix that unbound-anchor -f /etc/resolv.conf will
8ba890
 not pass   if DNSSEC is not enabled.  New option -R allows fallback from  
8ba890
 resolv.conf to direct queries.
8ba890
8ba890
git-svn-id: file:///svn/unbound/trunk@4770 be551aaa-1e26-0410-a405-d3ace91eadb9
8ba890
---
8ba890
 doc/unbound-anchor.8.in   |  5 ++++
8ba890
 smallapp/unbound-anchor.c | 66 ++++++++++++++++++++++++++++++++++-------------
8ba890
 2 files changed, 53 insertions(+), 18 deletions(-)
8ba890
8ba890
diff --git a/doc/unbound-anchor.8.in b/doc/unbound-anchor.8.in
8ba890
index 02a3e781..e114eb25 100644
8ba890
--- a/doc/unbound-anchor.8.in
8ba890
+++ b/doc/unbound-anchor.8.in
8ba890
@@ -109,6 +109,11 @@ It does so, because the tool when used for bootstrapping the recursive
8ba890
 resolver, cannot use that recursive resolver itself because it is bootstrapping
8ba890
 that server.
8ba890
 .TP
8ba890
+.B \-R
8ba890
+Allow fallback from \-f resolv.conf file to direct root servers query.
8ba890
+It allows you to prefer local resolvers, but fallback automatically
8ba890
+to direct root query if they do not respond or do not support DNSSEC.
8ba890
+.TP
8ba890
 .B \-v
8ba890
 More verbose. Once prints informational messages, multiple times may enable
8ba890
 large debug amounts (such as full certificates or byte\-dumps of downloaded
8ba890
diff --git a/smallapp/unbound-anchor.c b/smallapp/unbound-anchor.c
8ba890
index b3009108..f3985090 100644
8ba890
--- a/smallapp/unbound-anchor.c
8ba890
+++ b/smallapp/unbound-anchor.c
8ba890
@@ -192,9 +192,10 @@ usage(void)
8ba890
 	printf("-n name		signer's subject emailAddress, default %s\n", P7SIGNER);
8ba890
 	printf("-4		work using IPv4 only\n");
8ba890
 	printf("-6		work using IPv6 only\n");
8ba890
-	printf("-f resolv.conf	use given resolv.conf to resolve -u name\n");
8ba890
-	printf("-r root.hints	use given root.hints to resolve -u name\n"
8ba890
+	printf("-f resolv.conf	use given resolv.conf\n");
8ba890
+	printf("-r root.hints	use given root.hints\n"
8ba890
 		"		builtin root hints are used by default\n");
8ba890
+	printf("-R		fallback from -f to root query on error\n");
8ba890
 	printf("-v		more verbose\n");
8ba890
 	printf("-C conf		debug, read config\n");
8ba890
 	printf("-P port		use port for https connect, default 443\n");
8ba890
@@ -1920,8 +1921,7 @@ static int
8ba890
 do_certupdate(const char* root_anchor_file, const char* root_cert_file,
8ba890
 	const char* urlname, const char* xmlname, const char* p7sname,
8ba890
 	const char* p7signer, const char* res_conf, const char* root_hints,
8ba890
-	const char* debugconf, int ip4only, int ip6only, int port,
8ba890
-	struct ub_result* dnskey)
8ba890
+	const char* debugconf, int ip4only, int ip6only, int port)
8ba890
 {
8ba890
 	STACK_OF(X509)* cert;
8ba890
 	BIO *xml, *p7s;
8ba890
@@ -1961,7 +1961,6 @@ do_certupdate(const char* root_anchor_file, const char* root_cert_file,
8ba890
 #ifndef S_SPLINT_S
8ba890
 	sk_X509_pop_free(cert, X509_free);
8ba890
 #endif
8ba890
-	ub_resolve_free(dnskey);
8ba890
 	ip_list_free(ip_list);
8ba890
 	return 1;
8ba890
 }
8ba890
@@ -2199,16 +2198,33 @@ probe_date_allows_certupdate(const char* root_anchor_file)
8ba890
 	return 0;
8ba890
 }
8ba890
 
8ba890
+static struct ub_result *
8ba890
+fetch_root_key(const char* root_anchor_file, const char* res_conf,
8ba890
+	const char* root_hints, const char* debugconf,
8ba890
+	int ip4only, int ip6only)
8ba890
+{
8ba890
+	struct ub_ctx* ctx;
8ba890
+	struct ub_result* dnskey;
8ba890
+
8ba890
+	ctx = create_unbound_context(res_conf, root_hints, debugconf,
8ba890
+		ip4only, ip6only);
8ba890
+	add_5011_probe_root(ctx, root_anchor_file);
8ba890
+	dnskey = prime_root_key(ctx);
8ba890
+	ub_ctx_delete(ctx);
8ba890
+	return dnskey;
8ba890
+}
8ba890
+
8ba890
 /** perform the unbound-anchor work */
8ba890
 static int
8ba890
 do_root_update_work(const char* root_anchor_file, const char* root_cert_file,
8ba890
 	const char* urlname, const char* xmlname, const char* p7sname,
8ba890
 	const char* p7signer, const char* res_conf, const char* root_hints,
8ba890
-	const char* debugconf, int ip4only, int ip6only, int force, int port)
8ba890
+	const char* debugconf, int ip4only, int ip6only, int force,
8ba890
+	int res_conf_fallback, int port)
8ba890
 {
8ba890
-	struct ub_ctx* ctx;
8ba890
 	struct ub_result* dnskey;
8ba890
 	int used_builtin = 0;
8ba890
+	int rcode;
8ba890
 
8ba890
 	/* see if builtin rootanchor needs to be provided, or if
8ba890
 	 * rootanchor is 'revoked-trust-point' */
8ba890
@@ -2217,12 +2233,22 @@ do_root_update_work(const char* root_anchor_file, const char* root_cert_file,
8ba890
 
8ba890
 	/* make unbound context with 5011-probe for root anchor,
8ba890
 	 * and probe . DNSKEY */
8ba890
-	ctx = create_unbound_context(res_conf, root_hints, debugconf,
8ba890
-		ip4only, ip6only);
8ba890
-	add_5011_probe_root(ctx, root_anchor_file);
8ba890
-	dnskey = prime_root_key(ctx);
8ba890
-	ub_ctx_delete(ctx);
8ba890
-	
8ba890
+	dnskey = fetch_root_key(root_anchor_file, res_conf,
8ba890
+		root_hints, debugconf, ip4only, ip6only);
8ba890
+	rcode = dnskey->rcode;
8ba890
+
8ba890
+	if (res_conf_fallback && res_conf && !dnskey->secure) {
8ba890
+		if (verb) printf("%s failed, retrying direct\n", res_conf);
8ba890
+		ub_resolve_free(dnskey);
8ba890
+		/* try direct query without res_conf */
8ba890
+		dnskey = fetch_root_key(root_anchor_file, NULL,
8ba890
+			root_hints, debugconf, ip4only, ip6only);
8ba890
+		if (rcode != 0 && dnskey->rcode == 0) {
8ba890
+			res_conf = NULL;
8ba890
+			rcode = 0;
8ba890
+		}
8ba890
+	}
8ba890
+
8ba890
 	/* if secure: exit */
8ba890
 	if(dnskey->secure && !force) {
8ba890
 		if(verb) printf("success: the anchor is ok\n");
8ba890
@@ -2230,18 +2256,18 @@ do_root_update_work(const char* root_anchor_file, const char* root_cert_file,
8ba890
 		return used_builtin;
8ba890
 	}
8ba890
 	if(force && verb) printf("debug cert update forced\n");
8ba890
+	ub_resolve_free(dnskey);
8ba890
 
8ba890
 	/* if not (and NOERROR): check date and do certupdate */
8ba890
-	if((dnskey->rcode == 0 &&
8ba890
+	if((rcode == 0 &&
8ba890
 		probe_date_allows_certupdate(root_anchor_file)) || force) {
8ba890
 		if(do_certupdate(root_anchor_file, root_cert_file, urlname,
8ba890
 			xmlname, p7sname, p7signer, res_conf, root_hints,
8ba890
-			debugconf, ip4only, ip6only, port, dnskey))
8ba890
+			debugconf, ip4only, ip6only, port))
8ba890
 			return 1;
8ba890
 		return used_builtin;
8ba890
 	}
8ba890
 	if(verb) printf("fail: the anchor is NOT ok and could not be fixed\n");
8ba890
-	ub_resolve_free(dnskey);
8ba890
 	return used_builtin;
8ba890
 }
8ba890
 
8ba890
@@ -2264,8 +2290,9 @@ int main(int argc, char* argv[])
8ba890
 	const char* root_hints = NULL;
8ba890
 	const char* debugconf = NULL;
8ba890
 	int dolist=0, ip4only=0, ip6only=0, force=0, port = HTTPS_PORT;
8ba890
+	int res_conf_fallback = 0;
8ba890
 	/* parse the options */
8ba890
-	while( (c=getopt(argc, argv, "46C:FP:a:c:f:hln:r:s:u:vx:")) != -1) {
8ba890
+	while( (c=getopt(argc, argv, "46C:FRP:a:c:f:hln:r:s:u:vx:")) != -1) {
8ba890
 		switch(c) {
8ba890
 		case 'l':
8ba890
 			dolist = 1;
8ba890
@@ -2300,6 +2327,9 @@ int main(int argc, char* argv[])
8ba890
 		case 'r':
8ba890
 			root_hints = optarg;
8ba890
 			break;
8ba890
+		case 'R':
8ba890
+			res_conf_fallback = 1;
8ba890
+			break;
8ba890
 		case 'C':
8ba890
 			debugconf = optarg;
8ba890
 			break;
8ba890
@@ -2346,5 +2376,5 @@ int main(int argc, char* argv[])
8ba890
 
8ba890
 	return do_root_update_work(root_anchor_file, root_cert_file, urlname,
8ba890
 		xmlname, p7sname, p7signer, res_conf, root_hints, debugconf,
8ba890
-		ip4only, ip6only, force, port);
8ba890
+		ip4only, ip6only, force, res_conf_fallback, port);
8ba890
 }
8ba890
-- 
8ba890
2.14.4
8ba890