]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix rpz for cname override action after nsdname and nsip triggers.
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 13 Mar 2024 16:14:14 +0000 (17:14 +0100)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 13 Mar 2024 16:14:14 +0000 (17:14 +0100)
doc/Changelog
iterator/iterator.c
services/rpz.c
testdata/rpz_nsdname_override.rpl [new file with mode: 0644]

index 6651612d88b08ddc830d6abbf95f78afdbc93ce4..a2229a42e6b00f8bb34ca949a34c5446f20f542a 100644 (file)
@@ -6,6 +6,7 @@
          clientip localdata action is logged. Fix rpz override action cname
          for the clientip trigger.
        - Fix to unify codepath for local alias for rpz cname action override.
+       - Fix rpz for cname override action after nsdname and nsip triggers.
 
 12 March 2024: Yorgos
        - Merge #1028: Clearer documentation for tcp-idle-timeout and
index 3c5d317810a83dfda7e1cdb8fde1a16c5dbb24ed..e35d8e34a9aa9eba8c93f30553b314ad84772656 100644 (file)
@@ -2746,8 +2746,48 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
        delegpt_add_unused_targets(iq->dp);
 
        if(qstate->env->auth_zones) {
+               uint8_t* sname = NULL;
+               size_t snamelen = 0;
                /* apply rpz triggers at query time */
+               struct dns_msg* forged_response_after_cname;
                struct dns_msg* forged_response = rpz_callback_from_iterator_module(qstate, iq);
+               while(forged_response && reply_find_rrset_section_an(
+                       forged_response->rep, iq->qchase.qname,
+                       iq->qchase.qname_len, LDNS_RR_TYPE_CNAME,
+                       iq->qchase.qclass)) {
+                       /* another cname to follow */
+                       if(!handle_cname_response(qstate, iq, forged_response,
+                               &sname, &snamelen)) {
+                               errinf(qstate, "malloc failure, CNAME info");
+                               return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+                       }
+                       iq->qchase.qname = sname;
+                       iq->qchase.qname_len = snamelen;
+                       forged_response_after_cname =
+                               rpz_callback_from_iterator_cname(qstate, iq);
+                       if(forged_response_after_cname) {
+                               forged_response = forged_response_after_cname;
+                       } else {
+                               /* Follow the CNAME with a query restart */
+                               iq->deleg_msg = NULL;
+                               iq->dp = NULL;
+                               iq->dsns_point = NULL;
+                               iq->auth_zone_response = 0;
+                               iq->refetch_glue = 0;
+                               iq->query_restart_count++;
+                               iq->sent_count = 0;
+                               iq->dp_target_count = 0;
+                               if(qstate->env->cfg->qname_minimisation)
+                                       iq->minimisation_state = INIT_MINIMISE_STATE;
+                               outbound_list_clear(&iq->outlist);
+                               iq->num_current_queries = 0;
+                               fptr_ok(fptr_whitelist_modenv_detach_subs(
+                                       qstate->env->detach_subs));
+                               (*qstate->env->detach_subs)(qstate);
+                               iq->num_target_queries = 0;
+                               return next_state(iq, INIT_REQUEST_STATE);
+                       }
+               }
                if(forged_response != NULL) {
                        qstate->ext_state[id] = module_finished;
                        qstate->return_rcode = LDNS_RCODE_NOERROR;
index fb9814335393c4454f6b951533a2a51bd153ab2d..a753f307b2c3426e166a70840ea03aa7b133a237 100644 (file)
@@ -2139,6 +2139,58 @@ rpz_synthesize_qname_localdata_msg(struct rpz* r, struct module_qstate* ms,
        return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az);
 }
 
+/** Synthesize a CNAME message for RPZ action override */
+static struct dns_msg*
+rpz_synthesize_cname_override_msg(struct rpz* r, struct module_qstate* ms,
+       struct query_info* qinfo)
+{
+       struct dns_msg* msg = NULL;
+       struct reply_info* new_reply_info;
+       struct ub_packed_rrset_key* rp;
+
+       msg = rpz_dns_msg_new(ms->region);
+       if(msg == NULL) { return NULL; }
+
+        new_reply_info = construct_reply_info_base(ms->region,
+                                                   LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
+                                                   1, /* qd */
+                                                   0, /* ttl */
+                                                   0, /* prettl */
+                                                   0, /* expttl */
+                                                   1, /* an */
+                                                   0, /* ns */
+                                                   0, /* ar */
+                                                   1, /* total */
+                                                   sec_status_insecure,
+                                                   LDNS_EDE_NONE);
+       if(new_reply_info == NULL) {
+               log_err("out of memory");
+               return NULL;
+       }
+       new_reply_info->authoritative = 1;
+
+       rp = respip_copy_rrset(r->cname_override, ms->region);
+       if(rp == NULL) {
+               log_err("out of memory");
+               return NULL;
+       }
+       rp->rk.dname = qinfo->qname;
+       rp->rk.dname_len = qinfo->qname_len;
+       /* this rrset is from the rpz data, or synthesized.
+        * It is not actually from the network, so we flag it with this
+        * flags as a fake RRset. If later the cache is used to look up
+        * rrsets, then the fake ones are not returned (if you look without
+        * the flag). For like CNAME lookups from the iterator or A, AAAA
+        * lookups for nameserver targets, it would use the without flag
+        * actual data. So that the actual network data and fake data
+        * are kept track of separately. */
+       rp->rk.flags |= PACKED_RRSET_RPZ;
+       new_reply_info->rrsets[0] = rp;
+
+       msg->rep = new_reply_info;
+       return msg;
+}
+
 static int
 rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
        struct local_zone* z, enum localzone_type lzt, struct query_info* qinfo,
@@ -2244,6 +2296,9 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
                ret = NULL;
                ms->rpz_passthru = 1;
                break;
+       case RPZ_CNAME_OVERRIDE_ACTION:
+               ret = rpz_synthesize_cname_override_msg(r, ms, &ms->qinfo);
+               break;
        default:
                verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
                        rpz_action_to_string(action));
