]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix queries for nameservers under a stub leaking to the internet.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 12 May 2017 15:10:10 +0000 (15:10 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 12 May 2017 15:10:10 +0000 (15:10 +0000)
git-svn-id: file:///svn/unbound/trunk@4154 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
iterator/iterator.c
testdata/iter_stub_leak.rpl

index 004e76f7787dafe7c75a3626db84dc078f3340b0..48700a4c3840d6423c0b7d5d8c9c6b43f7af4de6 100644 (file)
@@ -1,6 +1,7 @@
 12 May 2017: Wouter
        - Adjust servfail by iterator to not store in cache when serve-expired
          is enabled, to avoid overwriting useful information there.
+       - Fix queries for nameservers under a stub leaking to the internet.
 
 9 May 2017: Ralph
        - Add 'c' to getopt() in testbound.
index 55916d726a32f44dcf29dc576e01e4a07775986d..a57fa3b65386762013e8126994ab5d1748c7078e 100644 (file)
@@ -1576,28 +1576,26 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
 
 /** see if last resort is possible - does config allow queries to parent */
 static int
-can_have_last_resort(struct module_env* env, struct delegpt* dp,
-       struct iter_qstate* iq)
+can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen,
+       uint16_t qclass)
 {
        struct delegpt* fwddp;
        struct iter_hints_stub* stub;
+       int labs = dname_count_labels(nm);
        /* do not process a last resort (the parent side) if a stub
         * or forward is configured, because we do not want to go 'above'
         * the configured servers */
-       if(!dname_is_root(dp->name) && (stub = (struct iter_hints_stub*)
-               name_tree_find(&env->hints->tree, dp->name, dp->namelen,
-               dp->namelabs, iq->qchase.qclass)) &&
+       if(!dname_is_root(nm) && (stub = (struct iter_hints_stub*)
+               name_tree_find(&env->hints->tree, nm, nmlen, labs, qclass)) &&
                /* has_parent side is turned off for stub_first, where we
                 * are allowed to go to the parent */
                stub->dp->has_parent_side_NS) {
-               verbose(VERB_QUERY, "configured stub servers failed -- returning SERVFAIL");
                return 0;
        }
-       if((fwddp = forwards_find(env->fwds, dp->name, iq->qchase.qclass)) &&
+       if((fwddp = forwards_find(env->fwds, nm, qclass)) &&
                /* has_parent_side is turned off for forward_first, where
                 * we are allowed to go to the parent */
                fwddp->has_parent_side_NS) {
-               verbose(VERB_QUERY, "configured forward servers failed -- returning SERVFAIL");
                return 0;
        }
        return 1;
@@ -1624,9 +1622,11 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
        verbose(VERB_ALGO, "No more query targets, attempting last resort");
        log_assert(iq->dp);
 
-       if(!can_have_last_resort(qstate->env, iq->dp, iq)) {
+       if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
+               iq->qchase.qclass)) {
                /* fail -- no more targets, no more hope of targets, no hope 
                 * of a response. */
+               verbose(VERB_QUERY, "configured stub or forward servers failed -- returning SERVFAIL");
                return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
        }
        if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) {
@@ -1711,6 +1711,19 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
        /* see if we can issue queries to get nameserver addresses */
        /* this lookup is not randomized, but sequential. */
        for(ns = iq->dp->nslist; ns; ns = ns->next) {
+               /* if this nameserver is at a delegation point, but that
+                * delegation point is a stub and we cannot go higher, skip*/
+               if( ((ie->supports_ipv6 && !ns->done_pside6) ||
+                   (ie->supports_ipv4 && !ns->done_pside4)) &&
+                   !can_have_last_resort(qstate->env, ns->name, ns->namelen,
+                       iq->qchase.qclass)) {
+                       log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
+                               "because it is also a stub/forward,",
+                               ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
+                       if(ie->supports_ipv6) ns->done_pside6 = 1;
+                       if(ie->supports_ipv4) ns->done_pside4 = 1;
+                       continue;
+               }
                /* query for parent-side A and AAAA for nameservers */
                if(ie->supports_ipv6 && !ns->done_pside6) {
                        /* Send the AAAA request. */
index 2f07340ab603ec10e167d49087728cdc227a6d26..e5c6200060a03f50528451a4a805b51a6d808320 100644 (file)
@@ -8,6 +8,9 @@ stub-zone:
 stub-zone:
        name: "example.com"
        stub-addr: 10.0.1.1
+stub-zone:
+       name: "example.net"
+       stub-addr: 10.0.5.1
 CONFIG_END
 
 SCENARIO_BEGIN Test stub zone leaking to the internet on last resort fallback
@@ -18,7 +21,7 @@ RANGE_BEGIN 0 100
 
 ; root prime
 ENTRY_BEGIN
-MATCH
+MATCH qname qtype
 ADJUST copy_id copy_query
 REPLY QR NOERROR
 SECTION QUESTION
@@ -45,6 +48,7 @@ subzone.example.com. IN A
 SECTION AUTHORITY
 subzone.example.com. IN NS sub-ns1.example.com.
 subzone.example.com. IN NS sub-ns2.example.com.
+subzone.example.com. IN NS example.net.
 SECTION ADDITIONAL
 sub-ns1.example.com. IN A 10.0.2.3
 sub-ns2.example.com. IN A 10.0.2.4
@@ -92,6 +96,44 @@ ENTRY_END
 
 RANGE_END
 
+; stub server for example.net
+RANGE_BEGIN 0 100
+       ADDRESS 10.0.5.1
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 10.0.5.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION ANSWER
+example.net. IN A 10.0.5.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.net. IN AAAA
+SECTION AUTHORITY
+example.net. 300 SOA master.example.net etc 1 2 3 4 300
+ENTRY_END
+
+RANGE_END
+
 ; stub server for subzone.example.com
 RANGE_BEGIN 0 100
        ADDRESS 10.0.2.3
@@ -120,16 +162,52 @@ SECTION ANSWER
 ENTRY_END
 RANGE_END
 
+; stub server for subzone.example.com
+RANGE_BEGIN 0 100
+       ADDRESS 10.0.5.4
+; match anything, servfail
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+subzone.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+
+; fetch the delegation point for example.net in cache.
 STEP 1 QUERY
 ENTRY_BEGIN
 REPLY RD
 SECTION QUESTION
+example.net. IN NS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 10.0.5.1
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
 whatever.subzone.example.com. IN A
 ENTRY_END
 
 ; recursion happens here.
 ; the query should not leak subzone ns queries to the internet
-STEP 10 CHECK_ANSWER
+STEP 30 CHECK_ANSWER
 ENTRY_BEGIN
 MATCH all
 REPLY QR RD RA SERVFAIL