]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix that validation reason failure that uses string print uses
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Mon, 8 Jul 2024 13:29:20 +0000 (15:29 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Mon, 8 Jul 2024 13:29:20 +0000 (15:29 +0200)
  separate buffer that is passed, from the scratch validation buffer.

13 files changed:
doc/Changelog
services/authzone.c
testcode/unitverify.c
validator/autotrust.c
validator/val_nsec.c
validator/val_nsec.h
validator/val_nsec3.c
validator/val_nsec3.h
validator/val_sigcrypt.c
validator/val_sigcrypt.h
validator/val_utils.c
validator/val_utils.h
validator/validator.c

index 150817308afb9d848b6b5336cf396552fec5b11a..8fbbf3c0569ce6b841b68f1d087235b9d16db774 100644 (file)
@@ -1,3 +1,7 @@
+8 July 2024: Wouter
+       - Fix that validation reason failure that uses string print uses
+         separate buffer that is passed, from the scratch validation buffer.
+
 5 July 2024: Yorgos
        - Don't check for message TTL changes if the RRsets remain the same.
 
index f01a6d9e0e0e742ff5e062698cfc0d657b5db2ca..0f79f42ead89f5a1baeac0a3ef6ff3940d4d3eca 100644 (file)
@@ -7778,7 +7778,8 @@ static void auth_zone_log(uint8_t* name, enum verbosity_value level,
 static int zonemd_dnssec_verify_rrset(struct auth_zone* z,
        struct module_env* env, struct module_stack* mods,
        struct ub_packed_rrset_key* dnskey, struct auth_data* node,
-       struct auth_rrset* rrset, char** why_bogus, uint8_t* sigalg)
+       struct auth_rrset* rrset, char** why_bogus, uint8_t* sigalg,
+       char* reasonbuf, size_t reasonlen)
 {
        struct ub_packed_rrset_key pk;
        enum sec_status sec;
@@ -7808,7 +7809,7 @@ static int zonemd_dnssec_verify_rrset(struct auth_zone* z,
                        "zonemd: verify %s RRset with DNSKEY", typestr);
        }
        sec = dnskeyset_verify_rrset(env, ve, &pk, dnskey, sigalg, why_bogus, NULL,
-               LDNS_SECTION_ANSWER, NULL, &verified);
+               LDNS_SECTION_ANSWER, NULL, &verified, reasonbuf, reasonlen);
        if(sec == sec_status_secure) {
                return 1;
        }
@@ -7851,7 +7852,8 @@ static int nsec3_of_param_has_type(struct auth_rrset* nsec3, int algo,
 static int zonemd_check_dnssec_absence(struct auth_zone* z,
        struct module_env* env, struct module_stack* mods,
        struct ub_packed_rrset_key* dnskey, struct auth_data* apex,
-       char** reason, char** why_bogus, uint8_t* sigalg)
+       char** reason, char** why_bogus, uint8_t* sigalg, char* reasonbuf,
+       size_t reasonlen)
 {
        struct auth_rrset* nsec = NULL;
        if(!apex) {
@@ -7863,7 +7865,7 @@ static int zonemd_check_dnssec_absence(struct auth_zone* z,
                struct ub_packed_rrset_key pk;
                /* dnssec verify the NSEC */
                if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, apex,
-                       nsec, why_bogus, sigalg)) {
+                       nsec, why_bogus, sigalg, reasonbuf, reasonlen)) {
                        *reason = "DNSSEC verify failed for NSEC RRset";
                        return 0;
                }
@@ -7906,7 +7908,7 @@ static int zonemd_check_dnssec_absence(struct auth_zone* z,
                }
                /* dnssec verify the NSEC3 */
                if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, match,
-                       nsec3, why_bogus, sigalg)) {
+                       nsec3, why_bogus, sigalg, reasonbuf, reasonlen)) {
                        *reason = "DNSSEC verify failed for NSEC3 RRset";
                        return 0;
                }
@@ -7928,7 +7930,7 @@ static int zonemd_check_dnssec_soazonemd(struct auth_zone* z,
        struct module_env* env, struct module_stack* mods,
        struct ub_packed_rrset_key* dnskey, struct auth_data* apex,
        struct auth_rrset* zonemd_rrset, char** reason, char** why_bogus,
-       uint8_t* sigalg)
+       uint8_t* sigalg, char* reasonbuf, size_t reasonlen)
 {
        struct auth_rrset* soa;
        if(!apex) {
@@ -7941,12 +7943,12 @@ static int zonemd_check_dnssec_soazonemd(struct auth_zone* z,
                return 0;
        }
        if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, apex, soa,
-               why_bogus, sigalg)) {
+               why_bogus, sigalg, reasonbuf, reasonlen)) {
                *reason = "DNSSEC verify failed for SOA RRset";
                return 0;
        }
        if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, apex,
-               zonemd_rrset, why_bogus, sigalg)) {
+               zonemd_rrset, why_bogus, sigalg, reasonbuf, reasonlen)) {
                *reason = "DNSSEC verify failed for ZONEMD RRset";
                return 0;
        }
