]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
First step towards specific EDE DNSSEC errors
authorTom Carpay <tom@nlnetlabs.nl>
Tue, 14 Sep 2021 07:45:51 +0000 (07:45 +0000)
committerTom Carpay <tom@nlnetlabs.nl>
Tue, 14 Sep 2021 07:45:51 +0000 (07:45 +0000)
validator/val_sigcrypt.c
validator/val_sigcrypt.h
validator/val_utils.c
validator/val_utils.h
validator/validator.c

index b15fba3f499d44951b5cea0d65392cc42afe4940..08a963058e056015fb7c77fc6fcd40c647bc8ada 100644 (file)
@@ -530,6 +530,24 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
        struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
        uint8_t* sigalg, char** reason, sldns_pkt_section section, 
        struct module_qstate* qstate)
+{
+       return dnskeyset_verify_rrset_ede(
+               env, ve, rrset, dnskey, sigalg, reason, NULL, section, qstate);
+}
+
+static enum sec_status 
+dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve, 
+       time_t now, struct ub_packed_rrset_key* rrset, 
+       struct ub_packed_rrset_key* dnskey, size_t sig_idx, 
+       struct rbtree_type** sortree,
+       char** reason, sldns_ede_code *reason_bogus,
+       sldns_pkt_section section, struct module_qstate* qstate);
+
+enum sec_status 
+dnskeyset_verify_rrset_ede(struct module_env* env, struct val_env* ve,
+       struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
+       uint8_t* sigalg, char** reason, sldns_ede_code *reason_bogus,
+       sldns_pkt_section section, struct module_qstate* qstate)
 {
        enum sec_status sec;
        size_t i, num;
@@ -543,6 +561,8 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
                verbose(VERB_QUERY, "rrset failed to verify due to a lack of "
                        "signatures");
                *reason = "no signatures";
+               if (reason_bogus)
+                       *reason_bogus = LDNS_EDE_RRSIGS_MISSING;
                return sec_status_bogus;
        }
 
@@ -551,12 +571,15 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
                if(algo_needs_num_missing(&needs) == 0) {
                        verbose(VERB_QUERY, "zone has no known algorithms");
                        *reason = "zone has no known algorithms";
+                       if (reason_bogus)
+                               *reason_bogus = LDNS_EDE_UNSUPPORTED_DNSKEY_ALG;
                        return sec_status_insecure;
                }
        }
        for(i=0; i<num; i++) {
                sec = dnskeyset_verify_rrset_sig(env, ve, *env->now, rrset, 
-                       dnskey, i, &sortree, reason, section, qstate);
+                       dnskey, i, &sortree, reason, reason_bogus,
+                       section, qstate);
                /* see which algorithm has been fixed up */
                if(sec == sec_status_secure) {
                        if(!sigalg)
@@ -633,12 +656,22 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
        return sec_status_bogus;
 }
 
-enum sec_status 
+static enum sec_status 
+dnskey_verify_rrset_sig_ede(struct regional* region, sldns_buffer* buf, 
+       struct val_env* ve, time_t now,
+        struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
+        size_t dnskey_idx, size_t sig_idx,
+       struct rbtree_type** sortree, int* buf_canon,
+       char** reason, sldns_ede_code *reason_bogus,
+       sldns_pkt_section section, struct module_qstate* qstate);
+
+static enum sec_status 
 dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve, 
        time_t now, struct ub_packed_rrset_key* rrset, 
        struct ub_packed_rrset_key* dnskey, size_t sig_idx, 
-       struct rbtree_type** sortree, char** reason, sldns_pkt_section section,
-       struct module_qstate* qstate)
+       struct rbtree_type** sortree,
+       char** reason, sldns_ede_code *reason_bogus,
+       sldns_pkt_section section, struct module_qstate* qstate)
 {
        /* find matching keys and check them */
        enum sec_status sec = sec_status_bogus;
@@ -661,9 +694,10 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
                numchecked ++;
 
                /* see if key verifies */
-               sec = dnskey_verify_rrset_sig(env->scratch, 
+               sec = dnskey_verify_rrset_sig_ede(env->scratch, 
                        env->scratch_buffer, ve, now, rrset, dnskey, i, 
-                       sig_idx, sortree, &buf_canon, reason, section, qstate);
+                       sig_idx, sortree, &buf_canon, reason, reason_bogus,
+                       section, qstate);
                if(sec == sec_status_secure)
                        return sec;
        }
