]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
add DNSKEY EDE code
authorTCY16 <tom@nlnetlabs.nl>
Fri, 8 Oct 2021 13:54:10 +0000 (15:54 +0200)
committerTCY16 <tom@nlnetlabs.nl>
Fri, 8 Oct 2021 13:54:10 +0000 (15:54 +0200)
services/mesh.c
util/config_file.c
util/config_file.h
validator/val_sigcrypt.c
validator/val_utils.c
validator/val_utils.h
validator/validator.c

index 991dcce7d961353ed2844769671da34586d66e07..4f1cb83d97b1a9f21b2c40393a792527c7741cb0 100644 (file)
@@ -1280,9 +1280,11 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
 
                        char *reason = m->s.env->cfg->val_log_level >= 2
                                     ? errinf_to_str_bogus(&m->s) : NULL;
+                       sldns_ede_code reason_bogus = rep->reason_bogus != LDNS_EDE_DNSSEC_BOGUS
+                                                   ? rep->reason_bogus : errinf_to_reason_bogus(&m->s);
 
                        edns_opt_append_ede(&r->edns, m->s.region,
-                                       rep->reason_bogus, reason);
+                                       reason_bogus, reason);
                        free(reason);
                }
                error_encode(r_buffer, rcode, &m->s.qinfo, r->qid,
index 50b0e645af8f4d9d68791a733a5e722a0493b25f..1a8f5ada81cc641f126943a425a628fd3fbb42c0 100644 (file)
@@ -2542,6 +2542,7 @@ void errinf(struct module_qstate* qstate, const char* str)
        }
        p->next = NULL;
        p->str = regional_strdup(qstate->region, str);
+       p->reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
        if(!p->str) {
                log_err("malloc failure in validator-error-info string");
                return;
@@ -2549,7 +2550,34 @@ void errinf(struct module_qstate* qstate, const char* str)
        /* add at end */
        if(qstate->errinf) {
                struct config_strlist* q = qstate->errinf;
-               while(q->next) 
+               while(q->next)
+                       q = q->next;
+               q->next = p;
+       } else  qstate->errinf = p;
+}
+
+void errinf_ede(struct module_qstate* qstate,
+       const char* str, sldns_ede_code reason_bogus)
+{
+       struct config_strlist* p;
+       if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !str)
+               return;
+       p = (struct config_strlist*)regional_alloc(qstate->region, sizeof(*p));
+       if(!p) {
+               log_err("malloc failure in validator-error-info string");
+               return;
+       }
+       p->next = NULL;
+       p->str = regional_strdup(qstate->region, str);
+       p->reason_bogus = reason_bogus;
+       if(!p->str) {
+               log_err("malloc failure in validator-error-info string");
+               return;
+       }
+       /* add at end */
+       if(qstate->errinf) {
+               struct config_strlist* q = qstate->errinf;
+               while(q->next)
                        q = q->next;
                q->next = p;
        } else  qstate->errinf = p;
@@ -2600,6 +2628,17 @@ char* errinf_to_str_bogus(struct module_qstate* qstate)
        return p;
 }
 
+sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate)
+{
+       struct config_strlist* s;
+       for(s=qstate->errinf; s; s=s->next) {
+               if (s->reason_bogus != LDNS_EDE_DNSSEC_BOGUS) {
+                       return s->reason_bogus;
+               }
+       }
+       return LDNS_EDE_DNSSEC_BOGUS;
+}
+
 char* errinf_to_str_servfail(struct module_qstate* qstate)
 {
        char buf[20480];
index b868d9cc8f96fe76acb2dd6432d0858060a3ea04..a7b759e9303d00cbfebba48eab9091c14be476d3 100644 (file)
@@ -41,6 +41,7 @@
 
 #ifndef UTIL_CONFIG_FILE_H
 #define UTIL_CONFIG_FILE_H
+#include "sldns/rrdef.h"
 struct config_stub;
 struct config_auth;
 struct config_view;
@@ -784,6 +785,8 @@ struct config_strlist {
        struct config_strlist* next;
        /** config option string */
        char* str;
+       /** EDE code companion to the error str */
+       sldns_ede_code reason_bogus;
 };
 
 /**
@@ -1233,6 +1236,8 @@ char* cfg_ptr_reverse(char* str);
  * Failures to allocate are logged.
  */
 void errinf(struct module_qstate* qstate, const char* str);
+void errinf_ede(struct module_qstate* qstate, const char* str,
+                sldns_ede_code reason_bogus);
 
 /**
  * Append text to error info:  from 1.2.3.4
@@ -1268,6 +1273,9 @@ void errinf_dname(struct module_qstate* qstate, const char* str,
  */
 char* errinf_to_str_bogus(struct module_qstate* qstate);
 
+// @TODO write this
+sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate);
+
 /**
  * Create error info in string.  For other servfails.
  * @param qstate: query state.
index 67db8cfe469e6ff1150497c12afde0afa1bf5e82..777376c1fd997ff8653568f85d21562cced644e6 100644 (file)
@@ -645,7 +645,8 @@ dnskey_verify_rrset_ede(struct module_env* env, struct val_env* ve,
                verbose(VERB_QUERY, "rrset failed to verify due to a lack of "
                        "signatures");
                *reason = "no signatures";
-               // @TODO ADD EDE 10
+               if(reason_bogus)
+                       *reason_bogus = LDNS_EDE_RRSIGS_MISSING;
                return sec_status_bogus;
        }
        for(i=0; i<num; i++) {
@@ -654,6 +655,7 @@ dnskey_verify_rrset_ede(struct module_env* env, struct val_env* ve,
                        tag != rrset_get_sig_keytag(rrset, i))
                        continue;
                buf_canon = 0;
+               // @TODO should this be _ede verion as well?
                sec = dnskey_verify_rrset_sig(env->scratch, 
                        env->scratch_buffer, ve, *env->now, rrset, 
                        dnskey, dnskey_idx, i, &sortree, &buf_canon, reason,
index e94a1bb9fb3d897c80bb9e5d93ffd3be1bc12842..2fa0b37e1a1fd241afe6e8fd2e6d8dc664db141a 100644 (file)
@@ -421,11 +421,23 @@ val_verify_rrset_entry_ede(struct module_env* env, struct val_env* ve,
 }
 
 /** verify that a DS RR hashes to a key and that key signs the set */
+#if 0
 static enum sec_status
 verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve, 
        struct ub_packed_rrset_key* dnskey_rrset, 
         struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, char** reason,
        struct module_qstate* qstate)
+{
+       return verify_dnskeys_with_ds_rr_ede( env, ve, dnskey_rrset, ds_rrset,
+               ds_idx, reason, NULL, qstate);
+}
+#endif
+
+static enum sec_status
+verify_dnskeys_with_ds_rr_ede(struct module_env* env, struct val_env* ve,
+       struct ub_packed_rrset_key* dnskey_rrset,
+        struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, char** reason,
+       sldns_ede_code *reason_bogus, struct module_qstate* qstate)
 {
        enum sec_status sec = sec_status_bogus;
        size_t i, num, numchecked = 0, numhashok = 0, numsizesupp = 0;
@@ -460,8 +472,8 @@ verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
 
                /* Otherwise, we have a match! Make sure that the DNSKEY 
                 * verifies *with this key*  */
-               sec = dnskey_verify_rrset(env, ve, dnskey_rrset, 
-                       dnskey_rrset, i, reason, LDNS_SECTION_ANSWER, qstate);
+               sec = dnskey_verify_rrset_ede(env, ve, dnskey_rrset, dnskey_rrset,
+                       i, reason, reason_bogus, LDNS_SECTION_ANSWER, qstate);
                if(sec == sec_status_secure) {
                        return sec;
                }
@@ -498,11 +510,22 @@ int val_favorite_ds_algo(struct ub_packed_rrset_key* ds_rrset)
        return digest_algo;
 }
 
-enum sec_status 
+// @TODO change the use of this function to _ede function in authzone.c:8111
+enum sec_status
 val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
        struct ub_packed_rrset_key* dnskey_rrset,
        struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason,
        struct module_qstate* qstate)
