]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix #1332: CNAME chains are sometimes not followed when RPZs add a
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Tue, 9 Sep 2025 10:34:11 +0000 (12:34 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Tue, 9 Sep 2025 10:34:11 +0000 (12:34 +0200)
  local CNAME rewrite.

doc/Changelog
services/rpz.c
testdata/rpz_cname_wild.rpl [new file with mode: 0644]

index 5fe960354a5a36a21ab140a1617d14c636987c8c..3c3c835cbd46bd0a2e60d1fdd397469bda35b26b 100644 (file)
@@ -1,3 +1,7 @@
+9 September 2025: Wouter
+       - Fix #1332: CNAME chains are sometimes not followed when RPZs add a
+         local CNAME rewrite.
+
 8 September 2025: Yorgos
        - Update documentation for using "SET ... EX" in Redis.
        - Document max buffer sizes for Redis commands.
index df39e75b0596a12e8f489921cd9f53d7ce807e94..f45cf65420d7e32efcb1fdbe664ccc0ef8628a19 100644 (file)
@@ -2121,8 +2121,17 @@ rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
        rpz_log_dname("nsdname local data", key.name, key.namelen);
 
        ld = (struct local_data*)rbtree_search(&z->data, &key.node);
+       if(ld == NULL && dname_is_wild(z->name)) {
+               key.name = z->name;
+               key.namelen = z->namelen;
+               key.namelabs = z->namelabs;
+               ld = (struct local_data*)rbtree_search(&z->data, &key.node);
+               /* rpz_synthesize_localdata_from_rrset is going to make
+                * the rrset source name equal to the query name. So no need
+                * to make the wildcard rrset here. */
+       }
        if(ld == NULL) {
-               verbose(VERB_ALGO, "rpz: nsdname: impossible: qname not found");
+               verbose(VERB_ALGO, "rpz: nsdname: qname not found");
                return NULL;
        }
 
@@ -2148,6 +2157,15 @@ rpz_synthesize_qname_localdata_msg(struct rpz* r, struct module_qstate* ms,
        key.namelen = qinfo->qname_len;
        key.namelabs = dname_count_labels(qinfo->qname);
        ld = (struct local_data*)rbtree_search(&z->data, &key.node);
+       if(ld == NULL && dname_is_wild(z->name)) {
+               key.name = z->name;
+               key.namelen = z->namelen;
+               key.namelabs = z->namelabs;
+               ld = (struct local_data*)rbtree_search(&z->data, &key.node);
+               /* rpz_synthesize_localdata_from_rrset is going to make
+                * the rrset source name equal to the query name. So no need
+                * to make the wildcard rrset here. */
+       }
        if(ld == NULL) {
                verbose(VERB_ALGO, "rpz: qname: name not found");
                return NULL;
diff --git a/testdata/rpz_cname_wild.rpl b/testdata/rpz_cname_wild.rpl
new file mode 100644 (file)
index 0000000..ce7200a
--- /dev/null
@@ -0,0 +1,190 @@
+; 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"
+       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.
+*.gotham5.a CNAME static.gotham6.a.
+*.gotham7.a.rpz-nsdname CNAME static.gotham8.a.
+TEMPFILE_END
+
+stub-zone:
+       name: "a."
+       stub-addr: 10.20.30.40
+CONFIG_END
+
+SCENARIO_BEGIN Test RPZ with CNAME with a wildcarded qname trigger after it.
+
+; a.
+RANGE_BEGIN 0 100
+       ADDRESS 10.20.30.40
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gotham.a. IN NS
+SECTION AUTHORITY
+gotham.a. NS ns1.gotham.a.
+SECTION ADDITIONAL
+ns1.gotham.a. A 10.20.30.41
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gotham2.a. IN NS
+SECTION AUTHORITY
+gotham2.a. NS ns1.gotham2.a.
+SECTION ADDITIONAL
+ns1.gotham2.a. A 10.20.30.42
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gotham6.a. IN NS
+SECTION AUTHORITY
+gotham6.a. NS ns1.gotham6.a.
+SECTION ADDITIONAL
+ns1.gotham6.a. A 10.20.30.46
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gotham7.a. IN NS
+SECTION AUTHORITY
+gotham7.a. NS ns1.gotham7.a.
+SECTION ADDITIONAL
+ns1.gotham7.a. A 10.20.30.47
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gotham8.a. IN NS
+SECTION AUTHORITY
+gotham8.a. NS ns1.gotham8.a.
+SECTION ADDITIONAL
+ns1.gotham8.a. A 10.20.30.48
+ENTRY_END
+RANGE_END
+
+; gotham.a.
+RANGE_BEGIN 0 100
+       ADDRESS 10.20.30.41
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.gotham.a. IN A
+SECTION ANSWER
+www.gotham.a. CNAME host.gotham5.a.
+ENTRY_END
+RANGE_END
+
+; gotham2.a.
+RANGE_BEGIN 0 100
+       ADDRESS 10.20.30.42
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.gotham2.a. IN A
+SECTION ANSWER
+www.gotham2.a. CNAME host.gotham7.a.
+ENTRY_END
+RANGE_END
+
+; gotham6.a.
+RANGE_BEGIN 0 100
+       ADDRESS 10.20.30.46
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+static.gotham6.a. IN A
+SECTION ANSWER
+static.gotham6.a. A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; gotham8.a.
+RANGE_BEGIN 0 100
+       ADDRESS 10.20.30.48
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+static.gotham8.a. IN A
+SECTION ANSWER
+static.gotham8.a. A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.gotham.a.  IN      A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.gotham.a.  IN      A
+SECTION ANSWER
+www.gotham.a. CNAME host.gotham5.a.
+host.gotham5.a CNAME static.gotham6.a.
+static.gotham6.a. A 1.2.3.4
+ENTRY_END
+
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.gotham2.a. IN      A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.gotham2.a. IN      A
+SECTION ANSWER
+www.gotham2.a. CNAME host.gotham7.a.
+host.gotham7.a CNAME static.gotham8.a.
+static.gotham8.a. A 1.2.3.5
+ENTRY_END
+
+SCENARIO_END