@@ -8014,6 +8016,7 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env,
        struct module_stack* mods, struct ub_packed_rrset_key* dnskey,
        int is_insecure, char** result, uint8_t* sigalg)
 {
+       char reasonbuf[256];
        char* reason = NULL, *why_bogus = NULL;
        struct auth_data* apex = NULL;
        struct auth_rrset* zonemd_rrset = NULL;
@@ -8042,7 +8045,8 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env,
        } else if(!zonemd_rrset && dnskey && !is_insecure) {
                /* fetch, DNSSEC verify, and check NSEC/NSEC3 */
                if(!zonemd_check_dnssec_absence(z, env, mods, dnskey, apex,
-                       &reason, &why_bogus, sigalg)) {
+                       &reason, &why_bogus, sigalg, reasonbuf,
+                       sizeof(reasonbuf))) {
                        auth_zone_zonemd_fail(z, env, reason, why_bogus, result);
                        return;
                }
@@ -8050,7 +8054,8 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env,
        } else if(zonemd_rrset && dnskey && !is_insecure) {
                /* check DNSSEC verify of SOA and ZONEMD */
                if(!zonemd_check_dnssec_soazonemd(z, env, mods, dnskey, apex,
-                       zonemd_rrset, &reason, &why_bogus, sigalg)) {
+                       zonemd_rrset, &reason, &why_bogus, sigalg, reasonbuf,
+                       sizeof(reasonbuf))) {
                        auth_zone_zonemd_fail(z, env, reason, why_bogus, result);
                        return;
                }