+{
+       return val_verify_DNSKEY_with_DS_ede(env, ve, dnskey_rrset, ds_rrset,
+               sigalg, reason, NULL, qstate);
+}
+
+enum sec_status
+val_verify_DNSKEY_with_DS_ede(struct module_env* env, struct val_env* ve,
+       struct ub_packed_rrset_key* dnskey_rrset,
+       struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason,
+       sldns_ede_code *reason_bogus, struct module_qstate* qstate)
 {
        /* as long as this is false, we can consider this DS rrset to be
         * equivalent to no DS rrset. */
@@ -538,8 +561,8 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
                        continue;
                }
 
-               sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
-                       ds_rrset, i, reason, qstate);
+               sec = verify_dnskeys_with_ds_rr_ede(env, ve, dnskey_rrset,
+                       ds_rrset, i, reason, reason_bogus, qstate);
                if(sec == sec_status_insecure)
                        continue;
 
@@ -582,15 +605,26 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
        return sec_status_bogus;
 }
 
-struct key_entry_key* 
+struct key_entry_key*
 val_verify_new_DNSKEYs(struct regional* region, struct module_env* env, 
        struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, 
        struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason,
        struct module_qstate* qstate)
 {
+       return val_verify_new_DNSKEYs_ede(region, env, ve,dnskey_rrset, ds_rrset,
+               downprot, reason, NULL, qstate);
+}
+
+struct key_entry_key*
+val_verify_new_DNSKEYs_ede(struct regional* region, struct module_env* env, 
+       struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, 
+       struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason,
+       sldns_ede_code *reason_bogus, struct module_qstate* qstate)
+{      
        uint8_t sigalg[ALGO_NEEDS_MAX+1];
-       enum sec_status sec = val_verify_DNSKEY_with_DS(env, ve, 
-               dnskey_rrset, ds_rrset, downprot?sigalg:NULL, reason, qstate);
+       enum sec_status sec = val_verify_DNSKEY_with_DS_ede(env, ve, 
+               dnskey_rrset, ds_rrset, downprot?sigalg:NULL, reason, 
+               reason_bogus, qstate);
 
        if(sec == sec_status_secure) {
                return key_entry_create_rrset(region, 
@@ -608,12 +642,23 @@ val_verify_new_DNSKEYs(struct regional* region, struct module_env* env,
                BOGUS_KEY_TTL, *env->now);
 }
 
-enum sec_status 
+enum sec_status
 val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
        struct ub_packed_rrset_key* dnskey_rrset,
        struct ub_packed_rrset_key* ta_ds,
        struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason,
        struct module_qstate* qstate)
+{
+       return val_verify_DNSKEY_with_TA_ede(env, ve, dnskey_rrset, ta_ds,
+               ta_dnskey, sigalg, reason, NULL, qstate);
+}
+
+enum sec_status
+val_verify_DNSKEY_with_TA_ede(struct module_env* env, struct val_env* ve,
+       struct ub_packed_rrset_key* dnskey_rrset,
+       struct ub_packed_rrset_key* ta_ds,
+       struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason,
+       sldns_ede_code *reason_bogus, struct module_qstate* qstate)
 {
        /* as long as this is false, we can consider this anchor to be
         * equivalent to no anchor. */
@@ -628,6 +673,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
                verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset "
                        "by name");
                *reason = "DNSKEY RRset did not match DS RRset by name";
+               if (reason_bogus)
+                       *reason_bogus = LDNS_EDE_DNSKEY_MISSING;
                return sec_status_bogus;
        }
        if(ta_dnskey && (dnskey_rrset->rk.dname_len != ta_dnskey->rk.dname_len
@@ -636,6 +683,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
                verbose(VERB_QUERY, "DNSKEY RRset did not match anchor RRset "
                        "by name");
                *reason = "DNSKEY RRset did not match anchor RRset by name";
+               if (reason_bogus)
+                       *reason_bogus = LDNS_EDE_DNSKEY_MISSING;
                return sec_status_bogus;
        }
 
@@ -658,8 +707,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
                        ds_get_digest_algo(ta_ds, i) != digest_algo)
                        continue;
 
