From 79e25e192c84838739b37da37f21955bc0d6a563 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Mon, 18 Mar 2024 11:25:29 +0100 Subject: [PATCH 01/24] - Fix that rpz CNAME content is limited to the max number of cnames. --- doc/Changelog | 3 +++ iterator/iterator.c | 12 +++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index 69d80fda3..6f413e7a0 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,6 @@ +18 March 2024: Wouter + - Fix that rpz CNAME content is limited to the max number of cnames. + 15 March 2024: Yorgos - Merge #1030: Persist the openssl and expat directories for repeated Windows builds. diff --git a/iterator/iterator.c b/iterator/iterator.c index e35d8e34a..ad67a3241 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1453,10 +1453,12 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, /* apply rpz qname triggers after cname */ struct dns_msg* forged_response = rpz_callback_from_iterator_cname(qstate, iq); + int count = 0; 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)) { + iq->qchase.qclass) && + count++ < ie->max_query_restarts) { /* another cname to follow */ if(!handle_cname_response(qstate, iq, forged_response, &sname, &slen)) { @@ -2751,10 +2753,12 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, /* 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); + int count = 0; 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)) { + iq->qchase.qclass) && + count++ < ie->max_query_restarts) { /* another cname to follow */ if(!handle_cname_response(qstate, iq, forged_response, &sname, &snamelen)) { @@ -3382,10 +3386,12 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, /* apply rpz qname triggers after cname */ struct dns_msg* forged_response = rpz_callback_from_iterator_cname(qstate, iq); + int count = 0; 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)) { + iq->qchase.qclass) && + count++ < ie->max_query_restarts) { /* another cname to follow */ if(!handle_cname_response(qstate, iq, forged_response, &sname, &snamelen)) { From 39cfc8c1c0a0f4a2b18a2c831c40570214b58765 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Mon, 18 Mar 2024 12:45:00 +0100 Subject: [PATCH 02/24] - Fix rpz, it follows iterator CNAMEs for nsip and nsdname and sets the reply query_info values, that is better for debug logging. --- doc/Changelog | 2 ++ services/rpz.c | 59 ++++++++++++++++++++++++++------------------------ 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index 6f413e7a0..fe106cdcb 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,5 +1,7 @@ 18 March 2024: Wouter - Fix that rpz CNAME content is limited to the max number of cnames. + - Fix rpz, it follows iterator CNAMEs for nsip and nsdname and sets + the reply query_info values, that is better for debug logging. 15 March 2024: Yorgos - Merge #1030: Persist the openssl and expat directories for repeated diff --git a/services/rpz.c b/services/rpz.c index a753f307b..bcc0322bb 100644 --- a/services/rpz.c +++ b/services/rpz.c @@ -2009,6 +2009,7 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs msg = rpz_dns_msg_new(ms->region); if(msg == NULL) { return NULL; } + msg->qinfo = *qi; new_reply_info = construct_reply_info_base(ms->region, LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA, 1, /* qd */ @@ -2051,9 +2052,9 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs static inline struct dns_msg* rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms, - struct clientip_synthesized_rr* data, struct auth_zone* az) + struct query_info* qi, struct clientip_synthesized_rr* data, + struct auth_zone* az) { - struct query_info* qi = &ms->qinfo; struct local_rrset* rrset; rrset = rpz_find_synthesized_rrset(qi->qtype, data); @@ -2062,7 +2063,7 @@ rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms, return NULL; } - return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az); + return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az); } /* copy'n'paste from localzone.c */ @@ -2083,8 +2084,8 @@ local_data_find_type(struct local_data* data, uint16_t type, int alias_ok) /* based on localzone.c:local_data_answer() */ static inline struct dns_msg* rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms, - struct local_zone* z, struct matched_delegation_point const* match, - struct auth_zone* az) + struct query_info* qi, struct local_zone* z, + struct matched_delegation_point const* match, struct auth_zone* az) { struct local_data key; struct local_data* ld; @@ -2105,13 +2106,13 @@ rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms, return NULL; } - rrset = local_data_find_type(ld, ms->qinfo.qtype, 1); + rrset = local_data_find_type(ld, qi->qtype, 1); if(rrset == NULL) { verbose(VERB_ALGO, "rpz: nsdname: no matching local data found"); return NULL; } - return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az); + return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az); } /* like local_data_answer for qname triggers after a cname */ @@ -2151,6 +2152,7 @@ rpz_synthesize_cname_override_msg(struct rpz* r, struct module_qstate* ms, msg = rpz_dns_msg_new(ms->region); if(msg == NULL) { return NULL; } + msg->qinfo = *qinfo; new_reply_info = construct_reply_info_base(ms->region, LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA, 1, /* qd */ @@ -2253,8 +2255,9 @@ rpz_delegation_point_ipbased_trigger_lookup(struct rpz* rpz, struct iter_qstate* } static struct dns_msg* -rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r, - struct clientip_synthesized_rr* raddr, struct auth_zone* az) +rpz_apply_nsip_trigger(struct module_qstate* ms, struct query_info* qchase, + struct rpz* r, struct clientip_synthesized_rr* raddr, + struct auth_zone* az) { enum rpz_action action = raddr->action; struct dns_msg* ret = NULL; @@ -2267,16 +2270,16 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r, if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL) { verbose(VERB_ALGO, "rpz: bug: nsip local data action but no local data"); - ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); + ret = rpz_synthesize_nodata(r, ms, qchase, az); goto done; } switch(action) { case RPZ_NXDOMAIN_ACTION: - ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az); + ret = rpz_synthesize_nxdomain(r, ms, qchase, az); break; case RPZ_NODATA_ACTION: - ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); + ret = rpz_synthesize_nodata(r, ms, qchase, az); break; case RPZ_TCP_ONLY_ACTION: /* basically a passthru here but the tcp-only will be @@ -2285,19 +2288,19 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r, ret = NULL; break; case RPZ_DROP_ACTION: - ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); + ret = rpz_synthesize_nodata(r, ms, qchase, az); ms->is_drop = 1; break; case RPZ_LOCAL_DATA_ACTION: - ret = rpz_synthesize_nsip_localdata(r, ms, raddr, az); - if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); } + ret = rpz_synthesize_nsip_localdata(r, ms, qchase, raddr, az); + if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); } break; case RPZ_PASSTHRU_ACTION: ret = NULL; ms->rpz_passthru = 1; break; case RPZ_CNAME_OVERRIDE_ACTION: - ret = rpz_synthesize_cname_override_msg(r, ms, &ms->qinfo); + ret = rpz_synthesize_cname_override_msg(r, ms, qchase); break; default: verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'", @@ -2316,9 +2319,9 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r, } static struct dns_msg* -rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r, - struct local_zone* z, struct matched_delegation_point const* match, - struct auth_zone* az) +rpz_apply_nsdname_trigger(struct module_qstate* ms, struct query_info* qchase, + struct rpz* r, struct local_zone* z, + struct matched_delegation_point const* match, struct auth_zone* az) { struct dns_msg* ret = NULL; enum rpz_action action = localzone_type_to_rpz_action(z->type); @@ -2331,10 +2334,10 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r, switch(action) { case RPZ_NXDOMAIN_ACTION: - ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az); + ret = rpz_synthesize_nxdomain(r, ms, qchase, az); break; case RPZ_NODATA_ACTION: - ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); + ret = rpz_synthesize_nodata(r, ms, qchase, az); break; case RPZ_TCP_ONLY_ACTION: /* basically a passthru here but the tcp-only will be @@ -2343,19 +2346,19 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r, ret = NULL; break; case RPZ_DROP_ACTION: - ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); + ret = rpz_synthesize_nodata(r, ms, qchase, az); ms->is_drop = 1; break; case RPZ_LOCAL_DATA_ACTION: - ret = rpz_synthesize_nsdname_localdata(r, ms, z, match, az); - if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); } + ret = rpz_synthesize_nsdname_localdata(r, ms, qchase, z, match, az); + if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); } break; case RPZ_PASSTHRU_ACTION: ret = NULL; ms->rpz_passthru = 1; break; case RPZ_CNAME_OVERRIDE_ACTION: - ret = rpz_synthesize_cname_override_msg(r, ms, &ms->qinfo); + ret = rpz_synthesize_cname_override_msg(r, ms, qchase); break; default: verbose(VERB_ALGO, "rpz: nsdname: bug: unhandled or invalid action: '%s'", @@ -2449,7 +2452,7 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate* /* the nsdname has precedence over the nsip triggers */ z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones, - ms->qinfo.qclass, &match); + is->qchase.qclass, &match); if(z != NULL) { lock_rw_unlock(&a->lock); break; @@ -2472,9 +2475,9 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate* if(z) { lock_rw_unlock(&z->lock); } - return rpz_apply_nsip_trigger(ms, r, raddr, a); + return rpz_apply_nsip_trigger(ms, &is->qchase, r, raddr, a); } - return rpz_apply_nsdname_trigger(ms, r, z, &match, a); + return rpz_apply_nsdname_trigger(ms, &is->qchase, r, z, &match, a); } struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms, From e6b1f9a4c3cf4708fecff19ab8df9fb39eb701ae Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Mon, 18 Mar 2024 13:52:59 +0100 Subject: [PATCH 03/24] - Fix rpz that copies the cname override completely to the temp region, so there are no references to the rpz region. --- doc/Changelog | 2 ++ services/rpz.c | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index fe106cdcb..9deac82ff 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -2,6 +2,8 @@ - Fix that rpz CNAME content is limited to the max number of cnames. - Fix rpz, it follows iterator CNAMEs for nsip and nsdname and sets the reply query_info values, that is better for debug logging. + - Fix rpz that copies the cname override completely to the temp + region, so there are no references to the rpz region. 15 March 2024: Yorgos - Merge #1030: Persist the openssl and expat directories for repeated diff --git a/services/rpz.c b/services/rpz.c index bcc0322bb..0637e3262 100644 --- a/services/rpz.c +++ b/services/rpz.c @@ -1888,8 +1888,7 @@ rpz_apply_cname_override_action(struct rpz* r, sizeof(struct local_rrset)); if(qinfo->local_alias == NULL) return 0; /* out of memory */ - qinfo->local_alias->rrset = regional_alloc_init(temp, - r->cname_override, sizeof(*r->cname_override)); + qinfo->local_alias->rrset = respip_copy_rrset(r->cname_override, temp); if(qinfo->local_alias->rrset == NULL) { qinfo->local_alias = NULL; return 0; /* out of memory */ From e46b188fe8b79cdc10cd1f43a91f1d25c7622483 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Mon, 18 Mar 2024 14:11:43 +0100 Subject: [PATCH 04/24] - Add rpz unit test for nsip action override. --- doc/Changelog | 1 + testdata/rpz_nsip_override.rpl | 332 +++++++++++++++++++++++++++++++++ 2 files changed, 333 insertions(+) create mode 100644 testdata/rpz_nsip_override.rpl diff --git a/doc/Changelog b/doc/Changelog index 9deac82ff..1086f18e3 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -4,6 +4,7 @@ the reply query_info values, that is better for debug logging. - Fix rpz that copies the cname override completely to the temp region, so there are no references to the rpz region. + - Add rpz unit test for nsip action override. 15 March 2024: Yorgos - Merge #1030: Persist the openssl and expat directories for repeated diff --git a/testdata/rpz_nsip_override.rpl b/testdata/rpz_nsip_override.rpl new file mode 100644 index 000000000..8c3b20be3 --- /dev/null +++ b/testdata/rpz_nsip_override.rpl @@ -0,0 +1,332 @@ +; 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 +32.41.30.20.10.rpz-nsip 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 +32.42.30.20.10.rpz-nsip 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 +32.43.30.20.10.rpz-nsip 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 +32.43.30.20.10.rpz-nsip A 1.2.3.5 +; ns1.gotham4.a +32.44.30.20.10.rpz-nsip 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 +32.45.30.20.10.rpz-nsip 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 +32.46.30.20.10.rpz-nsip 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 nsip. + +; 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 From 8dbf46913b6b29d0be791cd8ed323c913d468827 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Mon, 18 Mar 2024 14:36:29 +0100 Subject: [PATCH 05/24] - Fix rpz for qtype CNAME after nameserver trigger. --- doc/Changelog | 1 + iterator/iterator.c | 5 +- testdata/rpz_qtype_cname.rpl | 120 +++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 testdata/rpz_qtype_cname.rpl diff --git a/doc/Changelog b/doc/Changelog index 1086f18e3..421d79a96 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -5,6 +5,7 @@ - Fix rpz that copies the cname override completely to the temp region, so there are no references to the rpz region. - Add rpz unit test for nsip action override. + - Fix rpz for qtype CNAME after nameserver trigger. 15 March 2024: Yorgos - Merge #1030: Persist the openssl and expat directories for repeated diff --git a/iterator/iterator.c b/iterator/iterator.c index ad67a3241..b6d0b67d4 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1458,6 +1458,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, forged_response->rep, iq->qchase.qname, iq->qchase.qname_len, LDNS_RR_TYPE_CNAME, iq->qchase.qclass) && + iq->qchase.qtype != LDNS_RR_TYPE_CNAME && count++ < ie->max_query_restarts) { /* another cname to follow */ if(!handle_cname_response(qstate, iq, forged_response, @@ -2750,7 +2751,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, if(qstate->env->auth_zones) { uint8_t* sname = NULL; size_t snamelen = 0; - /* apply rpz triggers at query time */ + /* apply rpz triggers at query time; nameserver IP and dname */ struct dns_msg* forged_response_after_cname; struct dns_msg* forged_response = rpz_callback_from_iterator_module(qstate, iq); int count = 0; @@ -2758,6 +2759,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, forged_response->rep, iq->qchase.qname, iq->qchase.qname_len, LDNS_RR_TYPE_CNAME, iq->qchase.qclass) && + iq->qchase.qtype != LDNS_RR_TYPE_CNAME && count++ < ie->max_query_restarts) { /* another cname to follow */ if(!handle_cname_response(qstate, iq, forged_response, @@ -3391,6 +3393,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, forged_response->rep, iq->qchase.qname, iq->qchase.qname_len, LDNS_RR_TYPE_CNAME, iq->qchase.qclass) && + iq->qchase.qtype != LDNS_RR_TYPE_CNAME && count++ < ie->max_query_restarts) { /* another cname to follow */ if(!handle_cname_response(qstate, iq, forged_response, diff --git a/testdata/rpz_qtype_cname.rpl b/testdata/rpz_qtype_cname.rpl new file mode 100644 index 000000000..fa5674a0f --- /dev/null +++ b/testdata/rpz_qtype_cname.rpl @@ -0,0 +1,120 @@ +; 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. +www.gotham.a CNAME foo.target.a. +32.42.30.20.10.rpz-nsip CNAME foo.target.a. +TEMPFILE_END + +stub-zone: + name: "a." + stub-addr: 10.20.30.40 +CONFIG_END + +SCENARIO_BEGIN Test RPZ with qtype CNAME. + +; 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 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 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 + +; gotham2.a. +RANGE_BEGIN 0 1000 + ADDRESS 10.20.30.42 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.gotham2.a. IN CNAME +SECTION ANSWER +www.gotham2.a. CNAME foo2.target.a. +ENTRY_END +RANGE_END + +; Query for type CNAME, from the RPZ response +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham.a. IN CNAME +ENTRY_END + +STEP 11 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA +SECTION QUESTION +www.gotham.a. IN CNAME +SECTION ANSWER +www.gotham.a. IN CNAME foo.target.a. +ENTRY_END + +; Query for type CNAME, the answer is nameserver lookup, CNAME from rpz nsip. +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham2.a. IN CNAME +ENTRY_END + +STEP 21 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +www.gotham2.a. IN CNAME +SECTION ANSWER +www.gotham2.a. IN CNAME foo.target.a. +ENTRY_END + +SCENARIO_END From fef974ca5c713639f3cc7080cfecb323c5eb9b3e Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Tue, 19 Mar 2024 09:32:53 +0100 Subject: [PATCH 06/24] - Fix rpz so that rpz CNAME can apply after rpz CNAME. And fix that clientip and nsip can give a CNAME. --- doc/Changelog | 4 + iterator/iterator.c | 91 ++-- services/rpz.c | 24 +- testdata/rpz_cname_handle.rpl | 779 ++++++++++++++++++++++++++++++++++ 4 files changed, 850 insertions(+), 48 deletions(-) create mode 100644 testdata/rpz_cname_handle.rpl diff --git a/doc/Changelog b/doc/Changelog index 421d79a96..48106ac46 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,7 @@ +19 March 2024: Wouter + - Fix rpz so that rpz CNAME can apply after rpz CNAME. And fix that + clientip and nsip can give a CNAME. + 18 March 2024: Wouter - Fix that rpz CNAME content is limited to the max number of cnames. - Fix rpz, it follows iterator CNAMEs for nsip and nsdname and sets diff --git a/iterator/iterator.c b/iterator/iterator.c index b6d0b67d4..6ec8af401 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1389,7 +1389,59 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, /* This either results in a query restart (CNAME cache response), a * terminating response (ANSWER), or a cache miss (null). */ - + + /* Check RPZ for override */ + if(qstate->env->auth_zones) { + /* apply rpz qname triggers, like after cname */ + struct dns_msg* forged_response = + rpz_callback_from_iterator_cname(qstate, iq); + if(forged_response) { + uint8_t* sname = 0; + size_t slen = 0; + int count = 0; + 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) && + iq->qchase.qtype != LDNS_RR_TYPE_CNAME && + count++ < ie->max_query_restarts) { + /* another cname to follow */ + if(!handle_cname_response(qstate, iq, forged_response, + &sname, &slen)) { + errinf(qstate, "malloc failure, CNAME info"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + iq->qchase.qname = sname; + iq->qchase.qname_len = slen; + forged_response = + rpz_callback_from_iterator_cname(qstate, iq); + } + if(forged_response != NULL) { + qstate->ext_state[id] = module_finished; + qstate->return_rcode = LDNS_RCODE_NOERROR; + qstate->return_msg = forged_response; + iq->response = forged_response; + next_state(iq, FINISHED_STATE); + if(!iter_prepend(iq, qstate->return_msg, qstate->region)) { + log_err("rpz: after cached cname, prepend rrsets: out of memory"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + qstate->return_msg->qinfo = qstate->qinfo; + return 0; + } + /* Follow the CNAME response */ + iq->dp = NULL; + iq->refetch_glue = 0; + iq->query_restart_count++; + iq->sent_count = 0; + iq->dp_target_count = 0; + sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region); + if(qstate->env->cfg->qname_minimisation) + iq->minimisation_state = INIT_MINIMISE_STATE; + return next_state(iq, INIT_REQUEST_STATE); + } + } + if (iter_stub_fwd_no_cache(qstate, &iq->qchase, &dpname, &dpnamelen)) { /* Asked to not query cache. */ verbose(VERB_ALGO, "no-cache set, going to the network"); @@ -1449,42 +1501,6 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, } iq->qchase.qname = sname; iq->qchase.qname_len = slen; - if(qstate->env->auth_zones) { - /* apply rpz qname triggers after cname */ - struct dns_msg* forged_response = - rpz_callback_from_iterator_cname(qstate, iq); - int count = 0; - 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) && - iq->qchase.qtype != LDNS_RR_TYPE_CNAME && - count++ < ie->max_query_restarts) { - /* another cname to follow */ - if(!handle_cname_response(qstate, iq, forged_response, - &sname, &slen)) { - errinf(qstate, "malloc failure, CNAME info"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - iq->qchase.qname = sname; - iq->qchase.qname_len = slen; - forged_response = - rpz_callback_from_iterator_cname(qstate, iq); - } - if(forged_response != NULL) { - qstate->ext_state[id] = module_finished; - qstate->return_rcode = LDNS_RCODE_NOERROR; - qstate->return_msg = forged_response; - iq->response = forged_response; - next_state(iq, FINISHED_STATE); - if(!iter_prepend(iq, qstate->return_msg, qstate->region)) { - log_err("rpz: after cached cname, prepend rrsets: out of memory"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - qstate->return_msg->qinfo = qstate->qinfo; - return 0; - } - } /* This *is* a query restart, even if it is a cheap * one. */ iq->dp = NULL; @@ -1497,7 +1513,6 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, iq->minimisation_state = INIT_MINIMISE_STATE; return next_state(iq, INIT_REQUEST_STATE); } - /* if from cache, NULL, else insert 'cache IP' len=0 */ if(qstate->reply_origin) sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region); diff --git a/services/rpz.c b/services/rpz.c index 0637e3262..0bbb886f9 100644 --- a/services/rpz.c +++ b/services/rpz.c @@ -1244,16 +1244,20 @@ rpz_find_zone(struct local_zones* zones, uint8_t* qname, size_t qname_len, uint1 /** Find entry for RR type in the list of rrsets for the clientip. */ static struct local_rrset* rpz_find_synthesized_rrset(uint16_t qtype, - struct clientip_synthesized_rr* data) + struct clientip_synthesized_rr* data, int alias_ok) { - struct local_rrset* cursor = data->data; + struct local_rrset* cursor = data->data, *cname = NULL; while( cursor != NULL) { struct packed_rrset_key* packed_rrset = &cursor->rrset->rk; if(htons(qtype) == packed_rrset->type) { return cursor; } + if(ntohs(packed_rrset->type) == LDNS_RR_TYPE_CNAME && alias_ok) + cname = cursor; cursor = cursor->next; } + if(alias_ok) + return cname; return NULL; } @@ -1439,7 +1443,7 @@ static int rpz_remove_clientip_rr(struct clientip_synthesized_rr* node, struct local_rrset* rrset; struct packed_rrset_data* d; size_t index; - rrset = rpz_find_synthesized_rrset(rr_type, node); + rrset = rpz_find_synthesized_rrset(rr_type, node, 0); if(rrset == NULL) return 0; /* type not found, ignore */ d = (struct packed_rrset_data*)rrset->rrset->entry.data; @@ -1842,7 +1846,7 @@ rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr* raddr, } /* check query type / rr type */ - rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr); + rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr, 1); if(rrset == NULL) { verbose(VERB_ALGO, "rpz: unable to find local-data for query"); rrset_count = 0; @@ -2056,7 +2060,7 @@ rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms, { struct local_rrset* rrset; - rrset = rpz_find_synthesized_rrset(qi->qtype, data); + rrset = rpz_find_synthesized_rrset(qi->qtype, data, 1); if(rrset == NULL) { verbose(VERB_ALGO, "rpz: nsip: no matching local data found"); return NULL; @@ -2128,12 +2132,12 @@ rpz_synthesize_qname_localdata_msg(struct rpz* r, struct module_qstate* ms, key.namelabs = dname_count_labels(qinfo->qname); ld = (struct local_data*)rbtree_search(&z->data, &key.node); if(ld == NULL) { - verbose(VERB_ALGO, "rpz: qname after cname: name not found"); + verbose(VERB_ALGO, "rpz: qname: name not found"); return NULL; } rrset = local_data_find_type(ld, qinfo->qtype, 1); if(rrset == NULL) { - verbose(VERB_ALGO, "rpz: qname after cname: type not found"); + verbose(VERB_ALGO, "rpz: qname: type not found"); return NULL; } return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az); @@ -2539,10 +2543,10 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms, dname_str(is->qchase.qname, nm); dname_str(z->name, zn); if(strcmp(zn, nm) != 0) - verbose(VERB_ALGO, "rpz: qname trigger after cname %s on %s, with action=%s", + verbose(VERB_ALGO, "rpz: qname trigger %s on %s, with action=%s", zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt))); else - verbose(VERB_ALGO, "rpz: qname trigger after cname %s, with action=%s", + verbose(VERB_ALGO, "rpz: qname trigger %s, with action=%s", nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt))); } switch(localzone_type_to_rpz_action(lzt)) { @@ -2571,7 +2575,7 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms, ms->rpz_passthru = 1; break; default: - verbose(VERB_ALGO, "rpz: qname trigger after cname: bug: unhandled or invalid action: '%s'", + verbose(VERB_ALGO, "rpz: qname trigger: bug: unhandled or invalid action: '%s'", rpz_action_to_string(localzone_type_to_rpz_action(lzt))); ret = NULL; } diff --git a/testdata/rpz_cname_handle.rpl b/testdata/rpz_cname_handle.rpl new file mode 100644 index 000000000..38dddf12c --- /dev/null +++ b/testdata/rpz_cname_handle.rpl @@ -0,0 +1,779 @@ +; 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. +www.gotham.a A 1.2.3.61 +www.gotham2.a CNAME g2.target.a. +g2.target.a A 1.2.3.62 +www.gotham3.a CNAME g3.target.a. +g3.target.a CNAME g3b.target.a. +g3b.target.a A 1.2.3.63 +www.gotham4.a CNAME g4.target.a. +g4.target.a CNAME g4b.target.a. +g4b.target.a CNAME g4c.target.a. +g4c.target.a A 1.2.3.64 +w2.gotham5.a A 1.2.3.65 +w2.gotham6.a CNAME g6.target.a. +g6.target.a A 1.2.3.66 +w2.gotham7.a CNAME g7.target.a. +g7.target.a CNAME g7b.target.a. +g7b.target.a A 1.2.3.66 +; ns1.gotham8.a +32.48.30.20.10.rpz-nsip A 1.2.3.68 +; ns1.gotham9.a +32.49.30.20.10.rpz-nsip CNAME g9.target.a. +g9.target.a A 1.2.3.69 +; ns1.gotham10.a +32.50.30.20.10.rpz-nsip CNAME g10.target.a. +g10.target.a CNAME g10b.target.a. +g10b.target.a A 1.2.3.70 +www.gotham11.a CNAME g11.target.a. +www.gotham12.a CNAME g12.target.a. +g12.target.a CNAME g12b.target.a. +www.gotham13.a CNAME g13.target.a. +g13.target.a CNAME g13b.target.a. +g13b.target.a CNAME g13c.target.a. +w2.gotham14.a CNAME g14.target.a. +w2.gotham15.a CNAME g15.target.a. +g15.target.a CNAME g15b.target.a. +; ns1.gotham16.a +32.56.30.20.10.rpz-nsip CNAME g16.target.a. +; ns1.gotham17.a +32.57.30.20.10.rpz-nsip CNAME g17.target.a. +g17.target.a CNAME g17b.target.a. +TEMPFILE_END + +stub-zone: + name: "a." + stub-addr: 10.20.30.40 +CONFIG_END + +SCENARIO_BEGIN Test RPZ handling of CNAMEs. + +; a. +RANGE_BEGIN 0 1000 + ADDRESS 10.20.30.40 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham5.a. IN NS +SECTION AUTHORITY +gotham5.a. NS ns1.gotham5.a. +SECTION ADDITIONAL +ns1.gotham5.a. A 10.20.30.45 +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 + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham9.a. IN NS +SECTION AUTHORITY +gotham9.a. NS ns1.gotham9.a. +SECTION ADDITIONAL +ns1.gotham9.a. A 10.20.30.49 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham10.a. IN NS +SECTION AUTHORITY +gotham10.a. NS ns1.gotham10.a. +SECTION ADDITIONAL +ns1.gotham10.a. A 10.20.30.50 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham14.a. IN NS +SECTION AUTHORITY +gotham14.a. NS ns1.gotham14.a. +SECTION ADDITIONAL +ns1.gotham14.a. A 10.20.30.54 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham15.a. IN NS +SECTION AUTHORITY +gotham15.a. NS ns1.gotham15.a. +SECTION ADDITIONAL +ns1.gotham15.a. A 10.20.30.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham16.a. IN NS +SECTION AUTHORITY +gotham16.a. NS ns1.gotham16.a. +SECTION ADDITIONAL +ns1.gotham16.a. A 10.20.30.56 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham17.a. IN NS +SECTION AUTHORITY +gotham17.a. NS ns1.gotham17.a. +SECTION ADDITIONAL +ns1.gotham17.a. A 10.20.30.57 +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 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +g11.target.a. IN A +SECTION ANSWER +g11.target.a. IN A 1.2.3.11 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +g12b.target.a. IN A +SECTION ANSWER +g12b.target.a. A 1.2.3.12 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +g13c.target.a. IN A +SECTION ANSWER +g13c.target.a. A 1.2.3.13 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +g14.target.a. IN A +SECTION ANSWER +g14.target.a. A 1.2.3.14 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +g15b.target.a. IN A +SECTION ANSWER +g15b.target.a. A 1.2.3.15 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +g16.target.a. IN A +SECTION ANSWER +g16.target.a. A 1.2.3.16 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +g17b.target.a. IN A +SECTION ANSWER +g17b.target.a. A 1.2.3.17 +ENTRY_END +RANGE_END + +; gotham5.a. +RANGE_BEGIN 0 1000 + ADDRESS 10.20.30.45 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.gotham5.a. IN A +SECTION ANSWER +www.gotham5.a. CNAME w2.gotham5.a. +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. CNAME w2.gotham6.a. +ENTRY_END +RANGE_END + +; gotham7.a. +RANGE_BEGIN 0 1000 + ADDRESS 10.20.30.47 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.gotham7.a. IN A +SECTION ANSWER +www.gotham7.a. CNAME w2.gotham7.a. +ENTRY_END +RANGE_END + +; gotham14.a. +RANGE_BEGIN 0 1000 + ADDRESS 10.20.30.54 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.gotham14.a. IN A +SECTION ANSWER +www.gotham14.a. CNAME w2.gotham14.a. +ENTRY_END +RANGE_END + +; gotham15.a. +RANGE_BEGIN 0 1000 + ADDRESS 10.20.30.55 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.gotham15.a. IN A +SECTION ANSWER +www.gotham15.a. CNAME w2.gotham15.a. +ENTRY_END +RANGE_END + +; Test with zero rpz CNAMEs, rpz answer. +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 NOERROR +SECTION QUESTION +www.gotham.a. IN A +SECTION ANSWER +www.gotham.a. A 1.2.3.61 +ENTRY_END + +; Test with one rpz CNAME, rpz answer. +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 +www.gotham2.a. CNAME g2.target.a. +g2.target.a. A 1.2.3.62 +ENTRY_END + +; Test with two rpz CNAMEs, rpz answer. +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 AA NOERROR +SECTION QUESTION +www.gotham3.a. IN A +SECTION ANSWER +www.gotham3.a. CNAME g3.target.a. +g3.target.a. CNAME g3b.target.a. +g3b.target.a. A 1.2.3.63 +ENTRY_END + +; Test with three rpz CNAMEs, rpz answer. +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham4.a. IN A +ENTRY_END + +STEP 41 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +www.gotham4.a. IN A +SECTION ANSWER +www.gotham4.a. CNAME g4.target.a. +g4.target.a. CNAME g4b.target.a. +g4b.target.a. CNAME g4c.target.a. +g4c.target.a. A 1.2.3.64 +ENTRY_END + +; Test with a CNAME from upstream, zero rpz CNAMEs, rpz answer. +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 AA NOERROR +SECTION QUESTION +www.gotham5.a. IN A +SECTION ANSWER +www.gotham5.a. CNAME w2.gotham5.a. +w2.gotham5.a. A 1.2.3.65 +ENTRY_END + +; Test with a CNAME from upstream, one rpz CNAME, rpz answer. +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 AA NOERROR +SECTION QUESTION +www.gotham6.a. IN A +SECTION ANSWER +www.gotham6.a. CNAME w2.gotham6.a. +w2.gotham6.a. CNAME g6.target.a. +g6.target.a. A 1.2.3.66 +ENTRY_END + +; Test with a CNAME from upstream, two rpz CNAMEs, rpz answer. +STEP 70 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham7.a. IN A +ENTRY_END + +STEP 71 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +www.gotham7.a. IN A +SECTION ANSWER +www.gotham7.a. CNAME w2.gotham7.a. +w2.gotham7.a. CNAME g7.target.a. +g7.target.a. CNAME g7b.target.a. +g7b.target.a. A 1.2.3.66 +ENTRY_END + +; Test with a CNAME from cache, zero rpz CNAMEs, rpz answer. +STEP 80 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham5.a. IN A +ENTRY_END + +STEP 81 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +www.gotham5.a. IN A +SECTION ANSWER +www.gotham5.a. CNAME w2.gotham5.a. +w2.gotham5.a. A 1.2.3.65 +ENTRY_END + +; Test with a CNAME from cache, one rpz CNAME, rpz answer. +STEP 90 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham6.a. IN A +ENTRY_END + +STEP 91 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +www.gotham6.a. IN A +SECTION ANSWER +www.gotham6.a. CNAME w2.gotham6.a. +w2.gotham6.a. CNAME g6.target.a. +g6.target.a. A 1.2.3.66 +ENTRY_END + +; Test with a CNAME from cache, two rpz CNAMEs, rpz answer. +STEP 100 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham7.a. IN A +ENTRY_END + +STEP 101 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +www.gotham7.a. IN A +SECTION ANSWER +www.gotham7.a. CNAME w2.gotham7.a. +w2.gotham7.a. CNAME g7.target.a. +g7.target.a. CNAME g7b.target.a. +g7b.target.a. A 1.2.3.66 +ENTRY_END + +; Test with lookup from nameserver, zero rpz CNAMEs, rpz nsip answer. +STEP 110 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham8.a. IN A +ENTRY_END + +STEP 111 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +www.gotham8.a. IN A +SECTION ANSWER +www.gotham8.a. A 1.2.3.68 +ENTRY_END + +; Test with lookup from nameserver, one rpz CNAME, rpz nsip answer. +STEP 120 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham9.a. IN A +ENTRY_END + +STEP 121 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +www.gotham9.a. IN A +SECTION ANSWER +www.gotham9.a. CNAME g9.target.a. +g9.target.a. A 1.2.3.69 +ENTRY_END + +; Test with lookup from nameserver, two rpz CNAMEs, rpz nsip answer. +STEP 130 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham10.a. IN A +ENTRY_END + +STEP 131 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +www.gotham10.a. IN A +SECTION ANSWER +www.gotham10.a. CNAME g10.target.a. +g10.target.a. CNAME g10b.target.a. +g10b.target.a. A 1.2.3.70 +ENTRY_END + +; Test with one rpz CNAME, upstream answer. +STEP 140 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham11.a. IN A +ENTRY_END + +STEP 141 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +www.gotham11.a. IN A +SECTION ANSWER +www.gotham11.a. CNAME g11.target.a. +g11.target.a. A 1.2.3.11 +ENTRY_END + +; Test with two rpz CNAMEs, upstream answer. +STEP 150 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham12.a. IN A +ENTRY_END + +STEP 151 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +www.gotham12.a. IN A +SECTION ANSWER +www.gotham12.a. CNAME g12.target.a. +g12.target.a. CNAME g12b.target.a. +g12b.target.a. A 1.2.3.12 +ENTRY_END + +; Test with three rpz CNAMEs, upstream answer. +STEP 160 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham13.a. IN A +ENTRY_END + +STEP 161 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +www.gotham13.a. IN A +SECTION ANSWER +www.gotham13.a. CNAME g13.target.a. +g13.target.a. CNAME g13b.target.a. +g13b.target.a. CNAME g13c.target.a. +g13c.target.a. A 1.2.3.13 +ENTRY_END + +; Test with a CNAME from upstream, one rpz CNAME, upstream answer. +STEP 170 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham14.a. IN A +ENTRY_END + +STEP 171 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.gotham14.a. IN A +SECTION ANSWER +www.gotham14.a. CNAME w2.gotham14.a. +w2.gotham14.a. CNAME g14.target.a. +g14.target.a. A 1.2.3.14 +ENTRY_END + +; Test with a CNAME from upstream, two rpz CNAMEs, upstream answer. +STEP 180 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham15.a. IN A +ENTRY_END + +STEP 181 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.gotham15.a. IN A +SECTION ANSWER +www.gotham15.a. CNAME w2.gotham15.a. +w2.gotham15.a. CNAME g15.target.a. +g15.target.a. CNAME g15b.target.a. +g15b.target.a. A 1.2.3.15 +ENTRY_END + +; Test with a CNAME from cache, one rpz CNAME, upstream answer. +STEP 190 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham14.a. IN A +ENTRY_END + +STEP 191 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.gotham14.a. IN A +SECTION ANSWER +www.gotham14.a. CNAME w2.gotham14.a. +w2.gotham14.a. CNAME g14.target.a. +g14.target.a. A 1.2.3.14 +ENTRY_END + +; Test with a CNAME from cache, two rpz CNAMEs, upstream answer. +STEP 200 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham15.a. IN A +ENTRY_END + +STEP 201 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.gotham15.a. IN A +SECTION ANSWER +www.gotham15.a. CNAME w2.gotham15.a. +w2.gotham15.a. CNAME g15.target.a. +g15.target.a. CNAME g15b.target.a. +g15b.target.a. A 1.2.3.15 +ENTRY_END + +; Test with lookup from nameserver, one rpz nsip CNAME, upstream answer. +STEP 210 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham16.a. IN A +ENTRY_END + +STEP 211 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.gotham16.a. IN A +SECTION ANSWER +www.gotham16.a. CNAME g16.target.a. +g16.target.a. A 1.2.3.16 +ENTRY_END + +; Test with lookup from nameserver, two rpz nsip CNAMEs, upstream answer. +STEP 220 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.gotham17.a. IN A +ENTRY_END + +STEP 221 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.gotham17.a. IN A +SECTION ANSWER +www.gotham17.a. CNAME g17.target.a. +g17.target.a. CNAME g17b.target.a. +g17b.target.a. A 1.2.3.17 +ENTRY_END + +SCENARIO_END From 73bd5a19aa3ad026cbe8693dc11fd9762d1db052 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Tue, 19 Mar 2024 10:21:10 +0100 Subject: [PATCH 07/24] - Fix localdata and rpz localdata to match CNAME only if no direct type match is available. --- doc/Changelog | 2 ++ services/localzone.c | 6 ++-- services/rpz.c | 6 ++-- testdata/local_cnameother.rpl | 67 +++++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 testdata/local_cnameother.rpl diff --git a/doc/Changelog b/doc/Changelog index 48106ac46..866abe211 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,8 @@ 19 March 2024: Wouter - Fix rpz so that rpz CNAME can apply after rpz CNAME. And fix that clientip and nsip can give a CNAME. + - Fix localdata and rpz localdata to match CNAME only if no direct + type match is available. 18 March 2024: Wouter - Fix that rpz CNAME content is limited to the max number of cnames. diff --git a/services/localzone.c b/services/localzone.c index 9c8e3c7ac..51056c8ff 100644 --- a/services/localzone.c +++ b/services/localzone.c @@ -330,14 +330,16 @@ get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass, static struct local_rrset* local_data_find_type(struct local_data* data, uint16_t type, int alias_ok) { - struct local_rrset* p; + struct local_rrset* p, *cname = NULL; type = htons(type); for(p = data->rrsets; p; p = p->next) { if(p->rrset->rk.type == type) return p; if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME)) - return p; + cname = p; } + if(alias_ok) + return cname; return NULL; } diff --git a/services/rpz.c b/services/rpz.c index 0bbb886f9..f036cc5fd 100644 --- a/services/rpz.c +++ b/services/rpz.c @@ -2073,14 +2073,16 @@ rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms, static struct local_rrset* local_data_find_type(struct local_data* data, uint16_t type, int alias_ok) { - struct local_rrset* p; + struct local_rrset* p, *cname = NULL; type = htons(type); for(p = data->rrsets; p; p = p->next) { if(p->rrset->rk.type == type) return p; if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME)) - return p; + cname = p; } + if(alias_ok) + return cname; return NULL; } diff --git a/testdata/local_cnameother.rpl b/testdata/local_cnameother.rpl new file mode 100644 index 000000000..d86ba4f9d --- /dev/null +++ b/testdata/local_cnameother.rpl @@ -0,0 +1,67 @@ +; config options +server: + local-zone: "a." static + local-data: "myd.a. NSEC myd2.a. CNAME NSEC" + local-data: "myd.a. CNAME myd.target.a." + + ; Switches the types first one then the other. + local-data: "myd2.a. CNAME myd2.target.a." + local-data: "myd2.a. NSEC myd3.a. CNAME NSEC" + +stub-zone: + name: "a" + stub-addr: 1.2.3.4 + +CONFIG_END +SCENARIO_BEGIN Test local data queries with CNAME and other data. + +RANGE_BEGIN 0 1000 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.refuse.top. IN A +SECTION ANSWER +www.refuse.top. IN A 5.5.5.5 +ENTRY_END +RANGE_END + +; local data query for type next to CNAME, the specific type should +; be preferred over the CNAME. +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +myd.a. IN NSEC +ENTRY_END + +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA +SECTION QUESTION +myd.a. IN NSEC +SECTION ANSWER +myd.a. NSEC myd2.a. CNAME NSEC +ENTRY_END + +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +myd2.a. IN NSEC +ENTRY_END + +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA +SECTION QUESTION +myd2.a. IN NSEC +SECTION ANSWER +myd2.a. NSEC myd3.a. CNAME NSEC +ENTRY_END + +SCENARIO_END From ef60dcac31fd139a34fc8efddf610dafaf07d301 Mon Sep 17 00:00:00 2001 From: Pierre4012 <45879018+Pierre4012@users.noreply.github.com> Date: Mon, 25 Mar 2024 16:43:49 +0100 Subject: [PATCH 08/24] Improve Windows NSIS installer script (setup.nsi) (#831) * Improve Windows NSIS installer script (setup.nsi) Two improvements of installer script : - avoid error message when Unbound is running, - add "DisplayVersion" in registry thus Windows package manager (Winget) can handle Unbound. * Update setup.nsi ask user to stop unbound service + DisplayVersion in Windows registry --- winrc/setup.nsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/winrc/setup.nsi b/winrc/setup.nsi index 886d83a99..7374f5d5a 100644 --- a/winrc/setup.nsi +++ b/winrc/setup.nsi @@ -78,6 +78,15 @@ section "Root anchor - DNSSEC" SectionRootKey sectionEnd section "-hidden.postinstall" + # if Unbund is already installed, ask to stop it to allow file replacement + IfFileExists "$INSTDIR\unbound-service-remove.exe" 0 next_label + MessageBox MB_YESNO "Unbound is already installed! Would you like to stop the service to continue with the update?" /SD IDYES IDNO false_label # defaults to yes on silent installations + nsExec::ExecToLog '"$INSTDIR\unbound-service-remove.exe" stop' + Sleep 1000 + Goto next_label + false_label: + Quit + next_label: # copy files SetRegView 64 setOutPath $INSTDIR @@ -134,6 +143,7 @@ section "-hidden.postinstall" # register uninstaller WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Unbound" "DisplayName" "Unbound" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Unbound" "DisplayVersion" "${VERSION}" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Unbound" "UninstallString" "$\"$INSTDIR\uninst.exe$\"" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Unbound" "QuietUninstallString" "$\"$INSTDIR\uninst.exe$\" /S" WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Unbound" "NoModify" "1" From ce8c1ce5b0975c36749bc8cb703d87117d0bfb5b Mon Sep 17 00:00:00 2001 From: Yorgos Thessalonikefs Date: Mon, 25 Mar 2024 16:46:25 +0100 Subject: [PATCH 09/24] Changelog entry for #831 - Merge #831 from Pierre4012: Improve Windows NSIS installer script (setup.nsi). --- doc/Changelog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/Changelog b/doc/Changelog index 866abe211..3fcff16b9 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,7 @@ +25 March 2024: Yorgos + - Merge #831 from Pierre4012: Improve Windows NSIS installer + script (setup.nsi). + 19 March 2024: Wouter - Fix rpz so that rpz CNAME can apply after rpz CNAME. And fix that clientip and nsip can give a CNAME. From 07561964fcb294651cf426a176f54e4a5d722ac9 Mon Sep 17 00:00:00 2001 From: Yorgos Thessalonikefs Date: Mon, 25 Mar 2024 22:02:08 +0100 Subject: [PATCH 10/24] - For #831: Format text, use exclamation icon and explicit label names. --- doc/Changelog | 2 ++ winrc/setup.nsi | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index 3fcff16b9..8bfb1444e 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,8 @@ 25 March 2024: Yorgos - Merge #831 from Pierre4012: Improve Windows NSIS installer script (setup.nsi). + - For #831: Format text, use exclamation icon and explicit label + names. 19 March 2024: Wouter - Fix rpz so that rpz CNAME can apply after rpz CNAME. And fix that diff --git a/winrc/setup.nsi b/winrc/setup.nsi index 7374f5d5a..64e5523f7 100644 --- a/winrc/setup.nsi +++ b/winrc/setup.nsi @@ -79,14 +79,14 @@ sectionEnd section "-hidden.postinstall" # if Unbund is already installed, ask to stop it to allow file replacement - IfFileExists "$INSTDIR\unbound-service-remove.exe" 0 next_label - MessageBox MB_YESNO "Unbound is already installed! Would you like to stop the service to continue with the update?" /SD IDYES IDNO false_label # defaults to yes on silent installations + IfFileExists "$INSTDIR\unbound-service-remove.exe" 0 service_remove_end + MessageBox MB_YESNO|MB_ICONEXCLAMATION "Unbound is already installed!$\r$\n$\r$\nWould you like to stop the service to continue with the update?" /SD IDYES IDNO service_remove_quit # defaults to yes on silent installations nsExec::ExecToLog '"$INSTDIR\unbound-service-remove.exe" stop' Sleep 1000 - Goto next_label - false_label: + Goto service_remove_end + service_remove_quit: Quit - next_label: + service_remove_end: # copy files SetRegView 64 setOutPath $INSTDIR From c2b20c585ef32aea8d47a6c13930a2a78aef3ab0 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 27 Mar 2024 11:43:55 +0100 Subject: [PATCH 11/24] - Fix name of unit test for subnet cache response. --- doc/Changelog | 3 +++ testdata/subnet_cached.crpl | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/Changelog b/doc/Changelog index 8bfb1444e..fe3f8d063 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,6 @@ +27 March 2024: Wouter + - Fix name of unit test for subnet cache response. + 25 March 2024: Yorgos - Merge #831 from Pierre4012: Improve Windows NSIS installer script (setup.nsi). diff --git a/testdata/subnet_cached.crpl b/testdata/subnet_cached.crpl index 209831335..3cee6e978 100644 --- a/testdata/subnet_cached.crpl +++ b/testdata/subnet_cached.crpl @@ -21,7 +21,7 @@ stub-zone: stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. CONFIG_END -SCENARIO_BEGIN Test validator with positive response +SCENARIO_BEGIN Test subnet cached response ; K.ROOT-SERVERS.NET. RANGE_BEGIN 0 100 From eb3e1ae24f79f8e3211b649bc235ebfb94b1ae1d Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 27 Mar 2024 11:45:34 +0100 Subject: [PATCH 12/24] - Fix #1032: The size of subnet_msg_cache calculation mistake cause memory usage increased beyond expectations. --- doc/Changelog | 2 ++ edns-subnet/subnetmod.c | 18 ++++++++++++++++-- util/storage/lruhash.c | 32 ++++++++++++++++++++++++++++++++ util/storage/lruhash.h | 11 +++++++++++ util/storage/slabhash.c | 7 +++++++ util/storage/slabhash.h | 12 ++++++++++++ 6 files changed, 80 insertions(+), 2 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index fe3f8d063..e8f1f1c39 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,5 +1,7 @@ 27 March 2024: Wouter - Fix name of unit test for subnet cache response. + - Fix #1032: The size of subnet_msg_cache calculation mistake cause + memory usage increased beyond expectations. 25 March 2024: Yorgos - Merge #831 from Pierre4012: Improve Windows NSIS installer diff --git a/edns-subnet/subnetmod.c b/edns-subnet/subnetmod.c index cefde84e5..22e3ef17e 100644 --- a/edns-subnet/subnetmod.c +++ b/edns-subnet/subnetmod.c @@ -310,9 +310,18 @@ delfunc(void *envptr, void *elemptr) { static size_t sizefunc(void *elemptr) { struct reply_info *elem = (struct reply_info *)elemptr; - return sizeof (struct reply_info) - sizeof (struct rrset_ref) + size_t s = sizeof (struct reply_info) - sizeof (struct rrset_ref) + elem->rrset_count * sizeof (struct rrset_ref) + elem->rrset_count * sizeof (struct ub_packed_rrset_key *); + size_t i; + for (i = 0; i < elem->rrset_count; i++) { + struct ub_packed_rrset_key *key = elem->rrsets[i]; + struct packed_rrset_data *data = key->entry.data; + s += ub_rrset_sizefunc(key, data); + } + if(elem->reason_bogus_str) + s += strlen(elem->reason_bogus_str)+1; + return s; } /** @@ -352,7 +361,7 @@ update_cache(struct module_qstate *qstate, int id) struct slabhash *subnet_msg_cache = sne->subnet_msg_cache; struct ecs_data *edns = &sq->ecs_client_in; size_t i; - int only_match_scope_zero; + int only_match_scope_zero, diff_size; /* We already calculated hash upon lookup (lookup_and_reply) if we were * allowed to look in the ECS cache */ @@ -417,14 +426,19 @@ update_cache(struct module_qstate *qstate, int id) if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0) only_match_scope_zero = 1; else only_match_scope_zero = 0; + diff_size = (int)tree->size_bytes; addrtree_insert(tree, (addrkey_t*)edns->subnet_addr, edns->subnet_source_mask, sq->max_scope, rep, rep->ttl, *qstate->env->now, only_match_scope_zero); + diff_size = (int)tree->size_bytes - diff_size; lock_rw_unlock(&lru_entry->lock); if (need_to_insert) { slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data, NULL); + } else { + slabhash_update_space_used(subnet_msg_cache, h, NULL, + diff_size); } } diff --git a/util/storage/lruhash.c b/util/storage/lruhash.c index e17b180db..85bb8f02e 100644 --- a/util/storage/lruhash.c +++ b/util/storage/lruhash.c @@ -528,6 +528,38 @@ lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md) lock_quick_unlock(&table->lock); } +void +lruhash_update_space_used(struct lruhash* table, void* cb_arg, int diff_size) +{ + struct lruhash_entry *reclaimlist = NULL; + + fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc)); + fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc)); + fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc)); + fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc)); + + if(cb_arg == NULL) cb_arg = table->cb_arg; + + /* find bin */ + lock_quick_lock(&table->lock); + + table->space_used = (size_t)((int)table->space_used + diff_size); + + if(table->space_used > table->space_max) + reclaim_space(table, &reclaimlist); + + lock_quick_unlock(&table->lock); + + /* finish reclaim if any (outside of critical region) */ + while(reclaimlist) { + struct lruhash_entry* n = reclaimlist->overflow_next; + void* d = reclaimlist->data; + (*table->delkeyfunc)(reclaimlist->key, cb_arg); + (*table->deldatafunc)(d, cb_arg); + reclaimlist = n; + } +} + void lruhash_traverse(struct lruhash* h, int wr, void (*func)(struct lruhash_entry*, void*), void* arg) diff --git a/util/storage/lruhash.h b/util/storage/lruhash.h index 2086e4dec..5ab488beb 100644 --- a/util/storage/lruhash.h +++ b/util/storage/lruhash.h @@ -303,6 +303,17 @@ void lru_touch(struct lruhash* table, struct lruhash_entry* entry); */ void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md); +/** + * Update the size of an element in the hashtable. + * + * @param table: hash table. + * @param cb_override: if not NULL overrides the cb_arg for deletefunc. + * @param diff_size: difference in size to the hash table storage. + * This is newsize - oldsize, a positive number uses more space. + */ +void lruhash_update_space_used(struct lruhash* table, void* cb_override, + int diff_size); + /************************* getdns functions ************************/ /*** these are used by getdns only and not by unbound. ***/ diff --git a/util/storage/slabhash.c b/util/storage/slabhash.c index 7d376c4d6..62396e16a 100644 --- a/util/storage/slabhash.c +++ b/util/storage/slabhash.c @@ -166,6 +166,13 @@ int slabhash_is_size(struct slabhash* sl, size_t size, size_t slabs) return 0; } +void slabhash_update_space_used(struct slabhash* sl, hashvalue_type hash, + void* cb_arg, int diff_size) +{ + lruhash_update_space_used(sl->array[slab_idx(sl, hash)], cb_arg, + diff_size); +} + size_t slabhash_get_mem(struct slabhash* sl) { size_t i, total = sizeof(*sl); diff --git a/util/storage/slabhash.h b/util/storage/slabhash.h index dc5fc3603..089847d93 100644 --- a/util/storage/slabhash.h +++ b/util/storage/slabhash.h @@ -161,6 +161,18 @@ size_t slabhash_get_size(struct slabhash* table); */ int slabhash_is_size(struct slabhash* table, size_t size, size_t slabs); +/** + * Update the size of an element in the hashtable, uses + * lruhash_update_space_used. + * + * @param table: hash table. + * @param hash: hash value. User calculates the hash. + * @param cb_override: if not NULL overrides the cb_arg for deletefunc. + * @param diff_size: difference in size to the hash table storage. + */ +void slabhash_update_space_used(struct slabhash* table, hashvalue_type hash, + void* cb_override, int diff_size); + /** * Retrieve slab hash current memory use. * @param table: hash table. From 3ea078baf6e856258213dce22b5de53d0f22a6b4 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 27 Mar 2024 11:49:20 +0100 Subject: [PATCH 13/24] - Fix for #1032, add safeguard to make table space positive. --- doc/Changelog | 1 + util/storage/lruhash.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/Changelog b/doc/Changelog index e8f1f1c39..1b73bf547 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -2,6 +2,7 @@ - Fix name of unit test for subnet cache response. - Fix #1032: The size of subnet_msg_cache calculation mistake cause memory usage increased beyond expectations. + - Fix for #1032, add safeguard to make table space positive. 25 March 2024: Yorgos - Merge #831 from Pierre4012: Improve Windows NSIS installer diff --git a/util/storage/lruhash.c b/util/storage/lruhash.c index 85bb8f02e..f14e83b56 100644 --- a/util/storage/lruhash.c +++ b/util/storage/lruhash.c @@ -543,7 +543,9 @@ lruhash_update_space_used(struct lruhash* table, void* cb_arg, int diff_size) /* find bin */ lock_quick_lock(&table->lock); - table->space_used = (size_t)((int)table->space_used + diff_size); + if((int)table->space_used + diff_size < 0) + table->space_used = 0; + else table->space_used = (size_t)((int)table->space_used + diff_size); if(table->space_used > table->space_max) reclaim_space(table, &reclaimlist); From fe393ac355b20e961f7465f3abb779f6096df9cb Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 27 Mar 2024 12:30:00 +0100 Subject: [PATCH 14/24] - Fix comment in lruhash space function. --- doc/Changelog | 1 + util/storage/lruhash.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/Changelog b/doc/Changelog index 1b73bf547..2d46e7199 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -3,6 +3,7 @@ - Fix #1032: The size of subnet_msg_cache calculation mistake cause memory usage increased beyond expectations. - Fix for #1032, add safeguard to make table space positive. + - Fix comment in lruhash space function. 25 March 2024: Yorgos - Merge #831 from Pierre4012: Improve Windows NSIS installer diff --git a/util/storage/lruhash.c b/util/storage/lruhash.c index f14e83b56..aba9fcc1d 100644 --- a/util/storage/lruhash.c +++ b/util/storage/lruhash.c @@ -540,7 +540,7 @@ lruhash_update_space_used(struct lruhash* table, void* cb_arg, int diff_size) if(cb_arg == NULL) cb_arg = table->cb_arg; - /* find bin */ + /* update space used */ lock_quick_lock(&table->lock); if((int)table->space_used + diff_size < 0) From 238a796e38ca8b70865ae086eb08a8f819a3ca97 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 27 Mar 2024 13:33:46 +0100 Subject: [PATCH 15/24] - Fix to add unit test for lruhash space that exercises the routines. --- doc/Changelog | 1 + testdata/subnet_cached_size.crpl | 308 +++++++++++++++++++++++++++++++ 2 files changed, 309 insertions(+) create mode 100644 testdata/subnet_cached_size.crpl diff --git a/doc/Changelog b/doc/Changelog index 2d46e7199..3fbd27026 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -4,6 +4,7 @@ memory usage increased beyond expectations. - Fix for #1032, add safeguard to make table space positive. - Fix comment in lruhash space function. + - Fix to add unit test for lruhash space that exercises the routines. 25 March 2024: Yorgos - Merge #831 from Pierre4012: Improve Windows NSIS installer diff --git a/testdata/subnet_cached_size.crpl b/testdata/subnet_cached_size.crpl new file mode 100644 index 000000000..d221d0d37 --- /dev/null +++ b/testdata/subnet_cached_size.crpl @@ -0,0 +1,308 @@ +; Ask the same question twice. Check to see second is answered +; from cache + +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + trust-anchor-signaling: no + target-fetch-policy: "0 0 0 0 0" + send-client-subnet: 1.2.3.4 + max-client-subnet-ipv4: 17 + module-config: "subnetcache validator iterator" + verbosity: 3 + fake-sha1: yes + fake-dsa: yes + access-control: 127.0.0.0/8 allow_snoop + qname-minimisation: "no" + minimal-responses: no + ; the size for the edns subnet cache + msg-cache-size: 1500 + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test subnet cached response size + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 + ENTRY_BEGIN + MATCH opcode qtype qname ednsdata + ADJUST copy_id + REPLY QR NOERROR + SECTION QUESTION + . IN NS + SECTION ANSWER + . IN NS K.ROOT-SERVERS.NET. + SECTION ADDITIONAL + HEX_EDNSDATA_BEGIN + ;; we expect to receive empty + HEX_EDNSDATA_END + K.ROOT-SERVERS.NET. IN A 193.0.14.129 + ENTRY_END + + ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR NOERROR + SECTION QUESTION + www.example.com. IN A + SECTION AUTHORITY + com. IN NS a.gtld-servers.net. + SECTION ADDITIONAL + a.gtld-servers.net. IN A 192.5.6.30 + ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 + ENTRY_BEGIN + MATCH opcode qtype qname ednsdata + ADJUST copy_id + REPLY QR NOERROR + SECTION QUESTION + com. IN NS + SECTION ANSWER + com. IN NS a.gtld-servers.net. + SECTION ADDITIONAL + HEX_EDNSDATA_BEGIN + ;; we expect to receive empty + HEX_EDNSDATA_END + a.gtld-servers.net. IN A 192.5.6.30 + ENTRY_END + + ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR NOERROR + SECTION QUESTION + www.example.com. IN A + SECTION AUTHORITY + example.com. IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 1.2.3.4 + ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 + ENTRY_BEGIN + MATCH opcode qtype qname ednsdata + ADJUST copy_id + REPLY QR NOERROR + SECTION QUESTION + example.com. IN NS + SECTION ANSWER + example.com. IN NS ns.example.com. + example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} + SECTION ADDITIONAL + HEX_EDNSDATA_BEGIN + ;; we expect to receive empty + HEX_EDNSDATA_END + ns.example.com. IN A 1.2.3.4 + ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} + ENTRY_END + + ; response to DNSKEY priming query + ENTRY_BEGIN + MATCH opcode qtype qname ednsdata + ADJUST copy_id + REPLY QR NOERROR + SECTION QUESTION + example.com. IN DNSKEY + SECTION ANSWER + example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} + example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} + SECTION AUTHORITY + example.com. IN NS ns.example.com. + example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} + SECTION ADDITIONAL + HEX_EDNSDATA_BEGIN + ;; we expect to receive empty + HEX_EDNSDATA_END + ns.example.com. IN A 1.2.3.4 + ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} + ENTRY_END + + ; response to query of interest + ENTRY_BEGIN + MATCH opcode qtype qname ednsdata + ADJUST copy_id copy_ednsdata_assume_clientsubnet + REPLY QR NOERROR + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} + SECTION AUTHORITY + example.com. IN NS ns.example.com. + example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} + SECTION ADDITIONAL + HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 11 00 ; source mask, scopemask + 7f 00 00 ; address + HEX_EDNSDATA_END + ns.example.com. IN A 1.2.3.4 + www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} + ENTRY_END + + ENTRY_BEGIN + MATCH opcode qtype qname ednsdata + ADJUST copy_id copy_ednsdata_assume_clientsubnet + REPLY QR NOERROR + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.43 + www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. AFC5G+z0jWt132hDuTIFOva59cZ7MTd+ex/osuoiQhIIuWFAr9xoZz8= + SECTION AUTHORITY + example.com. IN NS ns.example.com. + example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} + SECTION ADDITIONAL + HEX_EDNSDATA_BEGIN + ; client is 127.3.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 11 00 ; source mask, scopemask + 7f 03 00 ; address + HEX_EDNSDATA_END + ns.example.com. IN A 1.2.3.4 + ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} + ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN + HEX_ANSWER_BEGIN; + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 11 00 ; ip4, scope 17, source 0 + 7f 00 00 ;127.0.0.0/17 + HEX_ANSWER_END +ENTRY_END + +STEP 10 CHECK_ANSWER +ENTRY_BEGIN + MATCH all ednsdata + REPLY QR RD RA AD NOERROR + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} + SECTION AUTHORITY + example.com. IN NS ns.example.com. + example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} + SECTION ADDITIONAL + HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 11 11 ; source mask, scopemask + 7f 00 00 ; address + HEX_EDNSDATA_END + ns.example.com. IN A 1.2.3.4 + ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +STEP 11 QUERY + +ENTRY_BEGIN + HEX_ANSWER_BEGIN; + 00 00 00 00 00 01 00 00 ;ID 0, no RD + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 12 00 ; ip4, scope 18, source 0 + 7f 00 00 ;127.0.0.0/18 + HEX_ANSWER_END +ENTRY_END + +STEP 20 CHECK_ANSWER +ENTRY_BEGIN + MATCH all ednsdata + REPLY QR RA AD NOERROR + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} + SECTION AUTHORITY + example.com. IN NS ns.example.com. + example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} + SECTION ADDITIONAL + HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 12 11 ; source mask, scopemask + 7f 00 00 ; address + HEX_EDNSDATA_END + ns.example.com. IN A 1.2.3.4 + ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +; update the cache entry +STEP 30 QUERY +ENTRY_BEGIN + HEX_ANSWER_BEGIN; + 00 00 01 00 00 01 00 00 ;ID 0 + 00 00 00 01 03 77 77 77 ; www.example.com A? (DO) + 07 65 78 61 6d 70 6c 65 + 03 63 6f 6d 00 00 01 00 + 01 00 00 29 10 00 00 00 + 80 00 00 0b + + 00 08 00 07 ; OPC, optlen + 00 01 11 00 ; ip4, scope 17, source 0 + 7f 03 00 ;127.3.0.0/17 + HEX_ANSWER_END +ENTRY_END + +STEP 40 CHECK_ANSWER +ENTRY_BEGIN + MATCH all ednsdata + REPLY QR RD RA AD NOERROR + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.43 + www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. AFC5G+z0jWt132hDuTIFOva59cZ7MTd+ex/osuoiQhIIuWFAr9xoZz8= + SECTION AUTHORITY + example.com. IN NS ns.example.com. + example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} + SECTION ADDITIONAL + HEX_EDNSDATA_BEGIN + ; client is 127.3.0.1 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 11 11 ; source mask, scopemask + 7f 03 00 ; address + HEX_EDNSDATA_END + ns.example.com. IN A 1.2.3.4 + ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +SCENARIO_END From 192f1b0e2bcad654d9b04fc98fa578c4712e25c7 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 27 Mar 2024 14:07:54 +0100 Subject: [PATCH 16/24] - Fix that when the server truncates the pidfile, it does not follow symbolic links. --- daemon/unbound.c | 6 +++++- doc/Changelog | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/daemon/unbound.c b/daemon/unbound.c index 457a08032..b5c7a0d20 100644 --- a/daemon/unbound.c +++ b/daemon/unbound.c @@ -746,7 +746,11 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pi if(daemon->pidfile) { int fd; /* truncate pidfile */ - fd = open(daemon->pidfile, O_WRONLY | O_TRUNC, 0644); + fd = open(daemon->pidfile, O_WRONLY | O_TRUNC +#ifdef O_NOFOLLOW + | O_NOFOLLOW +#endif + , 0644); if(fd != -1) close(fd); /* delete pidfile */ diff --git a/doc/Changelog b/doc/Changelog index 3fbd27026..05be2e56f 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -5,6 +5,8 @@ - Fix for #1032, add safeguard to make table space positive. - Fix comment in lruhash space function. - Fix to add unit test for lruhash space that exercises the routines. + - Fix that when the server truncates the pidfile, it does not follow + symbolic links. 25 March 2024: Yorgos - Merge #831 from Pierre4012: Improve Windows NSIS installer From 6f82b5be4aeedf0daad6d3b0a7b529466d380697 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 27 Mar 2024 14:52:25 +0100 Subject: [PATCH 17/24] - Fix that the server does not chown the pidfile. --- contrib/rc_d_unbound | 9 +++++++++ contrib/unbound.init | 1 + contrib/unbound.init_fedora | 1 + contrib/unbound.init_yocto | 1 + daemon/unbound.c | 33 ++++++++++++++------------------- doc/Changelog | 1 + 6 files changed, 27 insertions(+), 19 deletions(-) diff --git a/contrib/rc_d_unbound b/contrib/rc_d_unbound index 56516147f..9d98c5e05 100755 --- a/contrib/rc_d_unbound +++ b/contrib/rc_d_unbound @@ -22,4 +22,13 @@ pidfile=${unbound_pidfile:-"/usr/local/etc/unbound/unbound.pid"} command_args=${unbound_flags:-"-c /usr/local/etc/unbound/unbound.conf"} extra_commands="reload" +if test "$1" = "stop" ; then + run_rc_command "$1" + ret=$? + if test $ret -eq 0; then + rm -f "$pidfile" + fi + exit $ret +fi + run_rc_command "$1" diff --git a/contrib/unbound.init b/contrib/unbound.init index c5bb52bb4..70ab0134e 100644 --- a/contrib/unbound.init +++ b/contrib/unbound.init @@ -75,6 +75,7 @@ stop() { retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile + [ $retval -eq 0 ] && rm -f $pidfile if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then umount ${rootdir}/dev/log >/dev/null 2>&1 fi; diff --git a/contrib/unbound.init_fedora b/contrib/unbound.init_fedora index 989440341..75856777f 100644 --- a/contrib/unbound.init_fedora +++ b/contrib/unbound.init_fedora @@ -58,6 +58,7 @@ stop() { killproc -p $pidfile unbound retval=$? [ $retval -eq 0 ] && rm -f $lockfile + [ $retval -eq 0 ] && rm -f $pidfile for mountfile in /dev/log /dev/urandom /etc/localtime /etc/resolv.conf /var/run/unbound do if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}''${mountfile}'' /proc/mounts; then diff --git a/contrib/unbound.init_yocto b/contrib/unbound.init_yocto index 4eba752bc..e1a812448 100644 --- a/contrib/unbound.init_yocto +++ b/contrib/unbound.init_yocto @@ -75,6 +75,7 @@ stop() { retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile + [ $retval -eq 0 ] && rm -f $pidfile if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then umount ${rootdir}/dev/log >/dev/null 2>&1 fi; diff --git a/daemon/unbound.c b/daemon/unbound.c index b5c7a0d20..d6c371571 100644 --- a/daemon/unbound.c +++ b/daemon/unbound.c @@ -366,9 +366,8 @@ readpid (const char* file) /** write pid to file. * @param pidfile: file name of pid file. * @param pid: pid to write to file. - * @return false on failure */ -static int +static void writepid (const char* pidfile, pid_t pid) { int fd; @@ -383,7 +382,7 @@ writepid (const char* pidfile, pid_t pid) , 0644)) == -1) { log_err("cannot open pidfile %s: %s", pidfile, strerror(errno)); - return 0; + return; } while(count < strlen(pidbuf)) { ssize_t r = write(fd, pidbuf+count, strlen(pidbuf)-count); @@ -393,17 +392,16 @@ writepid (const char* pidfile, pid_t pid) log_err("cannot write to pidfile %s: %s", pidfile, strerror(errno)); close(fd); - return 0; + return; } else if(r == 0) { log_err("cannot write any bytes to pidfile %s: " "write returns 0 bytes written", pidfile); close(fd); - return 0; + return; } count += r; } close(fd); - return 1; } /** @@ -545,7 +543,15 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode, cfg, 1); if(!daemon->pidfile) fatal_exit("pidfile alloc: out of memory"); - checkoldpid(daemon->pidfile, pidinchroot); + /* Check old pid if there is no username configured. + * With a username, the assumption is that the privilege + * drop makes a pidfile not removed when the server stopped + * last time. The server does not chown the pidfile for it, + * because that creates privilege escape problems, with the + * pidfile writable by unprivileged users, but used by + * privileged users. */ + if(cfg->username && cfg->username[0]) + checkoldpid(daemon->pidfile, pidinchroot); } #endif @@ -557,18 +563,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode, /* write new pidfile (while still root, so can be outside chroot) */ #ifdef HAVE_KILL if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) { - if(writepid(daemon->pidfile, getpid())) { - if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 && - pidinchroot) { -# ifdef HAVE_CHOWN - if(chown(daemon->pidfile, cfg_uid, cfg_gid) == -1) { - verbose(VERB_QUERY, "cannot chown %u.%u %s: %s", - (unsigned)cfg_uid, (unsigned)cfg_gid, - daemon->pidfile, strerror(errno)); - } -# endif /* HAVE_CHOWN */ - } - } + writepid(daemon->pidfile, getpid()); } #else (void)daemon; diff --git a/doc/Changelog b/doc/Changelog index 05be2e56f..64b1bcf49 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -7,6 +7,7 @@ - Fix to add unit test for lruhash space that exercises the routines. - Fix that when the server truncates the pidfile, it does not follow symbolic links. + - Fix that the server does not chown the pidfile. 25 March 2024: Yorgos - Merge #831 from Pierre4012: Improve Windows NSIS installer From 6d1e61173bbf44dae458c361be63217f7e9e5599 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Thu, 28 Mar 2024 09:58:03 +0100 Subject: [PATCH 18/24] - Fix #1034: DoT forward-zone via unbound-control. --- daemon/remote.c | 20 +++++++++++++------- doc/Changelog | 3 +++ doc/unbound-control.8.in | 6 ++++-- smallapp/unbound-control.c | 5 +++-- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 5d79eafd2..cbce1198b 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -2097,7 +2097,7 @@ do_forward(RES* ssl, struct worker* worker, char* args) static int parse_fs_args(RES* ssl, char* args, uint8_t** nm, struct delegpt** dp, - int* insecure, int* prime) + int* insecure, int* prime, int* tls) { char* zonename; char* rest; @@ -2112,6 +2112,8 @@ parse_fs_args(RES* ssl, char* args, uint8_t** nm, struct delegpt** dp, *insecure = 1; else if(*args == 'p' && prime) *prime = 1; + else if(*args == 't' && tls) + *tls = 1; else { (void)ssl_printf(ssl, "error: unknown option %s\n", args); return 0; @@ -2144,11 +2146,13 @@ static void do_forward_add(RES* ssl, struct worker* worker, char* args) { struct iter_forwards* fwd = worker->env.fwds; - int insecure = 0; + int insecure = 0, tls = 0; uint8_t* nm = NULL; struct delegpt* dp = NULL; - if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, NULL)) + if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, NULL, &tls)) return; + if(tls) + dp->ssl_upstream = 1; if(insecure && worker->env.anchors) { if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN, nm)) { @@ -2174,7 +2178,7 @@ do_forward_remove(RES* ssl, struct worker* worker, char* args) struct iter_forwards* fwd = worker->env.fwds; int insecure = 0; uint8_t* nm = NULL; - if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL)) + if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL, NULL)) return; if(insecure && worker->env.anchors) anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN, @@ -2189,11 +2193,13 @@ static void do_stub_add(RES* ssl, struct worker* worker, char* args) { struct iter_forwards* fwd = worker->env.fwds; - int insecure = 0, prime = 0; + int insecure = 0, prime = 0, tls = 0; uint8_t* nm = NULL; struct delegpt* dp = NULL; - if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, &prime)) + if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, &prime, &tls)) return; + if(tls) + dp->ssl_upstream = 1; if(insecure && worker->env.anchors) { if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN, nm)) { @@ -2232,7 +2238,7 @@ do_stub_remove(RES* ssl, struct worker* worker, char* args) struct iter_forwards* fwd = worker->env.fwds; int insecure = 0; uint8_t* nm = NULL; - if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL)) + if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL, NULL)) return; if(insecure && worker->env.anchors) anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN, diff --git a/doc/Changelog b/doc/Changelog index 64b1bcf49..0c43e2a5e 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,6 @@ +28 March 2024: Wouter + - Fix #1034: DoT forward-zone via unbound-control. + 27 March 2024: Wouter - Fix name of unit test for subnet cache response. - Fix #1032: The size of subnet_msg_cache calculation mistake cause diff --git a/doc/unbound-control.8.in b/doc/unbound-control.8.in index 7823de3aa..642b4c946 100644 --- a/doc/unbound-control.8.in +++ b/doc/unbound-control.8.in @@ -239,22 +239,24 @@ still be bogus, use \fBflush_zone\fR to remove it), does not affect the config f .B insecure_remove \fIzone Removes domain\-insecure for the given zone. .TP -.B forward_add \fR[\fI+i\fR] \fIzone addr ... +.B forward_add \fR[\fI+it\fR] \fIzone addr ... Add a new forward zone to running Unbound. With +i option also adds a \fIdomain\-insecure\fR for the zone (so it can resolve insecurely if you have a DNSSEC root trust anchor configured for other names). The addr can be IP4, IP6 or nameserver names, like \fIforward-zone\fR config in unbound.conf. +The +t option sets it to use tls upstream, like \fIforward\-tls\-upstream\fR: yes. .TP .B forward_remove \fR[\fI+i\fR] \fIzone Remove a forward zone from running Unbound. The +i also removes a \fIdomain\-insecure\fR for the zone. .TP -.B stub_add \fR[\fI+ip\fR] \fIzone addr ... +.B stub_add \fR[\fI+ipt\fR] \fIzone addr ... Add a new stub zone to running Unbound. With +i option also adds a \fIdomain\-insecure\fR for the zone. With +p the stub zone is set to prime, without it it is set to notprime. The addr can be IP4, IP6 or nameserver names, like the \fIstub-zone\fR config in unbound.conf. +The +t option sets it to use tls upstream, like \fIstub\-tls\-upstream\fR: yes. .TP .B stub_remove \fR[\fI+i\fR] \fIzone Remove a stub zone from running Unbound. The +i also removes a diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c index c4f730061..57b0787db 100644 --- a/smallapp/unbound-control.c +++ b/smallapp/unbound-control.c @@ -150,12 +150,13 @@ usage(void) printf(" list_local_data list local-data RRs in use\n"); printf(" insecure_add zone add domain-insecure zone\n"); printf(" insecure_remove zone remove domain-insecure zone\n"); - printf(" forward_add [+i] zone addr.. add forward-zone with servers\n"); + printf(" forward_add [+it] zone addr.. add forward-zone with servers\n"); printf(" forward_remove [+i] zone remove forward zone\n"); - printf(" stub_add [+ip] zone addr.. add stub-zone with servers\n"); + printf(" stub_add [+ipt] zone addr.. add stub-zone with servers\n"); printf(" stub_remove [+i] zone remove stub zone\n"); printf(" +i also do dnssec insecure point\n"); printf(" +p set stub to use priming\n"); + printf(" +t set to use tls upstream\n"); printf(" forward [off | addr ...] without arg show forward setup\n"); printf(" or off to turn off root forwarding\n"); printf(" or give list of ip addresses\n"); From e1aeabde44c597c0319a7531d4cb89d6d900a340 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Thu, 28 Mar 2024 09:58:57 +0100 Subject: [PATCH 19/24] - Fix for crypto related failures to have a better error string. --- doc/Changelog | 1 + util/net_help.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index 0c43e2a5e..6392055cd 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,5 +1,6 @@ 28 March 2024: Wouter - Fix #1034: DoT forward-zone via unbound-control. + - Fix for crypto related failures to have a better error string. 27 March 2024: Wouter - Fix name of unit test for subnet cache response. diff --git a/util/net_help.c b/util/net_help.c index 897024792..f38d843ed 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -1026,11 +1026,11 @@ static void log_crypto_err_io_code_arg(const char* str, int r, } else { if(print_errno) { if(errno == 0) - log_err("str: syscall error with errno %s", - strerror(errno)); - else log_err("str: %s", strerror(errno)); + log_err("%s: syscall error with errno %s", + str, strerror(errno)); + else log_err("%s: %s", str, strerror(errno)); } else { - log_err("str: %s", inf); + log_err("%s: %s", str, inf); } } } From 193401e7543a1e561dd634a3eaae932fa462a2b9 Mon Sep 17 00:00:00 2001 From: zhailiangliang Date: Wed, 3 Apr 2024 15:40:58 +0800 Subject: [PATCH 20/24] fix heap-buffer-overflow issue in function cfg_mark_ports of file util/config_file.c --- util/config_file.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/util/config_file.c b/util/config_file.c index 26185da02..e7b2f1959 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -1761,6 +1761,10 @@ cfg_mark_ports(const char* str, int allow, int* avail, int num) #endif if(!mid) { int port = atoi(str); + if(port < 0) { + log_err("Prevent out-of-bounds access to array avail"); + return 0; + } if(port == 0 && strcmp(str, "0") != 0) { log_err("cannot parse port number '%s'", str); return 0; From 103d9a68faa731db1269a5478b2a41475511e575 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 3 Apr 2024 10:03:04 +0200 Subject: [PATCH 21/24] Changelog note for #1040 - Fix #1040: fix heap-buffer-overflow issue in function cfg_mark_ports of file util/config_file.c. --- doc/Changelog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/Changelog b/doc/Changelog index 6392055cd..0b4efc9ff 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,7 @@ +3 April 2024: Wouter + - Fix #1040: fix heap-buffer-overflow issue in function cfg_mark_ports + of file util/config_file.c. + 28 March 2024: Wouter - Fix #1034: DoT forward-zone via unbound-control. - Fix for crypto related failures to have a better error string. From dfff8d23cf4145c58e5c1e99d4159d3a91a70ab7 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 3 Apr 2024 10:16:18 +0200 Subject: [PATCH 22/24] - For #1040: adjust error text and disallow negative ports in other parts of cfg_mark_ports. --- doc/Changelog | 2 ++ util/config_file.c | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/doc/Changelog b/doc/Changelog index 0b4efc9ff..db46a1a8e 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,8 @@ 3 April 2024: Wouter - Fix #1040: fix heap-buffer-overflow issue in function cfg_mark_ports of file util/config_file.c. + - For #1040: adjust error text and disallow negative ports in other + parts of cfg_mark_ports. 28 March 2024: Wouter - Fix #1034: DoT forward-zone via unbound-control. diff --git a/util/config_file.c b/util/config_file.c index e7b2f1959..74554286b 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -1762,7 +1762,7 @@ cfg_mark_ports(const char* str, int allow, int* avail, int num) if(!mid) { int port = atoi(str); if(port < 0) { - log_err("Prevent out-of-bounds access to array avail"); + log_err("port number is negative: %d", port); return 0; } if(port == 0 && strcmp(str, "0") != 0) { @@ -1774,6 +1774,10 @@ cfg_mark_ports(const char* str, int allow, int* avail, int num) } else { int i, low, high = atoi(mid+1); char buf[16]; + if(high < 0) { + log_err("port number is negative: %d", high); + return 0; + } if(high == 0 && strcmp(mid+1, "0") != 0) { log_err("cannot parse port number '%s'", mid+1); return 0; @@ -1786,10 +1790,18 @@ cfg_mark_ports(const char* str, int allow, int* avail, int num) memcpy(buf, str, (size_t)(mid-str)); buf[mid-str] = 0; low = atoi(buf); + if(low < 0) { + log_err("port number is negative: %d", low); + return 0; + } if(low == 0 && strcmp(buf, "0") != 0) { log_err("cannot parse port number '%s'", buf); return 0; } + if(high > num) { + /* Stop very high values from taking a long time. */ + high = num; + } for(i=low; i<=high; i++) { if(i < num) avail[i] = (allow?i:0); From 91e8e0e51168c490ab871a92d7bbed450e52cc94 Mon Sep 17 00:00:00 2001 From: Yorgos Thessalonikefs Date: Wed, 3 Apr 2024 13:37:57 +0200 Subject: [PATCH 23/24] - Fix #1035: Potential Bug while parsing port from the "stub-host" string; also affected forward-zones and remote-control host directives. --- doc/Changelog | 5 +++++ util/net_help.c | 28 ++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index db46a1a8e..f4a5d1cbd 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -4,6 +4,11 @@ - For #1040: adjust error text and disallow negative ports in other parts of cfg_mark_ports. +3 April 2024: Yorgos + - Fix #1035: Potential Bug while parsing port from the "stub-host" + string; also affected forward-zones and remote-control host + directives. + 28 March 2024: Wouter - Fix #1034: DoT forward-zone via unbound-control. - Fix for crypto related failures to have a better error string. diff --git a/util/net_help.c b/util/net_help.c index f38d843ed..d2218ea88 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -77,6 +77,8 @@ /** max length of an IP address (the address portion) that we allow */ #define MAX_ADDR_STRLEN 128 /* characters */ +/** max length of a hostname (with port and tls name) that we allow */ +#define MAX_HOST_STRLEN (LDNS_MAX_DOMAINLEN * 3) /* characters */ /** default value for EDNS ADVERTISED size */ uint16_t EDNS_ADVERTISED_SIZE = 4096; @@ -486,28 +488,38 @@ uint8_t* authextstrtodname(char* str, int* port, char** auth_name) *port = UNBOUND_DNS_PORT; *auth_name = NULL; if((s=strchr(str, '@'))) { + char buf[MAX_HOST_STRLEN]; + size_t len = (size_t)(s-str); char* hash = strchr(s+1, '#'); if(hash) { *auth_name = hash+1; } else { *auth_name = NULL; } + if(len >= MAX_HOST_STRLEN) { + return NULL; + } + (void)strlcpy(buf, str, sizeof(buf)); + buf[len] = 0; *port = atoi(s+1); if(*port == 0) { if(!hash && strcmp(s+1,"0")!=0) - return 0; + return NULL; if(hash && strncmp(s+1,"0#",2)!=0) - return 0; + return NULL; } - *s = 0; - dname = sldns_str2wire_dname(str, &dname_len); - *s = '@'; + dname = sldns_str2wire_dname(buf, &dname_len); } else if((s=strchr(str, '#'))) { + char buf[MAX_HOST_STRLEN]; + size_t len = (size_t)(s-str); + if(len >= MAX_HOST_STRLEN) { + return NULL; + } + (void)strlcpy(buf, str, sizeof(buf)); + buf[len] = 0; *port = UNBOUND_DNS_OVER_TLS_PORT; *auth_name = s+1; - *s = 0; - dname = sldns_str2wire_dname(str, &dname_len); - *s = '#'; + dname = sldns_str2wire_dname(buf, &dname_len); } else { dname = sldns_str2wire_dname(str, &dname_len); } From fb4a7d65d72b96fd2043a8d89243392291c9b743 Mon Sep 17 00:00:00 2001 From: Yorgos Thessalonikefs Date: Wed, 3 Apr 2024 15:18:13 +0200 Subject: [PATCH 24/24] - Fix #369: dnstap showing extra responses; for client responses right from the cache when replying with expired data or prefetching. --- daemon/worker.c | 2 +- doc/Changelog | 3 +++ testdata/dnstap.tdir/dnstap.conf | 2 ++ testdata/dnstap.tdir/dnstap.test | 40 ++++++++++++++++++++++++++++++ testdata/dnstap.tdir/dnstap.testns | 10 ++++++++ 5 files changed, 56 insertions(+), 1 deletion(-) diff --git a/daemon/worker.c b/daemon/worker.c index 1a0b9abde..0d240db14 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -1943,7 +1943,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, /* * sending src (client)/dst (local service) addresses over DNSTAP from send_reply code label (when we serviced local zone for ex.) */ - if(worker->dtenv.log_client_response_messages) { + if(worker->dtenv.log_client_response_messages && rc !=0) { log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr, repinfo->c->socket->addrlen); log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen); dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr, c->type, c->ssl, c->buffer); diff --git a/doc/Changelog b/doc/Changelog index f4a5d1cbd..237dada84 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -8,6 +8,9 @@ - Fix #1035: Potential Bug while parsing port from the "stub-host" string; also affected forward-zones and remote-control host directives. + - Fix #369: dnstap showing extra responses; for client responses + right from the cache when replying with expired data or + prefetching. 28 March 2024: Wouter - Fix #1034: DoT forward-zone via unbound-control. diff --git a/testdata/dnstap.tdir/dnstap.conf b/testdata/dnstap.tdir/dnstap.conf index 5e8dfaefb..fc382ccfd 100644 --- a/testdata/dnstap.tdir/dnstap.conf +++ b/testdata/dnstap.tdir/dnstap.conf @@ -12,6 +12,8 @@ server: do-not-query-localhost: no local-zone: "example.net." redirect local-data: "example.net. IN A 10.20.30.41" + serve-expired: yes + serve-expired-reply-ttl: 30 remote-control: control-enable: yes control-interface: 127.0.0.1 diff --git a/testdata/dnstap.tdir/dnstap.test b/testdata/dnstap.tdir/dnstap.test index 3a2dcc5e1..3ec9c77bd 100644 --- a/testdata/dnstap.tdir/dnstap.test +++ b/testdata/dnstap.tdir/dnstap.test @@ -81,6 +81,46 @@ for x in q1 q2 q3 q4 5 q6 q7 q8 q9 q10; do fi done +echo "> query for a short ttl record" +dig @127.0.0.1 -p $UNBOUND_PORT short.example.com. +echo "> wait for log to happen on timer" +sleep 3 +if grep "short.example.com" tap.log >/dev/null; then :; else sleep 1; fi +if grep "short.example.com" tap.log >/dev/null; then :; else sleep 1; fi +if grep "short.example.com" tap.log >/dev/null; then :; else sleep 1; fi +if grep "short.example.com" tap.log >/dev/null; then :; else sleep 1; fi +if grep "short.example.com" tap.log >/dev/null; then :; else sleep 1; fi +if grep "short.example.com" tap.log >/dev/null; then :; else sleep 10; fi +if grep "short.example.com" tap.log; then echo "yes it is in tap.log"; +else + echo "short.example.com. information not in tap.log" + echo "failed" + echo "> cat logfiles" + cat tap.log + cat tap.errlog + cat fwd.log + cat unbound.log + echo "Not OK" + exit 1 +fi +echo "> query again for the now expired record" +dig @127.0.0.1 -p $UNBOUND_PORT short.example.com. +echo "> wait for log to happen on timer" +sleep 3 +num_responses=`grep "short.example.com" tap.log | grep CLIENT_RESPONSE | wc -l` +# Responses should be 2 for the 2 distinct dig commands. +if test $num_responses -gt 2; then + echo "Duplicate client responses for short.example.com. in tap.log" + echo "failed" + echo "> cat logfiles" + cat tap.log + cat tap.errlog + cat fwd.log + cat unbound.log + echo "Not OK" + exit 1 +fi + echo "> cat logfiles" cat tap.log cat tap.errlog diff --git a/testdata/dnstap.tdir/dnstap.testns b/testdata/dnstap.tdir/dnstap.testns index 0c911ca5b..0987c41c8 100644 --- a/testdata/dnstap.tdir/dnstap.testns +++ b/testdata/dnstap.tdir/dnstap.testns @@ -12,6 +12,16 @@ SECTION ANSWER www IN A 10.20.30.40 ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +REPLY QR AA NOERROR +ADJUST copy_id +SECTION QUESTION +short IN A +SECTION ANSWER +short 2 IN A 10.20.30.40 +ENTRY_END + ENTRY_BEGIN MATCH opcode qtype qname REPLY QR AA SERVFAIL