@@ -8114,7 +8119,8 @@ static struct ub_packed_rrset_key*
 zonemd_get_dnskey_from_anchor(struct auth_zone* z, struct module_env* env,
        struct module_stack* mods, struct trust_anchor* anchor,
        int* is_insecure, char** why_bogus,
-       struct ub_packed_rrset_key* keystorage)
+       struct ub_packed_rrset_key* keystorage, char* reasonbuf,
+       size_t reasonlen)
 {
        struct auth_data* apex;
        struct auth_rrset* dnskey_rrset;
@@ -8150,7 +8156,8 @@ zonemd_get_dnskey_from_anchor(struct auth_zone* z, struct module_env* env,
        auth_zone_log(z->name, VERB_QUERY,
                "zonemd: verify DNSKEY RRset with trust anchor");
        sec = val_verify_DNSKEY_with_TA(env, ve, keystorage, anchor->ds_rrset,
-               anchor->dnskey_rrset, NULL, why_bogus, NULL, NULL);
+               anchor->dnskey_rrset, NULL, why_bogus, NULL, NULL, reasonbuf,
+               reasonlen);
        regional_free_all(env->scratch);
        if(sec == sec_status_secure) {
                /* success */
@@ -8173,7 +8180,8 @@ static struct ub_packed_rrset_key*
 auth_zone_verify_zonemd_key_with_ds(struct auth_zone* z,
        struct module_env* env, struct module_stack* mods,
        struct ub_packed_rrset_key* ds, int* is_insecure, char** why_bogus,
-       struct ub_packed_rrset_key* keystorage, uint8_t* sigalg)
+       struct ub_packed_rrset_key* keystorage, uint8_t* sigalg,
+       char* reasonbuf, size_t reasonlen)
 {
        struct auth_data* apex;
        struct auth_rrset* dnskey_rrset;
@@ -8209,7 +8217,7 @@ auth_zone_verify_zonemd_key_with_ds(struct auth_zone* z,
        keystorage->rk.rrset_class = htons(z->dclass);
        auth_zone_log(z->name, VERB_QUERY, "zonemd: verify zone DNSKEY with DS");
        sec = val_verify_DNSKEY_with_DS(env, ve, keystorage, ds, sigalg,
-               why_bogus, NULL, NULL);
+               why_bogus, NULL, NULL, reasonbuf, reasonlen);
        regional_free_all(env->scratch);
        if(sec == sec_status_secure) {
                /* success */
@@ -8235,6 +8243,7 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
 {
        struct auth_zone* z = (struct auth_zone*)arg;
        struct module_env* env;
+       char reasonbuf[256];
        char* reason = NULL, *ds_bogus = NULL, *typestr="DNSKEY";
        struct ub_packed_rrset_key* dnskey = NULL, *ds = NULL;
        int is_insecure = 0, downprot;
@@ -8346,7 +8355,8 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
        if(!reason && !is_insecure && !dnskey && ds) {
                dnskey = auth_zone_verify_zonemd_key_with_ds(z, env,
                        &env->mesh->mods, ds, &is_insecure, &ds_bogus,
-                       &keystorage, downprot?sigalg:NULL);
+                       &keystorage, downprot?sigalg:NULL, reasonbuf,
+                       sizeof(reasonbuf));
                if(!dnskey && !is_insecure && !reason)
                        reason = "DNSKEY verify with DS failed";
        }
@@ -8354,6 +8364,7 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
        if(reason) {
                auth_zone_zonemd_fail(z, env, reason, ds_bogus, NULL);
                lock_rw_unlock(&z->lock);
+               regional_free_all(env->scratch);
                return;
        }
 
@@ -8438,6 +8449,7 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env)
 void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
        struct module_stack* mods, char** result, int offline, int only_online)
 {
+       char reasonbuf[256];
        char* reason = NULL, *why_bogus = NULL;
        struct trust_anchor* anchor = NULL;
        struct ub_packed_rrset_key* dnskey = NULL;
@@ -8472,7 +8484,8 @@ void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
                }
                /* equal to trustanchor, no need for online lookups */
                dnskey = zonemd_get_dnskey_from_anchor(z, env, mods, anchor,
-                       &is_insecure, &why_bogus, &keystorage);
+                       &is_insecure, &why_bogus, &keystorage, reasonbuf,
+                       sizeof(reasonbuf));
                lock_basic_unlock(&anchor->lock);
                if(!dnskey && !reason && !is_insecure) {
                        reason = "verify DNSKEY RRset with trust anchor failed";
@@ -8498,6 +8511,7 @@ void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
 
        if(reason) {
                auth_zone_zonemd_fail(z, env, reason, why_bogus, result);
+               regional_free_all(env->scratch);
                return;
        }
 
index 395b4c257427b00cfdbe5a5f9083caffc8475d4a..275435c73a0d6201031a8d8b06ed7b49e6a52920 100644 (file)
@@ -178,6 +178,7 @@ verifytest_rrset(struct module_env* env, struct val_env* ve,
        struct query_info* qinfo)
 {
        enum sec_status sec;
+       char reasonbuf[256];
        char* reason = NULL;
        uint8_t sigalg[ALGO_NEEDS_MAX+1];
        int verified = 0;
@@ -188,8 +189,9 @@ verifytest_rrset(struct module_env* env, struct val_env* ve,
        }
        setup_sigalg(dnskey, sigalg); /* check all algorithms in the dnskey */
        /* ok to give null as qstate here, won't be used for answer section. */
-       sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason, NULL,
-               LDNS_SECTION_ANSWER, NULL, &verified);
+       sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason,
+               NULL, LDNS_SECTION_ANSWER, NULL, &verified, reasonbuf,
+               sizeof(reasonbuf));
        if(vsig) {
                printf("verify outcome is: %s %s\n", sec_status_to_string(sec),
                        reason?reason:"");
index 3eb13b35c2298d98bc1b6719b66fa1716552457c..36cdf3e0a7a2bc6a076a9cdb2f8bf80cdcad067b 100644 (file)
@@ -1262,12 +1262,13 @@ verify_dnskey(struct module_env* env, struct val_env* ve,
         struct trust_anchor* tp, struct ub_packed_rrset_key* rrset,
        struct module_qstate* qstate)
 {
+       char reasonbuf[256];
        char* reason = NULL;
        uint8_t sigalg[ALGO_NEEDS_MAX+1];
        int downprot = env->cfg->harden_algo_downgrade;
        enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve, rrset,
                tp->ds_rrset, tp->dnskey_rrset, downprot?sigalg:NULL, &reason,
-               NULL, qstate);
+               NULL, qstate, reasonbuf, sizeof(reasonbuf));
        /* sigalg is ignored, it returns algorithms signalled to exist, but
         * in 5011 there are no other rrsets to check.  if downprot is
         * enabled, then it checks that the DNSKEY is signed with all
index d0cc67ff5d0bcaddf62c0aee715014db06ef5a23..ad0cba1c4b594df7a7b837d349a0ac0d12beae82 100644 (file)
@@ -177,7 +177,7 @@ static int
 nsec_verify_rrset(struct module_env* env, struct val_env* ve,
        struct ub_packed_rrset_key* nsec, struct key_entry_key* kkey,
        char** reason, sldns_ede_code* reason_bogus,
-       struct module_qstate* qstate)
+       struct module_qstate* qstate, char* reasonbuf, size_t reasonlen)
 {
        struct packed_rrset_data* d = (struct packed_rrset_data*)
                nsec->entry.data;
@@ -189,7 +189,8 @@ nsec_verify_rrset(struct module_env* env, struct val_env* ve,
        if(d->security == sec_status_secure)
                return 1;
        d->security = val_verify_rrset_entry(env, ve, nsec, kkey, reason,
-               reason_bogus, LDNS_SECTION_AUTHORITY, qstate, &verified);
+               reason_bogus, LDNS_SECTION_AUTHORITY, qstate, &verified,
+               reasonbuf, reasonlen);
        if(d->security == sec_status_secure) {
                rrset_update_sec_status(env->rrset_cache, nsec, *env->now);
                return 1;
@@ -201,7 +202,8 @@ enum sec_status
 val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve, 
        struct query_info* qinfo, struct reply_info* rep, 
        struct key_entry_key* kkey, time_t* proof_ttl, char** reason,
-       sldns_ede_code* reason_bogus, struct module_qstate* qstate)
+       sldns_ede_code* reason_bogus, struct module_qstate* qstate,
+       char* reasonbuf, size_t reasonlen)
 {
        struct ub_packed_rrset_key* nsec = reply_find_rrset_section_ns(
                rep, qinfo->qname, qinfo->qname_len, LDNS_RR_TYPE_NSEC, 
@@ -219,7 +221,7 @@ val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve,
         * 2) this is not a delegation point */
        if(nsec) {
                if(!nsec_verify_rrset(env, ve, nsec, kkey, reason,
-                       reason_bogus, qstate)) {
+                       reason_bogus, qstate, reasonbuf, reasonlen)) {
                        verbose(VERB_ALGO, "NSEC RRset for the "
                                "referral did not verify.");
                        return sec_status_bogus;
@@ -250,7 +252,7 @@ val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve,
                if(rep->rrsets[i]->rk.type != htons(LDNS_RR_TYPE_NSEC))
                        continue;
                if(!nsec_verify_rrset(env, ve, rep->rrsets[i], kkey, reason,
-                       reason_bogus, qstate)) {
+                       reason_bogus, qstate, reasonbuf, reasonlen)) {
                        verbose(VERB_ALGO, "NSEC for empty non-terminal "
                                "did not verify.");
                        *reason = "NSEC for empty non-terminal "
index 81844c908e548fd0d1de6e5229ac74d51e5d6acf..c1d45314abea8e8f8f08588a1103263268a2bef4 100644 (file)
@@ -68,6 +68,8 @@ struct key_entry_key;
  * @param reason: string explaining why bogus.
  * @param reason_bogus: relevant EDE code for validation failure.
  * @param qstate: qstate with region.
+ * @param reasonbuf: buffer to use for fail reason string print.
+ * @param reasonlen: length of reasonbuf.
  * @return security status.
  *     SECURE: proved absence of DS.
  *     INSECURE: proved that this was not a delegation point.
@@ -78,7 +80,7 @@ enum sec_status val_nsec_prove_nodata_dsreply(struct module_env* env,
        struct val_env* ve, struct query_info* qinfo, 
        struct reply_info* rep, struct key_entry_key* kkey,
        time_t* proof_ttl, char** reason, sldns_ede_code* reason_bogus,
-       struct module_qstate* qstate);
+       struct module_qstate* qstate, char* reasonbuf, size_t reasonlen);
 
 /** 
  * nsec typemap check, takes an NSEC-type bitmap as argument, checks for type.
index 95d1e4d7e4fe4b05f8800201d4fb2916766cd81f..e790e99825eac9e9dbae45bbb7f8298779ecc726 100644 (file)
@@ -1445,7 +1445,7 @@ static int
 list_is_secure(struct module_env* env, struct val_env* ve, 
        struct ub_packed_rrset_key** list, size_t num,
        struct key_entry_key* kkey, char** reason, sldns_ede_code *reason_bogus,
-       struct module_qstate* qstate)
+       struct module_qstate* qstate, char* reasonbuf, size_t reasonlen)
 {
        struct packed_rrset_data* d;
        size_t i;
@@ -1461,7 +1461,7 @@ list_is_secure(struct module_env* env, struct val_env* ve,
                        continue;
                d->security = val_verify_rrset_entry(env, ve, list[i], kkey,
                        reason, reason_bogus, LDNS_SECTION_AUTHORITY, qstate,
-                       &verified);
+                       &verified, reasonbuf, reasonlen);
                if(d->security != sec_status_secure) {
                        verbose(VERB_ALGO, "NSEC3 did not verify");
                        return 0;
@@ -1476,7 +1476,7 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
        struct ub_packed_rrset_key** list, size_t num,
        struct query_info* qinfo, struct key_entry_key* kkey, char** reason,
        sldns_ede_code* reason_bogus, struct module_qstate* qstate,
-       struct nsec3_cache_table* ct)
+       struct nsec3_cache_table* ct, char* reasonbuf, size_t reasonlen)
 {
        struct nsec3_filter flt;
        struct ce_response ce;
@@ -1491,7 +1491,8 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
                *reason = "no valid NSEC3s";
                return sec_status_bogus; /* no valid NSEC3s, bogus */
        }