-               sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
-                       ta_ds, i, reason, qstate);
+               sec = verify_dnskeys_with_ds_rr_ede(env, ve, dnskey_rrset,
+                       ta_ds, i, reason, reason_bogus, qstate);
                if(sec == sec_status_insecure)
                        continue;
 
@@ -732,26 +781,39 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
        return sec_status_bogus;
 }
 
+#if 0
 struct key_entry_key* 
 val_verify_new_DNSKEYs_with_ta(struct regional* region, struct module_env* env,
        struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, 
        struct ub_packed_rrset_key* ta_ds_rrset,
        struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot,
        char** reason, struct module_qstate* qstate)
+{
+       return val_verify_rrset_entry_ede(region, env, ve, dnskey_rrset,
+               ta_ds_rrset, ta_dnskey_rrset,downprot, reason, NULL, qstate);
+}
+#endif
+
+struct key_entry_key* 
+val_verify_new_DNSKEYs_with_ta_ede(struct regional* region, struct module_env* env,
+       struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
+       struct ub_packed_rrset_key* ta_ds_rrset,
+       struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot,
+       char** reason, sldns_ede_code *reason_bogus, struct module_qstate* qstate)
 {
        uint8_t sigalg[ALGO_NEEDS_MAX+1];
-       enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve, 
+       enum sec_status sec = val_verify_DNSKEY_with_TA_ede(env, ve,
                dnskey_rrset, ta_ds_rrset, ta_dnskey_rrset,
-               downprot?sigalg:NULL, reason, qstate);
+               downprot?sigalg:NULL, reason, reason_bogus, qstate);
 
        if(sec == sec_status_secure) {
-               return key_entry_create_rrset(region, 
+               return key_entry_create_rrset(region,
                        dnskey_rrset->rk.dname, dnskey_rrset->rk.dname_len,
                        ntohs(dnskey_rrset->rk.rrset_class), dnskey_rrset,
                        downprot?sigalg:NULL, *env->now);
        } else if(sec == sec_status_insecure) {
                return key_entry_create_null(region, dnskey_rrset->rk.dname,
-                       dnskey_rrset->rk.dname_len, 
+                       dnskey_rrset->rk.dname_len,
                        ntohs(dnskey_rrset->rk.rrset_class),
                        rrset_get_ttl(dnskey_rrset), *env->now);
        }
@@ -760,7 +822,7 @@ val_verify_new_DNSKEYs_with_ta(struct regional* region, struct module_env* env,
                BOGUS_KEY_TTL, *env->now);
 }
 
-int 
+int
 val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset)
 {
        size_t i;
index b7b0aea1b33aad0d260983b16ad7051a4c61597c..1c22a88948bea0f29d31b1931b46f1bd2ebf138a 100644 (file)
@@ -177,6 +177,11 @@ enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
        struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason,
        struct module_qstate* qstate);
 
