mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-02-02 11:49:28 -05:00
- Fix for consistent use of local zone CNAME alias for configured auth
zones. Now it also applies to downstream configured auth zones.
This commit is contained in:
parent
f066d6d453
commit
9201c75013
8 changed files with 145 additions and 28 deletions
|
|
@ -1818,8 +1818,9 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||
goto send_reply;
|
||||
}
|
||||
if(worker->env.auth_zones &&
|
||||
auth_zones_answer(worker->env.auth_zones, &worker->env,
|
||||
&qinfo, &edns, repinfo, c->buffer, worker->scratchpad)) {
|
||||
auth_zones_downstream_answer(worker->env.auth_zones,
|
||||
&worker->env, &qinfo, &edns, repinfo, c->buffer,
|
||||
worker->scratchpad)) {
|
||||
regional_free_all(worker->scratchpad);
|
||||
if(sldns_buffer_limit(c->buffer) == 0) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
|
|
@ -1872,20 +1873,11 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||
/* If we've found a local alias, replace the qname with the alias
|
||||
* target before resolving it. */
|
||||
if(qinfo.local_alias) {
|
||||
struct ub_packed_rrset_key* rrset = qinfo.local_alias->rrset;
|
||||
struct packed_rrset_data* d = rrset->entry.data;
|
||||
|
||||
/* Sanity check: our current implementation only supports
|
||||
* a single CNAME RRset as a local alias. */
|
||||
if(qinfo.local_alias->next ||
|
||||
rrset->rk.type != htons(LDNS_RR_TYPE_CNAME) ||
|
||||
d->count != 1) {
|
||||
log_err("assumption failure: unexpected local alias");
|
||||
if(!local_alias_shallow_copy_qname(qinfo.local_alias, &qinfo.qname,
|
||||
&qinfo.qname_len)) {
|
||||
regional_free_all(worker->scratchpad);
|
||||
return 0; /* drop it */
|
||||
}
|
||||
qinfo.qname = d->rr_data[0] + 2;
|
||||
qinfo.qname_len = d->rr_len[0] - 2;
|
||||
}
|
||||
|
||||
/* If we may apply IP-based actions to the answer, build the client
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
17 June 2025: Yorgos
|
||||
- Fix for consistent use of local zone CNAME alias for configured auth
|
||||
zones. Now it also applies to downstream configured auth zones.
|
||||
|
||||
16 June 2025: Wouter
|
||||
- Fix to check control-interface addresses in unbound-checkconf.
|
||||
- Fix #1295: Windows 32-bit binaries download seems to be missing dll
|
||||
|
|
|
|||
|
|
@ -630,8 +630,9 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
|
|||
free(qinfo.qname);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones,
|
||||
w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) {
|
||||
if(ctx->env->auth_zones && auth_zones_downstream_answer(
|
||||
ctx->env->auth_zones, w->env, &qinfo, &edns, NULL,
|
||||
w->back->udp_buff, w->env->scratch)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
libworker_fillup_fg(q, LDNS_RCODE_NOERROR,
|
||||
w->back->udp_buff, sec_status_insecure, NULL, 0);
|
||||
|
|
@ -709,8 +710,9 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
|
|||
w->back->udp_buff, sec_status_insecure, NULL, 0);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones,
|
||||
w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) {
|
||||
if(ctx->env->auth_zones && auth_zones_downstream_answer(
|
||||
ctx->env->auth_zones, w->env, &qinfo, &edns, NULL,
|
||||
w->back->udp_buff, w->env->scratch)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
free(qinfo.qname);
|
||||
libworker_event_done_cb(q, LDNS_RCODE_NOERROR,
|
||||
|
|
@ -847,8 +849,9 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
|
|||
free(qinfo.qname);
|
||||
return;
|
||||
}
|
||||
if(w->ctx->env->auth_zones && auth_zones_answer(w->ctx->env->auth_zones,
|
||||
w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) {
|
||||
if(w->ctx->env->auth_zones && auth_zones_downstream_answer(
|
||||
w->ctx->env->auth_zones, w->env, &qinfo, &edns, NULL,
|
||||
w->back->udp_buff, w->env->scratch)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
q->msg_security = sec_status_insecure;
|
||||
add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL, 0);
|
||||
|
|
|
|||
|
|
@ -3556,14 +3556,17 @@ auth_error_encode(struct query_info* qinfo, struct module_env* env,
|
|||
sldns_buffer_read_u16_at(buf, 2), edns);
|
||||
}
|
||||
|
||||
int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
||||
int auth_zones_downstream_answer(struct auth_zones* az, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns,
|
||||
struct comm_reply* repinfo, struct sldns_buffer* buf, struct regional* temp)
|
||||
struct comm_reply* repinfo, struct sldns_buffer* buf,
|
||||
struct regional* temp)
|
||||
{
|
||||
struct dns_msg* msg = NULL;
|
||||
struct auth_zone* z;
|
||||
int r;
|
||||
int fallback = 0;
|
||||
/* Copy the qinfo in case of cname aliasing from local-zone */
|
||||
struct query_info zqinfo = *qinfo;
|
||||
|
||||
lock_rw_rdlock(&az->lock);
|
||||
if(!az->have_downstream) {
|
||||
|
|
@ -3571,6 +3574,7 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
|||
lock_rw_unlock(&az->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(qinfo->qtype == LDNS_RR_TYPE_DS) {
|
||||
uint8_t* delname = qinfo->qname;
|
||||
size_t delnamelen = qinfo->qname_len;
|
||||
|
|
@ -3578,8 +3582,14 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
|||
z = auth_zones_find_zone(az, delname, delnamelen,
|
||||
qinfo->qclass);
|
||||
} else {
|
||||
z = auth_zones_find_zone(az, qinfo->qname, qinfo->qname_len,
|
||||
qinfo->qclass);
|
||||
if(zqinfo.local_alias && !local_alias_shallow_copy_qname(
|
||||
zqinfo.local_alias, &zqinfo.qname,
|
||||
&zqinfo.qname_len)) {
|
||||
lock_rw_unlock(&az->lock);
|
||||
return 0;
|
||||
}
|
||||
z = auth_zones_find_zone(az, zqinfo.qname, zqinfo.qname_len,
|
||||
zqinfo.qclass);
|
||||
}
|
||||
if(!z) {
|
||||
/* no zone above it */
|
||||
|
|
@ -3605,7 +3615,7 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
|||
}
|
||||
|
||||
/* answer it from zone z */
|
||||
r = auth_zone_generate_answer(z, qinfo, temp, &msg, &fallback);
|
||||
r = auth_zone_generate_answer(z, &zqinfo, temp, &msg, &fallback);
|
||||
lock_rw_unlock(&z->lock);
|
||||
if(!r && fallback) {
|
||||
/* fallback to regular answering (recursive) */
|
||||
|
|
|
|||
|
|
@ -550,9 +550,10 @@ int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
|
|||
* @param temp: temporary storage region.
|
||||
* @return false if not answered
|
||||
*/
|
||||
int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
||||
int auth_zones_downstream_answer(struct auth_zones* az, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns,
|
||||
struct comm_reply* repinfo, struct sldns_buffer* buf, struct regional* temp);
|
||||
struct comm_reply* repinfo, struct sldns_buffer* buf,
|
||||
struct regional* temp);
|
||||
|
||||
/**
|
||||
* Find the auth zone that is above the given qname.
|
||||
|
|
|
|||
82
testdata/local_cname.rpl
vendored
82
testdata/local_cname.rpl
vendored
|
|
@ -57,6 +57,14 @@ server:
|
|||
local-zone: synth.cname redirect
|
||||
local-data: "synth.cname. IN CNAME *.from.resolution."
|
||||
|
||||
# CNAME is pointing to a downstream auth zone
|
||||
local-zone: authdown.example.net. redirect
|
||||
local-data: "authdown.example.net. IN CNAME downstream.zone."
|
||||
|
||||
# CNAME is pointing to an upstream auth zone
|
||||
local-zone: authup.example.net. redirect
|
||||
local-data: "authup.example.net. IN CNAME upstream.zone."
|
||||
|
||||
### template zone and tag intended to be used for tests with CNAME and
|
||||
### other data.
|
||||
##local-zone: ambiguous.example.com redirect
|
||||
|
|
@ -67,14 +75,45 @@ server:
|
|||
##@TAGDATA1@
|
||||
##@TAGDATA2@
|
||||
|
||||
|
||||
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
|
||||
# send the queries to the test server (see the 10.0.10.3 entries below)
|
||||
forward-zone:
|
||||
name: "."
|
||||
forward-addr: 10.0.10.3
|
||||
|
||||
auth-zone:
|
||||
name: "downstream.zone."
|
||||
for-downstream: yes
|
||||
for-upstream: no
|
||||
fallback-enabled: no
|
||||
## this line generates zonefile: \n"/tmp/xxx.downstream.zone"\n
|
||||
zonefile:
|
||||
TEMPFILE_NAME downstream.zone
|
||||
## this is the inline file /tmp/xxx.downstream.zone
|
||||
## the tempfiles are deleted when the testrun is over.
|
||||
TEMPFILE_CONTENTS downstream.zone
|
||||
$ORIGIN downstream.zone.
|
||||
@ 3600 IN SOA a b 1 2 3 4 5
|
||||
@ IN TXT "hello from downstream auth zone"
|
||||
TEMPFILE_END
|
||||
|
||||
server: domain-insecure: upstream.zone.
|
||||
auth-zone:
|
||||
name: "upstream.zone."
|
||||
for-downstream: no
|
||||
for-upstream: yes
|
||||
fallback-enabled: no
|
||||
## this line generates zonefile: \n"/tmp/xxx.upstream.zone"\n
|
||||
zonefile:
|
||||
TEMPFILE_NAME upstream.zone
|
||||
## this is the inline file /tmp/xxx.upstream.zone
|
||||
## the tempfiles are deleted when the testrun is over.
|
||||
TEMPFILE_CONTENTS upstream.zone
|
||||
$ORIGIN upstream.zone.
|
||||
@ 3600 IN SOA a b 1 2 3 4 5
|
||||
@ IN TXT "hello from upstream auth zone"
|
||||
TEMPFILE_END
|
||||
CONFIG_END
|
||||
|
||||
; short one-line description of scenario:
|
||||
|
|
@ -525,5 +564,44 @@ SECTION AUTHORITY
|
|||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
STEP 290 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD DO
|
||||
SECTION QUESTION
|
||||
authdown.example.net. IN TXT
|
||||
ENTRY_END
|
||||
|
||||
STEP 300 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR AA RD RA DO NOERROR
|
||||
SECTION QUESTION
|
||||
authdown.example.net. IN TXT
|
||||
SECTION ANSWER
|
||||
authdown.example.net. IN CNAME downstream.zone.
|
||||
downstream.zone. IN TXT "hello from downstream auth zone"
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
STEP 310 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD DO
|
||||
SECTION QUESTION
|
||||
authup.example.net. IN TXT
|
||||
ENTRY_END
|
||||
|
||||
STEP 320 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR AA RD RA DO NOERROR
|
||||
SECTION QUESTION
|
||||
authup.example.net. IN TXT
|
||||
SECTION ANSWER
|
||||
authup.example.net. IN CNAME upstream.zone.
|
||||
upstream.zone. IN TXT "hello from upstream auth zone"
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
|
|
|
|||
|
|
@ -1471,3 +1471,22 @@ struct edns_option* edns_opt_list_find(struct edns_option* list, uint16_t code)
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int local_alias_shallow_copy_qname(struct local_rrset* local_alias, uint8_t** qname,
|
||||
size_t* qname_len)
|
||||
{
|
||||
struct ub_packed_rrset_key* rrset = local_alias->rrset;
|
||||
struct packed_rrset_data* d = rrset->entry.data;
|
||||
|
||||
/* Sanity check: our current implementation only supports
|
||||
* a single CNAME RRset as a local alias. */
|
||||
if(local_alias->next ||
|
||||
rrset->rk.type != htons(LDNS_RR_TYPE_CNAME) ||
|
||||
d->count != 1) {
|
||||
log_err("assumption failure: unexpected local alias");
|
||||
return 0;
|
||||
}
|
||||
*qname = d->rr_data[0] + 2;
|
||||
*qname_len = d->rr_len[0] - 2;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -801,4 +801,14 @@ int edns_opt_compare(struct edns_option* p, struct edns_option* q);
|
|||
*/
|
||||
int edns_opt_list_compare(struct edns_option* p, struct edns_option* q);
|
||||
|
||||
/**
|
||||
* Swallow copy the local_alias into the given qname and qname_len.
|
||||
* @param local_alias: the local_alias.
|
||||
* @param qname: the qname to copy to.
|
||||
* @param qname_len: the qname_len to copy to.
|
||||
* @return false on current local_alias assumptions, true otherwise.
|
||||
*/
|
||||
int local_alias_shallow_copy_qname(struct local_rrset* local_alias, uint8_t** qname,
|
||||
size_t* qname_len);
|
||||
|
||||
#endif /* UTIL_DATA_MSGREPLY_H */
|
||||
|
|
|
|||
Loading…
Reference in a new issue