-       if(!list_is_secure(env, ve, list, num, kkey, reason, reason_bogus, qstate)) {
+       if(!list_is_secure(env, ve, list, num, kkey, reason, reason_bogus,
+               qstate, reasonbuf, reasonlen)) {
                *reason = "not all NSEC3 records secure";
                return sec_status_bogus; /* not all NSEC3 records secure */
        }
index 8ca912934fa6afcd451ab82a331b1fbd5e71e9a1..f668a270ff123ba8f18fdeeb1ae74d248c5f15ca 100644 (file)
@@ -210,6 +210,8 @@ nsec3_prove_wildcard(struct module_env* env, struct val_env* ve,
  * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
  * @param qstate: qstate with region.
  * @param ct: cached hashes table.
+ * @param reasonbuf: buffer to use for fail reason string print.
+ * @param reasonlen: length of reasonbuf.
  * @return:
  *     sec_status SECURE of the proposition is proven by the NSEC3 RRs, 
  *     BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored.
@@ -222,7 +224,7 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
        struct ub_packed_rrset_key** list, size_t num, 
        struct query_info* qinfo, struct key_entry_key* kkey, char** reason,
        sldns_ede_code* reason_bogus, struct module_qstate* qstate,
-       struct nsec3_cache_table* ct);
+       struct nsec3_cache_table* ct, char* reasonbuf, size_t reasonlen);
 
 /**
  * Prove NXDOMAIN or NODATA.
index 7c2b9d7e660811b3ddd0fd94ff0d7767eb542be5..3e90eeb84fcb330cb1462589b9c2e977ab2cf4ac 100644 (file)
@@ -623,7 +623,8 @@ 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_ede_code *reason_bogus,
-       sldns_pkt_section section, struct module_qstate* qstate, int* verified)
+       sldns_pkt_section section, struct module_qstate* qstate, int* verified,
+       char* reasonbuf, size_t reasonlen)
 {
        enum sec_status sec;
        size_t i, num;
@@ -680,7 +681,8 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
                verbose(VERB_ALGO, "rrset failed to verify: "
                        "no valid signatures for %d algorithms",
                        (int)algo_needs_num_missing(&needs));
-               algo_needs_reason(env, alg, reason, "no signatures");
+               algo_needs_reason(alg, reason, "no signatures", reasonbuf,
+                       reasonlen);
        } else {
                verbose(VERB_ALGO, "rrset failed to verify: "
                        "no valid signatures");
@@ -688,17 +690,16 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
        return sec_status_bogus;
 }
 
-void algo_needs_reason(struct module_env* env, int alg, char** reason, char* s)
+void algo_needs_reason(int alg, char** reason, char* s, char* reasonbuf,
+       size_t reasonlen)
 {
-       char buf[256];
        sldns_lookup_table *t = sldns_lookup_by_id(sldns_algorithms, alg);
        if(t&&t->name)
-               snprintf(buf, sizeof(buf), "%s with algorithm %s", s, t->name);
-       else    snprintf(buf, sizeof(buf), "%s with algorithm ALG%u", s,
-                       (unsigned)alg);
-       *reason = regional_strdup(env->scratch, buf);
-       if(!*reason)
-               *reason = s;
+               snprintf(reasonbuf, sizeof(reasonlen), "%s with algorithm %s",
+                       s, t->name);
+       else    snprintf(reasonbuf, sizeof(reasonlen), "%s with algorithm "
+                       "ALG%u", s, (unsigned)alg);
+       *reason = reasonbuf;
 }
 
 enum sec_status
index 1a3d8fcb22debc3c05d6c1b119b85ea63cd25be5..1fac8bde0e91ae326a45caec28ddeda1c87c9d73 100644 (file)
@@ -134,12 +134,14 @@ int algo_needs_missing(struct algo_needs* n);
 
 /**
  * Format error reason for algorithm missing.
- * @param env: module env with scratch for temp storage of string.
  * @param alg: DNSKEY-algorithm missing.
  * @param reason: destination.
  * @param s: string, appended with 'with algorithm ..'.
+ * @param reasonbuf: buffer to use for fail reason string print.
+ * @param reasonlen: length of reasonbuf.
  */