@@ -1361,8 +1395,8 @@ subtract_1982(uint32_t a, uint32_t b)
 
 /** check rrsig dates */
 static int
-check_dates(struct val_env* ve, uint32_t unow,
-       uint8_t* expi_p, uint8_t* incep_p, char** reason)
+check_dates(struct val_env* ve, uint32_t unow, uint8_t* expi_p,
+               uint8_t* incep_p, char** reason, sldns_ede_code *reason_bogus)
 {
        /* read out the dates */
        uint32_t expi, incep, now;
@@ -1386,6 +1420,7 @@ check_dates(struct val_env* ve, uint32_t unow,
                sigdate_error("verify: inception after expiration, "
                        "signature bad", expi, incep, now);
                *reason = "signature inception after expiration";
+               /* @TODO Tom, wat hier te doen? */
                return 0;
        }
        if(compare_1982(incep, now) > 0) {
@@ -1397,6 +1432,8 @@ check_dates(struct val_env* ve, uint32_t unow,
                        sigdate_error("verify: signature bad, current time is"
                                " before inception date", expi, incep, now);
                        *reason = "signature before inception date";
+                       if (reason_bogus)
+                               *reason_bogus = LDNS_EDE_SIGNATURE_NOT_YET_VALID;
                        return 0;
                }
                sigdate_error("verify warning suspicious signature inception "
@@ -1410,6 +1447,8 @@ check_dates(struct val_env* ve, uint32_t unow,
                        sigdate_error("verify: signature expired", expi, 
                                incep, now);
                        *reason = "signature expired";
+                       if (reason_bogus)
+                               *reason_bogus = LDNS_EDE_SIGNATURE_EXPIRED;
                        return 0;
                }
                sigdate_error("verify warning suspicious signature expiration "
@@ -1475,6 +1514,20 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
         size_t dnskey_idx, size_t sig_idx,
        struct rbtree_type** sortree, int* buf_canon, char** reason,
        sldns_pkt_section section, struct module_qstate* qstate)
+{
+       return dnskey_verify_rrset_sig_ede(region, buf, ve, now, rrset, dnskey,
+                       dnskey_idx, sig_idx, sortree, buf_canon, reason, NULL,
+                       section, qstate);
+}
+
+static enum sec_status 
+dnskey_verify_rrset_sig_ede(struct regional* region, sldns_buffer* buf, 
+       struct val_env* ve, time_t now,
+        struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
+        size_t dnskey_idx, size_t sig_idx,
+       struct rbtree_type** sortree, int* buf_canon,
+       char** reason, sldns_ede_code *reason_bogus,
+       sldns_pkt_section section, struct module_qstate* qstate)
 {
        enum sec_status sec;
        uint8_t* sig;           /* RRSIG rdata */
@@ -1498,6 +1551,8 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
        if(!(dnskey_get_flags(dnskey, dnskey_idx) & DNSKEY_BIT_ZSK)) {
                verbose(VERB_QUERY, "verify: dnskey without ZSK flag");
                *reason = "dnskey without ZSK flag";
+               if(reason_bogus)
+                       *reason_bogus = LDNS_EDE_NO_ZONE_KEY_BIT_SET;
                return sec_status_bogus; 
        }
 
@@ -1598,7 +1653,8 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
                /* verify inception, expiration dates 
                 * Do this last so that if you ignore expired-sigs the
                 * rest is sure to be OK. */
-               if(!check_dates(ve, now, sig+2+8, sig+2+12, reason)) {
+               if(!check_dates(ve, now, sig+2+8, sig+2+12,
+                                       reason, reason_bogus)) {
                        return sec_status_bogus;
                }
        }
index bbb95780d7fe69a747bba8fd657672706d2fc1ee..af16c293c20679f5b91ae387eb6f2a6a14cec37e 100644 (file)
@@ -45,6 +45,7 @@
 #define VALIDATOR_VAL_SIGCRYPT_H
 #include "util/data/packed_rrset.h"
 #include "sldns/pkthdr.h"
+#include "sldns/rrdef.h"
 struct val_env;
 struct module_env;
 struct module_qstate;
@@ -266,6 +267,12 @@ enum sec_status dnskeyset_verify_rrset(struct module_env* env,
        struct val_env* ve, struct ub_packed_rrset_key* rrset, 
        struct ub_packed_rrset_key* dnskey, uint8_t* sigalg, char** reason,
        sldns_pkt_section section, struct module_qstate* qstate);
+enum sec_status dnskeyset_verify_rrset_ede(struct module_env* env, 
+       struct val_env* ve, struct ub_packed_rrset_key* rrset, 
+       struct ub_packed_rrset_key* dnskey, uint8_t* sigalg,
+       char** reason, sldns_ede_code *reason_bogus,
+       sldns_pkt_section section, struct module_qstate* qstate);
+
 
 /** 
  * verify rrset against one specific dnskey (from rrset) 
@@ -285,6 +292,7 @@ enum sec_status dnskey_verify_rrset(struct module_env* env,
        struct ub_packed_rrset_key* dnskey, size_t dnskey_idx, char** reason,
        sldns_pkt_section section, struct module_qstate* qstate);
 
+#if 0
 /** 
  * verify rrset, with dnskey rrset, for a specific rrsig in rrset
  * @param env: module environment, scratch space is used.
@@ -306,6 +314,7 @@ enum sec_status dnskeyset_verify_rrset_sig(struct module_env* env,
        struct ub_packed_rrset_key* dnskey, size_t sig_idx, 
        struct rbtree_type** sortree, char** reason, sldns_pkt_section section,
        struct module_qstate* qstate);
+#endif
 
 /** 
  * verify rrset, with specific dnskey(from set), for a specific rrsig 
index dd8d320e515d03f44782a3d13c365e21cdcb12ed..d0a59ef025a866cb413afcba138066e968bf21ae 100644 (file)
@@ -332,11 +332,11 @@ rrset_get_ttl(struct ub_packed_rrset_key* rrset)
        return d->ttl;
 }
 
-enum sec_status 
+static enum sec_status 
 val_verify_rrset(struct module_env* env, struct val_env* ve,
         struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
-       uint8_t* sigalg, char** reason, sldns_pkt_section section,
-       struct module_qstate* qstate)
+       uint8_t* sigalg, char** reason, sldns_ede_code *reason_bogus,
+       sldns_pkt_section section, struct module_qstate* qstate)
 {
        enum sec_status sec;
        struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
@@ -358,8 +358,8 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
        }
        log_nametypeclass(VERB_ALGO, "verify rrset", rrset->rk.dname,
                ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
-       sec = dnskeyset_verify_rrset(env, ve, rrset, keys, sigalg, reason,
-               section, qstate);
+       sec = dnskeyset_verify_rrset_ede(env, ve, rrset, keys, sigalg, reason,
+               reason_bogus, section, qstate);
        verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec));
        regional_free_all(env->scratch);
 
@@ -393,6 +393,16 @@ enum sec_status
 val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
         struct ub_packed_rrset_key* rrset, struct key_entry_key* kkey,
        char** reason, sldns_pkt_section section, struct module_qstate* qstate)
+{
+       return val_verify_rrset_entry_ede(
+                       env, ve, rrset, kkey, reason, NULL, section, qstate);
+}
+
+enum sec_status 
+val_verify_rrset_entry_ede(struct module_env* env, struct val_env* ve,
+        struct ub_packed_rrset_key* rrset, struct key_entry_key* kkey,
+       char** reason, sldns_ede_code *reason_bogus,
+       sldns_pkt_section section, struct module_qstate* qstate)
 {
        /* temporary dnskey rrset-key */
        struct ub_packed_rrset_key dnskey;
@@ -406,7 +416,7 @@ val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
        dnskey.entry.key = &dnskey;
        dnskey.entry.data = kd->rrset_data;
        sec = val_verify_rrset(env, ve, rrset, &dnskey, kd->algo, reason,
-               section, qstate);
+               reason_bogus, section, qstate);
        return sec;
 }
 
index 6e9867f6e3c76919cee2546b6b08d101b56cca66..b7b0aea1b33aad0d260983b16ad7051a4c61597c 100644 (file)
@@ -43,6 +43,7 @@
 #define VALIDATOR_VAL_UTILS_H
 #include "util/data/packed_rrset.h"
 #include "sldns/pkthdr.h"
+#include "sldns/rrdef.h"
 struct query_info;
 struct reply_info;
 struct val_env;
@@ -113,6 +114,7 @@ void val_find_signer(enum val_classification subtype,
        struct query_info* qinf, struct reply_info* rep,
        size_t cname_skip, uint8_t** signer_name, size_t* signer_len);
 
+#if 0
 /**
  * Verify RRset with keys
  * @param env: module environment (scratch buffer)
@@ -130,6 +132,7 @@ enum sec_status val_verify_rrset(struct module_env* env, struct val_env* ve,
        struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
        uint8_t* sigalg, char** reason, sldns_pkt_section section,
        struct module_qstate* qstate);
+#endif
 
 /**
  * Verify RRset with keys from a keyset.
@@ -147,6 +150,12 @@ enum sec_status val_verify_rrset_entry(struct module_env* env,
        struct key_entry_key* kkey, char** reason, sldns_pkt_section section,
        struct module_qstate* qstate);
 
+enum sec_status val_verify_rrset_entry_ede(struct module_env* env, 
+       struct val_env* ve, struct ub_packed_rrset_key* rrset, 
+       struct key_entry_key* kkey, char** reason, sldns_ede_code *reason_bogus,
+       sldns_pkt_section section, struct module_qstate* qstate);
+
+
 /**
  * Verify DNSKEYs with DS rrset. Like val_verify_new_DNSKEYs but
  * returns a sec_status instead of a key_entry.
index d4d48d956895550d70108ca8bab2da87972d56e7..f71c2191a7cc632fa8bd0bedf6f95b4f4f21ef0a 100644 (file)
@@ -592,6 +592,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct module_env* env,
        enum sec_status sec;
        int dname_seen = 0;
        char* reason = NULL;
+       sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
 
        /* validate the ANSWER section */
        for(i=0; i<chase_reply->an_numrrsets; i++) {
@@ -612,8 +613,8 @@ validate_msg_signatures(struct module_qstate* qstate, struct module_env* env,
                }
 
                /* Verify the answer rrset */
-               sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason,
-                       LDNS_SECTION_ANSWER, qstate);
+               sec = val_verify_rrset_entry_ede(env, ve, s, key_entry, &reason,
+                       &reason_bogus, LDNS_SECTION_ANSWER, qstate);
                /* If the (answer) rrset failed to validate, then this 
                 * message is BAD. */
                if(sec != sec_status_secure) {
@@ -627,6 +628,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct module_env* env,
                                errinf(qstate, "for DNAME");
                        errinf_origin(qstate, qstate->reply_origin);
                        chase_reply->security = sec_status_bogus;
+                       chase_reply->reason_bogus = reason_bogus; 
                        return 0;
                }
 
@@ -642,8 +644,8 @@ validate_msg_signatures(struct module_qstate* qstate, struct module_env* env,
        for(i=chase_reply->an_numrrsets; i<chase_reply->an_numrrsets+
                chase_reply->ns_numrrsets; i++) {
                s = chase_reply->rrsets[i];
-               sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason,
-                       LDNS_SECTION_AUTHORITY, qstate);
+               sec = val_verify_rrset_entry_ede(env, ve, s, key_entry, &reason,
+                       &reason_bogus, LDNS_SECTION_AUTHORITY, qstate);
                /* If anything in the authority section fails to be secure, 
                 * we have a bad message. */
                if(sec != sec_status_secure) {
@@ -654,6 +656,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct module_env* env,
                        errinf_origin(qstate, qstate->reply_origin);
                        errinf_rrset(qstate, s);
                        chase_reply->security = sec_status_bogus;
+                       chase_reply->reason_bogus = reason_bogus;
                        return 0;
                }
        }
@@ -2001,17 +2004,21 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
                vq->orig_msg->rep, vq->rrset_skip);
 
        /* store overall validation result in orig_msg */
-       if(vq->rrset_skip == 0)
+       if(vq->rrset_skip == 0) {
                vq->orig_msg->rep->security = vq->chase_reply->security;
-       else if(subtype != VAL_CLASS_REFERRAL ||
+               vq->orig_msg->rep->reason_bogus = vq->chase_reply->reason_bogus;
+       } else if(subtype != VAL_CLASS_REFERRAL ||
                vq->rrset_skip < vq->orig_msg->rep->an_numrrsets + 
                vq->orig_msg->rep->ns_numrrsets) {
                /* ignore sec status of additional section if a referral 
                 * type message skips there and
                 * use the lowest security status as end result. */
-               if(vq->chase_reply->security < vq->orig_msg->rep->security)
+               if(vq->chase_reply->security < vq->orig_msg->rep->security) {
                        vq->orig_msg->rep->security = 
                                vq->chase_reply->security;
+                       vq->orig_msg->rep->reason_bogus = 
+                               vq->chase_reply->reason_bogus;
+               }
        }
 
        if(subtype == VAL_CLASS_REFERRAL) {