]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
add validation EDEs to CD bit queries
authorTCY16 <tom@nlnetlabs.nl>
Mon, 5 Dec 2022 10:41:17 +0000 (11:41 +0100)
committerTCY16 <tom@nlnetlabs.nl>
Mon, 5 Dec 2022 10:41:17 +0000 (11:41 +0100)
services/mesh.c
testdata/ede.tdir/ede.test

index 9007b6e08c32fb605f7ce883aca42938797a2c3a..dcaa3cc3282ed93902b4ef6dc4635fed8a6af94a 100644 (file)
@@ -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;
index 5d478bd49cb2a7bf0203ad13506cf30d48f06075..0ce8b92a5f9e9712712265a287526739d9603027 100644 (file)
@@ -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