-void algo_needs_reason(struct module_env* env, int alg, char** reason, char* s);
+void algo_needs_reason(int alg, char** reason, char* s, char* reasonbuf,
+       size_t reasonlen);
 
 /** 
  * Check if dnskey matches a DS digest 
@@ -261,6 +263,8 @@ uint16_t dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx);
  * @param section: section of packet where this rrset comes from.
  * @param qstate: qstate with region.
  * @param verified: if not NULL the number of RRSIG validations is returned.
+ * @param reasonbuf: buffer to use for fail reason string print.
+ * @param reasonlen: length of reasonbuf.
  * @return SECURE if one key in the set verifies one rrsig.
  *     UNCHECKED on allocation errors, unsupported algorithms, malformed data,
  *     and BOGUS on verification failures (no keys match any signatures).
@@ -269,8 +273,8 @@ 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_ede_code *reason_bogus,
-       sldns_pkt_section section, struct module_qstate* qstate, int* verified);
-
+       sldns_pkt_section section, struct module_qstate* qstate, int* verified,
+       char* reasonbuf, size_t reasonlen);
 
 /** 
  * verify rrset against one specific dnskey (from rrset) 
index add6d9bba64aabd64115b7e93eb2a388381896d0..549264d76a1f1ac0db92dd0fe26044c46736366f 100644 (file)
@@ -406,7 +406,7 @@ 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_ede_code *reason_bogus,
        sldns_pkt_section section, struct module_qstate* qstate,
-       int *verified)
+       int *verified, char* reasonbuf, size_t reasonlen)
 {
        enum sec_status sec;
        struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
@@ -431,7 +431,7 @@ 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,
-               reason_bogus, section, qstate, verified);
+               reason_bogus, section, qstate, verified, reasonbuf, reasonlen);
        verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec));
        regional_free_all(env->scratch);
 
@@ -466,7 +466,7 @@ 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_ede_code *reason_bogus,
        sldns_pkt_section section, struct module_qstate* qstate,
-       int* verified)
+       int* verified, char* reasonbuf, size_t reasonlen)
 {
        /* temporary dnskey rrset-key */
        struct ub_packed_rrset_key dnskey;