+enum sec_status val_verify_DNSKEY_with_DS_ede(struct module_env* env,
+    struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
+    struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason,
+    sldns_ede_code *reason_bogus, struct module_qstate* qstate);
+
 /**
  * Verify DNSKEYs with DS and DNSKEY rrset.  Like val_verify_DNSKEY_with_DS
  * but for a trust anchor.
@@ -200,6 +205,12 @@ enum sec_status val_verify_DNSKEY_with_TA(struct module_env* env,
        struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason,
        struct module_qstate* qstate);
 
+enum sec_status val_verify_DNSKEY_with_TA_ede(struct module_env* env,
+    struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
+    struct ub_packed_rrset_key* ta_ds,
+    struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason,
+    sldns_ede_code *reason_bogus, struct module_qstate* qstate);
+
 /**
  * Verify new DNSKEYs with DS rrset. The DS contains hash values that should
  * match the DNSKEY keys.
@@ -230,6 +241,11 @@ struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region,
        struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason,
        struct module_qstate* qstate);
 
+struct key_entry_key* val_verify_new_DNSKEYs_ede(struct regional* region,
+    struct module_env* env, struct val_env* ve,
+    struct ub_packed_rrset_key* dnskey_rrset, 
+    struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason,
+    sldns_ede_code *reason_bogus, struct module_qstate* qstate);
 
 /**
  * Verify rrset with trust anchor: DS and DNSKEY rrset.
@@ -261,6 +277,13 @@ struct key_entry_key* val_verify_new_DNSKEYs_with_ta(struct regional* region,
        struct ub_packed_rrset_key* ta_dnskey_rrset,
        int downprot, char** reason, struct module_qstate* qstate);
 
+struct key_entry_key* val_verify_new_DNSKEYs_with_ta_ede(struct regional* region, 
+    struct module_env* env, struct val_env* ve,
+    struct ub_packed_rrset_key* dnskey_rrset,
+    struct ub_packed_rrset_key* ta_ds_rrset,
+    struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot,
+    char** reason, sldns_ede_code *reason_bogus, struct module_qstate* qstate);
+
 /**
  * Determine if DS rrset is usable for validator or not.
  * Returns true if the algorithms for key and DShash are supported,
index 309128fcdf30b5839dac9ad08c57de4bacce48b6..c5e351e8396ed4b71c6717cdcc2bc9a1c7c11d07 100644 (file)
@@ -1720,6 +1720,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id)
                        vq->chase_reply->reason_bogus = LDNS_EDE_RRSIGS_MISSING;
                        errinf_origin(qstate, qstate->reply_origin);
                        vq->chase_reply->security = sec_status_bogus;
+                       // @TODO add EDE 10 - RRSIGs Missing
                        vq->state = VAL_FINISHED_STATE;
                        return 1;
                }
@@ -2313,6 +2314,7 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
        struct key_entry_key* kkey = NULL;
        enum sec_status sec = sec_status_unchecked;
        char* reason = NULL;
+       sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
        int downprot = qstate->env->cfg->harden_algo_downgrade;
 
        if(!dnskey_rrset) {
@@ -2334,9 +2336,9 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
                return kkey;
        }
        /* attempt to verify with trust anchor DS and DNSKEY */
-       kkey = val_verify_new_DNSKEYs_with_ta(qstate->region, qstate->env, ve, 
+       kkey = val_verify_new_DNSKEYs_with_ta_ede(qstate->region, qstate->env, ve, 
                dnskey_rrset, ta->ds_rrset, ta->dnskey_rrset, downprot,
-               &reason, qstate);
+               &reason, &reason_bogus, qstate);
        if(!kkey) {
                log_err("out of memory: verifying prime TA");
                return NULL;
@@ -2355,7 +2357,8 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
                /* NOTE: in this case, we should probably reject the trust 
                 * anchor for longer, perhaps forever. */
                if(qstate->env->cfg->harden_dnssec_stripped) {
-                       errinf(qstate, reason);
+                       // errinf(qstate, reason);
+                       errinf_ede(qstate, reason, reason_bogus);
                        kkey = key_entry_create_bad(qstate->region, ta->name,
                                ta->namelen, ta->dclass, BOGUS_KEY_TTL,
                                *qstate->env->now);
@@ -2706,6 +2709,9 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
                /* bad response */
                verbose(VERB_DETAIL, "Missing DNSKEY RRset in response to "
                        "DNSKEY query.");
+
+               // @TODO add EDE 9 - DNSKEY Missing
+
                if(vq->restart_count < ve->max_restart) {
                        val_blacklist(&vq->chain_blacklist, qstate->region,
                                origin, 1);
@@ -2733,6 +2739,7 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
                return;
        }
        downprot = qstate->env->cfg->harden_algo_downgrade;
+       // @TODO add _ede
        vq->key_entry = val_verify_new_DNSKEYs(qstate->region, qstate->env,
                ve, dnskey, vq->ds_rrset, downprot, &reason, qstate);