From: TCY16 Date: Mon, 5 Dec 2022 10:41:17 +0000 (+0100) Subject: add validation EDEs to CD bit queries X-Git-Tag: release-1.18.0rc1~24^2~16^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dd3984eae94366451fe7a03fe16a21c06f534138;p=thirdparty%2Funbound.git add validation EDEs to CD bit queries --- diff --git a/services/mesh.c b/services/mesh.c index 9007b6e08..dcaa3cc32 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -1315,6 +1315,34 @@ mesh_is_udp(struct mesh_reply const* r) { return r->query_reply.c->type == comm_udp; } +static inline void +mesh_find_and_attach_ede_and_reason(struct mesh_state* m, + struct reply_info* rep, struct mesh_reply* r) { + char *reason = m->s.env->cfg->val_log_level >= 2 + ? errinf_to_str_bogus(&m->s) : NULL; + + /* During validation the EDE code can be received via two + * code paths. One code path fills the reply_info EDE, and + * the other fills it in the errinf_strlist. These paths + * intersect at some points, but where is opaque due to + * the complexity of the validator. At the time of writing + * we make the choice to prefer the EDE from errinf_strlist + * but a compelling reason to do otherwise is just as valid + */ + sldns_ede_code reason_bogus = errinf_to_reason_bogus(&m->s); + if ((reason_bogus == LDNS_EDE_DNSSEC_BOGUS && + rep->reason_bogus != LDNS_EDE_NONE) || + reason_bogus == LDNS_EDE_NONE) { + reason_bogus = rep->reason_bogus; + } + + if(reason_bogus != LDNS_EDE_NONE) { + edns_opt_list_append_ede(&r->edns.opt_list_out, + m->s.region, reason_bogus, reason); + } + free(reason); +} + /** * Send reply to mesh reply entry * @param m: mesh state to send it for. @@ -1406,35 +1434,14 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, &r->edns, &r->query_reply, m->s.region, &r->start_time)) r->edns.opt_list_inplace_cb_out = NULL; } - /* Send along EDE BOGUS EDNS0 option when answer is bogus */ + /* Send along EDE BOGUS EDNS0 option when validation is bogus */ if(m->s.env->cfg->ede && rcode == LDNS_RCODE_SERVFAIL && m->s.env->need_to_validate && (!(r->qflags&BIT_CD) || m->s.env->cfg->ignore_cd) && rep && (rep->security <= sec_status_bogus || rep->security == sec_status_secure_sentinel_fail)) { - char *reason = m->s.env->cfg->val_log_level >= 2 - ? errinf_to_str_bogus(&m->s) : NULL; - - /* During validation the EDE code can be received via two - * code paths. One code path fills the reply_info EDE, and - * the other fills it in the errinf_strlist. These paths - * intersect at some points, but where is opaque due to - * the complexity of the validator. At the time of writing - * we make the choice to prefer the EDE from errinf_strlist - * but a compelling reason to do otherwise is just as valid - */ - sldns_ede_code reason_bogus = errinf_to_reason_bogus(&m->s); - if ((reason_bogus == LDNS_EDE_DNSSEC_BOGUS && - rep->reason_bogus != LDNS_EDE_NONE) || - reason_bogus == LDNS_EDE_NONE) { - reason_bogus = rep->reason_bogus; - } - - if(reason_bogus != LDNS_EDE_NONE) { - edns_opt_list_append_ede(&r->edns.opt_list_out, - m->s.region, reason_bogus, reason); - } - free(reason); + + mesh_find_and_attach_ede_and_reason(m, rep, r); } error_encode(r_buffer, rcode, &m->s.qinfo, r->qid, r->qflags, &r->edns); @@ -1449,6 +1456,14 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, r->edns.bits &= EDNS_DO; m->s.qinfo.qname = r->qname; m->s.qinfo.local_alias = r->local_alias; + + /* Attach EDE without servfail if the validation failed */ + if (m->s.env->cfg->ede && rep && + (rep->security <= sec_status_bogus || + rep->security == sec_status_secure_sentinel_fail)) { + mesh_find_and_attach_ede_and_reason(m, rep, r); + } + if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, LDNS_RCODE_NOERROR, &r->edns, &r->query_reply, m->s.region, &r->start_time) || !reply_info_answer_encode(&m->s.qinfo, rep, r->qid, @@ -1464,6 +1479,9 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, error_encode(r_buffer, LDNS_RCODE_SERVFAIL, &m->s.qinfo, r->qid, r->qflags, &r->edns); } + + /* Send along EDE BOGUS EDNS0 option when validation is bogus */ + m->reply_list = NULL; comm_point_send_reply(&r->query_reply); m->reply_list = rlist; diff --git a/testdata/ede.tdir/ede.test b/testdata/ede.tdir/ede.test index 5d478bd49..0ce8b92a5 100644 --- a/testdata/ede.tdir/ede.test +++ b/testdata/ede.tdir/ede.test @@ -68,5 +68,14 @@ then exit 1 fi +# EDE with CD bit set (EDE but no SERVFAIL) +dig @127.0.0.1 -p $UNBOUND_PORT cd.dnskey-failures.test +cd > cd_bit_ede.txt -# @TODO DNSSEC indeterminate when implemented +if ! grep -q -e "OPT=15: 00 09" -e "EDE: 9" cd_bit_ede.txt +then + echo "No EDE attached with CD bit set" + cat cd_bit_ede.txt + exit 1 +fi + +# TODO DNSSEC indeterminate when implemented