@@ -480,7 +480,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,
-               reason_bogus, section, qstate, verified);
+               reason_bogus, section, qstate, verified, reasonbuf, reasonlen);
        return sec;
 }
 
@@ -490,7 +490,7 @@ 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,
        sldns_ede_code *reason_bogus, struct module_qstate* qstate,
-       int *nonechecked)
+       int *nonechecked, char* reasonbuf, size_t reasonlen)
 {
        enum sec_status sec = sec_status_bogus;
        size_t i, num, numchecked = 0, numhashok = 0, numsizesupp = 0;
@@ -544,8 +544,8 @@ verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
                return sec_status_insecure;
        }
        if(numchecked == 0) {
-               algo_needs_reason(env, ds_get_key_algo(ds_rrset, ds_idx),
-                       reason, "no keys have a DS");
+               algo_needs_reason(ds_get_key_algo(ds_rrset, ds_idx),
+                       reason, "no keys have a DS", reasonbuf, reasonlen);
                *nonechecked = 1;
        } else if(numhashok == 0) {
                *reason = "DS hash mismatches key";
@@ -576,7 +576,8 @@ 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,
-       sldns_ede_code *reason_bogus, struct module_qstate* qstate)
+       sldns_ede_code *reason_bogus, struct module_qstate* qstate,
+       char* reasonbuf, size_t reasonlen)
 {
        /* as long as this is false, we can consider this DS rrset to be
         * equivalent to no DS rrset. */
@@ -615,7 +616,7 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
 
                sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
                        ds_rrset, i, reason, reason_bogus, qstate,
-                       &nonechecked);
+                       &nonechecked, reasonbuf, reasonlen);
                if(sec == sec_status_insecure) {
                        /* DNSKEY too large unsupported or algo refused by
                         * crypto lib. */
@@ -666,8 +667,8 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
        /* If any were understandable, then it is bad. */
        verbose(VERB_QUERY, "Failed to match any usable DS to a DNSKEY.");
        if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
-               algo_needs_reason(env, alg, reason, "missing verification of "
-                       "DNSKEY signature");
+               algo_needs_reason(alg, reason, "missing verification of "
+                       "DNSKEY signature", reasonbuf, reasonlen);
        }
        return sec_status_bogus;
 }
@@ -676,12 +677,13 @@ 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,
-       sldns_ede_code *reason_bogus, struct module_qstate* qstate)
+       sldns_ede_code *reason_bogus, struct module_qstate* qstate,
+       char* reasonbuf, size_t reasonlen)
 {
        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, 
-               reason_bogus, qstate);
+               reason_bogus, qstate, reasonbuf, reasonlen);
 
        if(sec == sec_status_secure) {
                return key_entry_create_rrset(region, 
@@ -706,7 +708,8 @@ 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,
-       sldns_ede_code *reason_bogus, struct module_qstate* qstate)
+       sldns_ede_code *reason_bogus, struct module_qstate* qstate,
+       char* reasonbuf, size_t reasonlen)
 {
        /* as long as this is false, we can consider this anchor to be
         * equivalent to no anchor. */
@@ -757,7 +760,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
                        continue;
 
                sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
-                       ta_ds, i, reason, reason_bogus, qstate, &nonechecked);
+                       ta_ds, i, reason, reason_bogus, qstate, &nonechecked,
+                       reasonbuf, reasonlen);
                if(sec == sec_status_insecure) {
                        has_algo_refusal = 1;
                        continue;
@@ -837,8 +841,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
        /* If any were understandable, then it is bad. */
        verbose(VERB_QUERY, "Failed to match any usable anchor to a DNSKEY.");
        if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
-               algo_needs_reason(env, alg, reason, "missing verification of "
-                       "DNSKEY signature");
+               algo_needs_reason(alg, reason, "missing verification of "
+                       "DNSKEY signature", reasonbuf, reasonlen);
        }
        return sec_status_bogus;
 }