@@ -2299,8 +2354,11 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
                ret = NULL;
                ms->rpz_passthru = 1;
                break;
+       case RPZ_CNAME_OVERRIDE_ACTION:
+               ret = rpz_synthesize_cname_override_msg(r, ms, &ms->qinfo);
+               break;
        default:
-               verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
+               verbose(VERB_ALGO, "rpz: nsdname: bug: unhandled or invalid action: '%s'",
                        rpz_action_to_string(action));
                ret = NULL;
        }
diff --git a/testdata/rpz_nsdname_override.rpl b/testdata/rpz_nsdname_override.rpl
new file mode 100644 (file)
index 0000000..d662e55
--- /dev/null
@@ -0,0 +1,325 @@
+; config options
+server:
+       module-config: "respip validator iterator"
+       target-fetch-policy: "0 0 0 0 0"
+       qname-minimisation: no
+       access-control: 192.0.0.0/8 allow
+
+rpz:
+       name: "rpz.example.com."
+       rpz-log: yes
+       rpz-log-name: "rpz.example.com"
+       rpz-action-override: "nxdomain"
+       zonefile:
+TEMPFILE_NAME rpz.example.com
+TEMPFILE_CONTENTS rpz.example.com
+$ORIGIN example.com.
+rpz    3600    IN      SOA     ns1.rpz.example.com. hostmaster.rpz.example.com. (
+               1379078166 28800 7200 604800 7200 )
+       3600    IN      NS      ns1.rpz.example.com.
+       3600    IN      NS      ns2.rpz.example.com.
+$ORIGIN rpz.example.com.
+ns1.gotham.a.rpz-nsdname A 1.2.3.5
+TEMPFILE_END
+
+rpz:
+       name: "rpz2.example.com."
+       rpz-log: yes
+       rpz-log-name: "rpz2.example.com"
+       rpz-action-override: "nodata"
+       zonefile:
+TEMPFILE_NAME rpz2.example.com
+TEMPFILE_CONTENTS rpz2.example.com
+$ORIGIN example.com.
+rpz2   3600    IN      SOA     ns1.rpz2.example.com. hostmaster.rpz2.example.com. (
+               1379078166 28800 7200 604800 7200 )
+       3600    IN      NS      ns1.rpz2.example.com.
+       3600    IN      NS      ns2.rpz2.example.com.
+$ORIGIN rpz2.example.com.
+ns1.gotham2.a.rpz-nsdname A 1.2.3.5
+TEMPFILE_END
+
+rpz:
+       name: "rpz3.example.com."
+       rpz-log: yes
+       rpz-log-name: "rpz3.example.com"
+       rpz-action-override: "passthru"
+       zonefile:
+TEMPFILE_NAME rpz3.example.com
+TEMPFILE_CONTENTS rpz3.example.com
+$ORIGIN example.com.
+rpz3   3600    IN      SOA     ns1.rpz3.example.com. hostmaster.rpz3.example.com. (
+               1379078166 28800 7200 604800 7200 )
+       3600    IN      NS      ns1.rpz3.example.com.
+       3600    IN      NS      ns2.rpz3.example.com.
+$ORIGIN rpz3.example.com.
+ns1.gotham3.a.rpz-nsdname A 1.2.3.5
+TEMPFILE_END
+
+rpz:
+       name: "rpz4.example.com."
+       rpz-log: yes
+       rpz-log-name: "rpz4.example.com"
+       rpz-action-override: "drop"
+       zonefile:
+TEMPFILE_NAME rpz4.example.com
+TEMPFILE_CONTENTS rpz4.example.com
+$ORIGIN example.com.
+rpz4   3600    IN      SOA     ns1.rpz4.example.com. hostmaster.rpz4.example.com. (
+               1379078166 28800 7200 604800 7200 )
+       3600    IN      NS      ns1.rpz4.example.com.
+       3600    IN      NS      ns2.rpz4.example.com.
+$ORIGIN rpz4.example.com.
+ns1.gotham3.a.rpz-nsdname A 1.2.3.5
+ns1.gotham4.a.rpz-nsdname A 1.2.3.5
+TEMPFILE_END
+
+rpz:
+       name: "rpz5.example.com."
+       rpz-log: yes
+       rpz-log-name: "rpz5.example.com"
+       rpz-action-override: "cname"
+       rpz-cname-override: "target.a"
+       zonefile:
+TEMPFILE_NAME rpz5.example.com
+TEMPFILE_CONTENTS rpz5.example.com
+$ORIGIN example.com.
+rpz5   3600    IN      SOA     ns1.rpz5.example.com. hostmaster.rpz5.example.com. (
+               1379078166 28800 7200 604800 7200 )
+       3600    IN      NS      ns1.rpz5.example.com.
+       3600    IN      NS      ns2.rpz5.example.com.
+$ORIGIN rpz5.example.com.
+ns1.gotham5.a.rpz-nsdname A 1.2.3.5
+TEMPFILE_END
+
+rpz:
+       name: "rpz6.example.com."
+       rpz-log: yes
+       rpz-log-name: "rpz6.example.com"
+       rpz-action-override: "disabled"
+       zonefile:
+TEMPFILE_NAME rpz6.example.com
+TEMPFILE_CONTENTS rpz6.example.com
+$ORIGIN example.com.
+rpz6   3600    IN      SOA     ns1.rpz6.example.com. hostmaster.rpz6.example.com. (
+               1379078166 28800 7200 604800 7200 )
+       3600    IN      NS      ns1.rpz6.example.com.
+       3600    IN      NS      ns2.rpz6.example.com.
+$ORIGIN rpz6.example.com.
+ns1.gotham6.a.rpz-nsdname A 1.2.3.5
+TEMPFILE_END
+
+stub-zone:
+       name: "a."
+       stub-addr: 10.20.30.40
+CONFIG_END
+
+SCENARIO_BEGIN Test RPZ action override with trigger from nsdname.
+
+; a.
+RANGE_BEGIN 0 1000
+       ADDRESS 10.20.30.40
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.gotham.a. IN A
+SECTION AUTHORITY
+gotham.a. NS ns1.gotham.a.
+SECTION ADDITIONAL
+ns1.gotham.a. A 10.20.30.41
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.gotham2.a. IN A
+SECTION AUTHORITY
+gotham2.a. NS ns1.gotham2.a.
+SECTION ADDITIONAL
+ns1.gotham2.a. A 10.20.30.42
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.gotham3.a. IN A
+SECTION AUTHORITY
+gotham3.a. NS ns1.gotham3.a.
+SECTION ADDITIONAL
+ns1.gotham3.a. A 10.20.30.43
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.gotham4.a. IN A
+SECTION AUTHORITY
+gotham4.a. NS ns1.gotham4.a.
+SECTION ADDITIONAL
+ns1.gotham4.a. A 10.20.30.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.gotham5.a. IN A
+SECTION AUTHORITY
+gotham5.a. NS ns1.gotham5.a.
+SECTION ADDITIONAL
+ns1.gotham5.a. A 10.20.30.45
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.gotham6.a. IN A
+SECTION AUTHORITY
+gotham6.a. NS ns1.gotham6.a.
+SECTION ADDITIONAL
+ns1.gotham6.a. A 10.20.30.46
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+target.a. IN A
+SECTION ANSWER
+target.a. IN A 1.2.3.6
+ENTRY_END
+RANGE_END
+
+; gotham3.a.
+RANGE_BEGIN 0 1000
+       ADDRESS 10.20.30.43
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.gotham3.a. IN A
+SECTION ANSWER
+www.gotham3.a. A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; gotham6.a.
+RANGE_BEGIN 0 1000
+       ADDRESS 10.20.30.46
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.gotham6.a. IN A
+SECTION ANSWER
+www.gotham6.a. A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.gotham.a.  IN      A
+ENTRY_END
+
+STEP 11 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+www.gotham.a.  IN      A
+SECTION ANSWER
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.gotham2.a. IN      A
+ENTRY_END
+
+STEP 21 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AA NOERROR
+SECTION QUESTION
+www.gotham2.a. IN      A
+SECTION ANSWER
+ENTRY_END
+
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.gotham3.a. IN      A
+ENTRY_END
+
+STEP 31 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.gotham3.a. IN      A
+SECTION ANSWER
+www.gotham3.a. A 1.2.3.4
+ENTRY_END
+
+STEP 40 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.gotham4.a. IN      A
+ENTRY_END
+;dropped
+
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.gotham5.a. IN      A
+ENTRY_END
+
+STEP 51 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.gotham5.a. IN      A
+SECTION ANSWER
+www.gotham5.a. CNAME target.a
+target.a A 1.2.3.6
+ENTRY_END
+
+STEP 60 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.gotham6.a. IN      A
+ENTRY_END
+
+STEP 61 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.gotham6.a. IN      A
+SECTION ANSWER
+www.gotham6.a. A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END