@@ -848,12 +852,14 @@ 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, sldns_ede_code *reason_bogus, struct module_qstate* qstate)
+       char** reason, sldns_ede_code *reason_bogus,
+       struct module_qstate* qstate, char* reasonbuf, size_t reasonlen)
 {
        uint8_t sigalg[ALGO_NEEDS_MAX+1];
        enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve,
                dnskey_rrset, ta_ds_rrset, ta_dnskey_rrset,
-               downprot?sigalg:NULL, reason, reason_bogus, qstate);
+               downprot?sigalg:NULL, reason, reason_bogus, qstate,
+               reasonbuf, reasonlen);
 
        if(sec == sec_status_secure) {
                return key_entry_create_rrset(region,
index e8cdcefa6923fa93e1dc11e6b1c3d619694aaeb6..4fe38c1bb995a8bbcb9e272e7c0997c0531724a7 100644 (file)
@@ -125,13 +125,15 @@ void val_find_signer(enum val_classification subtype,
  * @param section: section of packet where this rrset comes from.
  * @param qstate: qstate with region.
  * @param verified: if not NULL, the number of RRSIG validations is returned.
+ * @param reasonbuf: buffer to use for fail reason string print.
+ * @param reasonlen: length of reasonbuf.
  * @return security status of verification.
  */
 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_ede_code *reason_bogus,
        sldns_pkt_section section, struct module_qstate* qstate,
-       int* verified);
+       int* verified, char* reasonbuf, size_t reasonlen);
 
 /**
  * Verify DNSKEYs with DS rrset. Like val_verify_new_DNSKEYs but
@@ -146,6 +148,8 @@ enum sec_status val_verify_rrset_entry(struct module_env* env,
  * @param reason: reason of failure. Fixed string or alloced in scratch.
  * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
  * @param qstate: qstate with region.
+ * @param reasonbuf: buffer to use for fail reason string print.
+ * @param reasonlen: length of reasonbuf.
  * @return: sec_status_secure if a DS matches.
  *     sec_status_insecure if end of trust (i.e., unknown algorithms).
  *     sec_status_bogus if it fails.
@@ -153,7 +157,8 @@ enum sec_status val_verify_rrset_entry(struct module_env* env,
 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,
-    sldns_ede_code *reason_bogus, struct module_qstate* qstate);
+    sldns_ede_code *reason_bogus, struct module_qstate* qstate,
+    char* reasonbuf, size_t reasonlen);
 
 /**
  * Verify DNSKEYs with DS and DNSKEY rrset.  Like val_verify_DNSKEY_with_DS
@@ -167,8 +172,10 @@ enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
  *   algorithm is enough.  The list of signalled algorithms is returned,
  *   must have enough space for ALGO_NEEDS_MAX+1.
  * @param reason: reason of failure. Fixed string or alloced in scratch.
-* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
+ * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
  * @param qstate: qstate with region.
+ * @param reasonbuf: buffer to use for fail reason string print.
+ * @param reasonlen: length of reasonbuf.
  * @return: sec_status_secure if a DS matches.
  *     sec_status_insecure if end of trust (i.e., unknown algorithms).
  *     sec_status_bogus if it fails.
@@ -177,7 +184,8 @@ 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,
-    sldns_ede_code *reason_bogus, struct module_qstate* qstate);
+    sldns_ede_code *reason_bogus, struct module_qstate* qstate,
+    char* reasonbuf, size_t reasonlen);
 
 /**
  * Verify new DNSKEYs with DS rrset. The DS contains hash values that should
@@ -194,6 +202,8 @@ enum sec_status val_verify_DNSKEY_with_TA(struct module_env* env,
  * @param reason: reason of failure. Fixed string or alloced in scratch.
  * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
  * @param qstate: qstate with region.
+ * @param reasonbuf: buffer to use for fail reason string print.
+ * @param reasonlen: length of reasonbuf.
  * @return a KeyEntry. This will either contain the now trusted
  *         dnskey_rrset, a "null" key entry indicating that this DS
  *         rrset/DNSKEY pair indicate an secure end to the island of trust
@@ -208,7 +218,8 @@ 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,
-    sldns_ede_code *reason_bogus, struct module_qstate* qstate);
+    sldns_ede_code *reason_bogus, struct module_qstate* qstate,
+    char* reasonbuf, size_t reasonlen);
 
 /**
  * Verify rrset with trust anchor: DS and DNSKEY rrset.
@@ -224,6 +235,8 @@ struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region,
  * @param reason: reason of failure. Fixed string or alloced in scratch.
  * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
  * @param qstate: qstate with region.
+ * @param reasonbuf: buffer to use for fail reason string print.
+ * @param reasonlen: length of reasonbuf.
  * @return a KeyEntry. This will either contain the now trusted
  *         dnskey_rrset, a "null" key entry indicating that this DS
  *         rrset/DNSKEY pair indicate an secure end to the island of trust
@@ -239,7 +252,8 @@ struct key_entry_key* val_verify_new_DNSKEYs_with_ta(struct regional* region,
     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);
+    char** reason, sldns_ede_code *reason_bogus, struct module_qstate* qstate,
+    char* reasonbuf, size_t reasonlen);
 
 /**
  * Determine if DS rrset is usable for validator or not.
index f5894e30cc1ba13b0ffc07179b523ddbd4a2e260..77718cbfdfa705689fa91db5e145e87380f65675 100644 (file)
@@ -647,6 +647,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
        struct ub_packed_rrset_key* s;
        enum sec_status sec;
        int num_verifies = 0, verified, have_state = 0;
+       char reasonbuf[256];
        char* reason = NULL;
        sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
        *suspend = 0;
@@ -682,7 +683,8 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
 
                /* Verify the answer rrset */
                sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason,
-                       &reason_bogus, LDNS_SECTION_ANSWER, qstate, &verified);
+                       &reason_bogus, LDNS_SECTION_ANSWER, qstate, &verified,
+                       reasonbuf, sizeof(reasonbuf));
                /* If the (answer) rrset failed to validate, then this 
                 * message is BAD. */
                if(sec != sec_status_secure) {
@@ -727,7 +729,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
                s = chase_reply->rrsets[i];
                sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason,
                        &reason_bogus, LDNS_SECTION_AUTHORITY, qstate,
-                       &verified);
+                       &verified, reasonbuf, sizeof(reasonbuf));
                /* If anything in the authority section fails to be secure, 
                 * we have a bad message. */
                if(sec != sec_status_secure) {
@@ -773,7 +775,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
                if(sname && query_dname_compare(sname, key_entry->name)==0)
                        (void)val_verify_rrset_entry(env, ve, s, key_entry,
                                &reason, NULL, LDNS_SECTION_ADDITIONAL, qstate,
-                               &verified);
+                               &verified, reasonbuf, sizeof(reasonbuf));
                /* the additional section can fail to be secure, 
                 * it is optional, check signature in case we need
                 * to clean the additional section later. */
@@ -2680,6 +2682,7 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
        struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
        struct key_entry_key* kkey = NULL;
        enum sec_status sec = sec_status_unchecked;
+       char reasonbuf[256];
        char* reason = NULL;
        sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
        int downprot = qstate->env->cfg->harden_algo_downgrade;
@@ -2716,7 +2719,7 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
        /* attempt to verify with trust anchor DS and DNSKEY */
        kkey = val_verify_new_DNSKEYs_with_ta(qstate->region, qstate->env, ve, 
                dnskey_rrset, ta->ds_rrset, ta->dnskey_rrset, downprot,
-               &reason, &reason_bogus, qstate);
+               &reason, &reason_bogus, qstate, reasonbuf, sizeof(reasonbuf));
        if(!kkey) {
                log_err("out of memory: verifying prime TA");
                return NULL;
@@ -2785,6 +2788,7 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
        struct key_entry_key** ke, struct module_qstate* sub_qstate)
 {
        struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
+       char reasonbuf[256];
        char* reason = NULL;
        sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
        enum val_classification subtype;
@@ -2827,7 +2831,9 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
                /* Verify only returns BOGUS or SECURE. If the rrset is 
                 * bogus, then we are done. */
                sec = val_verify_rrset_entry(qstate->env, ve, ds,
-                       vq->key_entry, &reason, &reason_bogus, LDNS_SECTION_ANSWER, qstate, &verified);
+                       vq->key_entry, &reason, &reason_bogus,
+                       LDNS_SECTION_ANSWER, qstate, &verified, reasonbuf,
+                       sizeof(reasonbuf));
                if(sec != sec_status_secure) {
                        verbose(VERB_DETAIL, "DS rrset in DS response did "
                                "not verify");
@@ -2877,7 +2883,8 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
                /* Try to prove absence of the DS with NSEC */
                sec = val_nsec_prove_nodata_dsreply(
                        qstate->env, ve, qinfo, msg->rep, vq->key_entry, 
-                       &proof_ttl, &reason, &reason_bogus, qstate);
+                       &proof_ttl, &reason, &reason_bogus, qstate,
+                       reasonbuf, sizeof(reasonbuf));
                switch(sec) {
                        case sec_status_secure:
                                verbose(VERB_DETAIL, "NSEC RRset for the "
@@ -2914,7 +2921,8 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
                sec = nsec3_prove_nods(qstate->env, ve, 
                        msg->rep->rrsets + msg->rep->an_numrrsets,
                        msg->rep->ns_numrrsets, qinfo, vq->key_entry, &reason,
-                       &reason_bogus, qstate, &vq->nsec3_cache_table);
+                       &reason_bogus, qstate, &vq->nsec3_cache_table,
+                       reasonbuf, sizeof(reasonbuf));
                switch(sec) {
                        case sec_status_insecure:
                                /* case insecure also continues to unsigned
@@ -2981,7 +2989,8 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
                }
                sec = val_verify_rrset_entry(qstate->env, ve, cname,
                        vq->key_entry, &reason, &reason_bogus,
-                       LDNS_SECTION_ANSWER, qstate, &verified);
+                       LDNS_SECTION_ANSWER, qstate, &verified, reasonbuf,
+                       sizeof(reasonbuf));
                if(sec == sec_status_secure) {
                        verbose(VERB_ALGO, "CNAME validated, "
                                "proof that DS does not exist");
@@ -3135,6 +3144,7 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
        struct key_entry_key* old = vq->key_entry;
        struct ub_packed_rrset_key* dnskey = NULL;
        int downprot;
+       char reasonbuf[256];
        char* reason = NULL;
        sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
 
@@ -3185,7 +3195,8 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
        }
        downprot = qstate->env->cfg->harden_algo_downgrade;
        vq->key_entry = val_verify_new_DNSKEYs(qstate->region, qstate->env,
-               ve, dnskey, vq->ds_rrset, downprot, &reason, &reason_bogus, qstate);
+               ve, dnskey, vq->ds_rrset, downprot, &reason, &reason_bogus,
+               qstate, reasonbuf, sizeof(reasonbuf));
 
        if(!vq->key_entry) {
                log_err("out of memory in verify new DNSKEYs");