summaryrefslogtreecommitdiff
path: root/validator
diff options
context:
space:
mode:
Diffstat (limited to 'validator')
-rw-r--r--validator/autotrust.c3
-rw-r--r--validator/val_nsec.c12
-rw-r--r--validator/val_nsec.h4
-rw-r--r--validator/val_nsec3.c9
-rw-r--r--validator/val_nsec3.h4
-rw-r--r--validator/val_secalgo.c8
-rw-r--r--validator/val_sigcrypt.c19
-rw-r--r--validator/val_sigcrypt.h12
-rw-r--r--validator/val_utils.c82
-rw-r--r--validator/val_utils.h26
-rw-r--r--validator/validator.c129
11 files changed, 218 insertions, 90 deletions
diff --git a/validator/autotrust.c b/validator/autotrust.c
index 3eb13b35c229..36cdf3e0a7a2 100644
--- a/validator/autotrust.c
+++ b/validator/autotrust.c
@@ -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
diff --git a/validator/val_nsec.c b/validator/val_nsec.c
index d0cc67ff5d0b..ad0cba1c4b59 100644
--- a/validator/val_nsec.c
+++ b/validator/val_nsec.c
@@ -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 "
diff --git a/validator/val_nsec.h b/validator/val_nsec.h
index 81844c908e54..c1d45314abea 100644
--- a/validator/val_nsec.h
+++ b/validator/val_nsec.h
@@ -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.
diff --git a/validator/val_nsec3.c b/validator/val_nsec3.c
index 95d1e4d7e4fe..e790e99825ea 100644
--- a/validator/val_nsec3.c
+++ b/validator/val_nsec3.c
@@ -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 */
}
diff --git a/validator/val_nsec3.h b/validator/val_nsec3.h
index 8ca912934fa6..f668a270ff12 100644
--- a/validator/val_nsec3.h
+++ b/validator/val_nsec3.h
@@ -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.
diff --git a/validator/val_secalgo.c b/validator/val_secalgo.c
index 78651674991e..be8347b1bc88 100644
--- a/validator/val_secalgo.c
+++ b/validator/val_secalgo.c
@@ -423,7 +423,10 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len)
if(!dsasig) return 0;
#ifdef HAVE_DSA_SIG_SET0
- if(!DSA_SIG_set0(dsasig, R, S)) return 0;
+ if(!DSA_SIG_set0(dsasig, R, S)) {
+ DSA_SIG_free(dsasig);
+ return 0;
+ }
#else
# ifndef S_SPLINT_S
dsasig->r = R;
@@ -2057,11 +2060,13 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE);
#endif
/* double fallthrough annotation to please gcc parser */
+ ATTR_FALLTHROUGH
/* fallthrough */
#ifdef USE_SHA2
/* fallthrough */
case LDNS_RSASHA256:
digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
+ ATTR_FALLTHROUGH
/* fallthrough */
case LDNS_RSASHA512:
digest_size = (digest_size ? digest_size : SHA512_DIGEST_SIZE);
@@ -2077,6 +2082,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
#ifdef USE_ECDSA
case LDNS_ECDSAP256SHA256:
digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
+ ATTR_FALLTHROUGH
/* fallthrough */
case LDNS_ECDSAP384SHA384:
digest_size = (digest_size ? digest_size : SHA384_DIGEST_SIZE);
diff --git a/validator/val_sigcrypt.c b/validator/val_sigcrypt.c
index 7c2b9d7e6608..9251d2b1f38a 100644
--- a/validator/val_sigcrypt.c
+++ b/validator/val_sigcrypt.c
@@ -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,
+ snprintf(reasonbuf, reasonlen, "%s with algorithm %s", s,
+ t->name);
+ else snprintf(reasonbuf, reasonlen, "%s with algorithm ALG%u", s,
(unsigned)alg);
- *reason = regional_strdup(env->scratch, buf);
- if(!*reason)
- *reason = s;
+ *reason = reasonbuf;
}
enum sec_status
diff --git a/validator/val_sigcrypt.h b/validator/val_sigcrypt.h
index 1a3d8fcb22de..1fac8bde0e91 100644
--- a/validator/val_sigcrypt.h
+++ b/validator/val_sigcrypt.h
@@ -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)
diff --git a/validator/val_utils.c b/validator/val_utils.c
index a7db41dadc3d..549264d76a1f 100644
--- a/validator/val_utils.c
+++ b/validator/val_utils.c
@@ -240,6 +240,26 @@ val_find_best_signer(struct ub_packed_rrset_key* rrset,
}
}
+/** Detect if the, unsigned, CNAME is under a previous DNAME RR in the
+ * message, and thus it was generated from that previous DNAME.
+ */
+static int
+cname_under_previous_dname(struct reply_info* rep, size_t cname_idx,
+ size_t* ret)
+{
+ size_t i;
+ for(i=0; i<cname_idx; i++) {
+ if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DNAME &&
+ dname_strict_subdomain_c(rep->rrsets[cname_idx]->
+ rk.dname, rep->rrsets[i]->rk.dname)) {
+ *ret = i;
+ return 1;
+ }
+ }
+ *ret = 0;
+ return 0;
+}
+
void
val_find_signer(enum val_classification subtype, struct query_info* qinf,
struct reply_info* rep, size_t skip, uint8_t** signer_name,
@@ -275,12 +295,19 @@ val_find_signer(enum val_classification subtype, struct query_info* qinf,
*signer_name = NULL;
*signer_len = 0;
} else if(subtype == VAL_CLASS_CNAME) {
+ size_t j;
/* check for the first signed cname/dname rrset */
for(i=skip; i<rep->an_numrrsets; i++) {
val_find_rrset_signer(rep->rrsets[i],
signer_name, signer_len);
if(*signer_name)
return;
+ if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME
+ && cname_under_previous_dname(rep, i, &j)) {
+ val_find_rrset_signer(rep->rrsets[j],
+ signer_name, signer_len);
+ return;
+ }
if(ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_DNAME)
break; /* only check CNAME after a DNAME */
}
@@ -379,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->
@@ -404,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);
@@ -439,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;
@@ -453,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;
}
@@ -463,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;
@@ -517,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";
@@ -549,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. */
@@ -588,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. */
@@ -639,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;
}
@@ -649,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,
@@ -679,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. */
@@ -730,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;
@@ -810,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;
}
@@ -821,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,
@@ -979,7 +1012,7 @@ void
val_fill_reply(struct reply_info* chase, struct reply_info* orig,
size_t skip, uint8_t* name, size_t len, uint8_t* signer)
{
- size_t i;
+ size_t i, j;
int seen_dname = 0;
chase->rrset_count = 0;
chase->an_numrrsets = 0;
@@ -1002,8 +1035,15 @@ val_fill_reply(struct reply_info* chase, struct reply_info* orig,
LDNS_RR_TYPE_DNAME) {
seen_dname = 1;
}
+ } else if(ntohs(orig->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME
+ && ((struct packed_rrset_data*)orig->rrsets[i]->
+ entry.data)->rrsig_count == 0 &&
+ cname_under_previous_dname(orig, i, &j) &&
+ rrset_has_signer(orig->rrsets[j], name, len)) {
+ chase->rrsets[chase->an_numrrsets++] = orig->rrsets[j];
+ chase->rrsets[chase->an_numrrsets++] = orig->rrsets[i];
}
- }
+ }
/* AUTHORITY section */
for(i = (skip > orig->an_numrrsets)?skip:orig->an_numrrsets;
i<orig->an_numrrsets+orig->ns_numrrsets;
diff --git a/validator/val_utils.h b/validator/val_utils.h
index e8cdcefa6923..4fe38c1bb995 100644
--- a/validator/val_utils.h
+++ b/validator/val_utils.h
@@ -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.
diff --git a/validator/validator.c b/validator/validator.c
index 3cf291658e71..e6d19a2c9f06 100644
--- a/validator/validator.c
+++ b/validator/validator.c
@@ -72,7 +72,8 @@
/* forward decl for cache response and normal super inform calls of a DS */
static void process_ds_response(struct module_qstate* qstate,
struct val_qstate* vq, int id, int rcode, struct dns_msg* msg,
- struct query_info* qinfo, struct sock_list* origin, int* suspend);
+ struct query_info* qinfo, struct sock_list* origin, int* suspend,
+ struct module_qstate* sub_qstate);
/* Updates the suplied EDE (RFC8914) code selectively so we don't lose
@@ -273,11 +274,17 @@ val_new_getmsg(struct module_qstate* qstate, struct val_qstate* vq)
return NULL;
if(vq->orig_msg->rep->rrset_count > RR_COUNT_MAX)
return NULL; /* protect against integer overflow */
- vq->chase_reply->rrsets = regional_alloc_init(qstate->region,
- vq->orig_msg->rep->rrsets, sizeof(struct ub_packed_rrset_key*)
- * vq->orig_msg->rep->rrset_count);
+ /* Over allocate (+an_numrrsets) in case we need to put extra DNAME
+ * records for unsigned CNAME repetitions */
+ vq->chase_reply->rrsets = regional_alloc(qstate->region,
+ sizeof(struct ub_packed_rrset_key*) *
+ (vq->orig_msg->rep->rrset_count
+ + vq->orig_msg->rep->an_numrrsets));
if(!vq->chase_reply->rrsets)
return NULL;
+ memmove(vq->chase_reply->rrsets, vq->orig_msg->rep->rrsets,
+ sizeof(struct ub_packed_rrset_key*) *
+ vq->orig_msg->rep->rrset_count);
vq->rrset_skip = 0;
return vq;
}
@@ -640,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;
@@ -675,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) {
@@ -720,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) {
@@ -766,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. */
@@ -2060,7 +2069,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id)
verbose(VERB_ALGO, "Process suspended sub DS response");
msg = vq->sub_ds_msg;
process_ds_response(qstate, vq, id, LDNS_RCODE_NOERROR,
- msg, &msg->qinfo, NULL, &suspend);
+ msg, &msg->qinfo, NULL, &suspend, NULL);
if(suspend) {
/* we'll come back here later to continue */
if(!validate_suspend_setup_timer(qstate, vq,
@@ -2076,7 +2085,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id)
vq->key_entry->name)) ) {
verbose(VERB_ALGO, "Process cached DS response");
process_ds_response(qstate, vq, id, LDNS_RCODE_NOERROR,
- msg, &msg->qinfo, NULL, &suspend);
+ msg, &msg->qinfo, NULL, &suspend, NULL);
if(suspend) {
/* we'll come back here later to continue */
if(!validate_suspend_setup_timer(qstate, vq,
@@ -2658,6 +2667,8 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
* @param ta: trust anchor.
* @param qstate: qstate that needs key.
* @param id: module id.
+ * @param sub_qstate: the sub query state, that is the lookup that fetched
+ * the trust anchor data, it contains error information for the answer.
* @return new key entry or NULL on allocation failure.
* The key entry will either contain a validated DNSKEY rrset, or
* represent a Null key (query failed, but validation did not), or a
@@ -2665,31 +2676,38 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
*/
static struct key_entry_key*
primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
- struct trust_anchor* ta, struct module_qstate* qstate, int id)
+ struct trust_anchor* ta, struct module_qstate* qstate, int id,
+ struct module_qstate* sub_qstate)
{
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;
if(!dnskey_rrset) {
+ char* err = errinf_to_str_misc(sub_qstate);
+ char rstr[1024];
log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- "
"could not fetch DNSKEY rrset",
ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass);
reason_bogus = LDNS_EDE_DNSKEY_MISSING;
- reason = "no DNSKEY rrset";
+ if(!err) {
+ snprintf(rstr, sizeof(rstr), "no DNSKEY rrset");
+ } else {
+ snprintf(rstr, sizeof(rstr), "no DNSKEY rrset "
+ "[%s]", err);
+ }
if(qstate->env->cfg->harden_dnssec_stripped) {
- errinf_ede(qstate, reason, reason_bogus);
+ errinf_ede(qstate, rstr, reason_bogus);
kkey = key_entry_create_bad(qstate->region, ta->name,
ta->namelen, ta->dclass, BOGUS_KEY_TTL,
- reason_bogus, reason,
- *qstate->env->now);
+ reason_bogus, rstr, *qstate->env->now);
} else kkey = key_entry_create_null(qstate->region, ta->name,
ta->namelen, ta->dclass, NULL_KEY_TTL,
- reason_bogus, reason,
- *qstate->env->now);
+ reason_bogus, rstr, *qstate->env->now);
if(!kkey) {
log_err("out of memory: allocate fail prime key");
return NULL;
@@ -2699,7 +2717,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;
@@ -2754,6 +2772,9 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
* DS response indicated an end to secure space, is_good if the DS
* validated. It returns ke=NULL if the DS response indicated that the
* request wasn't a delegation point.
+ * @param sub_qstate: the sub query state, that is the lookup that fetched
+ * the trust anchor data, it contains error information for the answer.
+ * Can be NULL.
* @return
* 0 on success,
* 1 on servfail error (malloc failure),
@@ -2762,9 +2783,10 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
static int
ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
int id, int rcode, struct dns_msg* msg, struct query_info* qinfo,
- struct key_entry_key** ke)
+ 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;
@@ -2777,6 +2799,14 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
verbose(VERB_DETAIL, "DS response was error, thus bogus");
errinf(qstate, rc);
reason = "no DS";
+ if(sub_qstate) {
+ char* err = errinf_to_str_misc(sub_qstate);
+ if(err) {
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "[%s]", err);
+ errinf(qstate, buf);
+ }
+ }
reason_bogus = LDNS_EDE_NETWORK_ERROR;
errinf_ede(qstate, reason, reason_bogus);
goto return_bogus;
@@ -2799,7 +2829,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");
@@ -2849,7 +2881,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 "
@@ -2886,7 +2919,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
@@ -2953,7 +2987,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");
@@ -3002,11 +3037,15 @@ return_bogus:
* @param origin: the origin of msg.
* @param suspend: returned true if the task takes too long and needs to
* suspend to continue the effort later.
+ * @param sub_qstate: the sub query state, that is the lookup that fetched
+ * the trust anchor data, it contains error information for the answer.
+ * Can be NULL.
*/
static void
process_ds_response(struct module_qstate* qstate, struct val_qstate* vq,
int id, int rcode, struct dns_msg* msg, struct query_info* qinfo,
- struct sock_list* origin, int* suspend)
+ struct sock_list* origin, int* suspend,
+ struct module_qstate* sub_qstate)
{
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
struct key_entry_key* dske = NULL;
@@ -3014,7 +3053,8 @@ process_ds_response(struct module_qstate* qstate, struct val_qstate* vq,
int ret;
*suspend = 0;
vq->empty_DS_name = NULL;
- ret = ds_response_to_ke(qstate, vq, id, rcode, msg, qinfo, &dske);
+ ret = ds_response_to_ke(qstate, vq, id, rcode, msg, qinfo, &dske,
+ sub_qstate);
if(ret != 0) {
switch(ret) {
case 1:
@@ -3090,16 +3130,19 @@ process_ds_response(struct module_qstate* qstate, struct val_qstate* vq,
* @param msg: result message (if rcode is OK).
* @param qinfo: from the sub query state, query info.
* @param origin: the origin of msg.
+ * @param sub_qstate: the sub query state, that is the lookup that fetched
+ * the trust anchor data, it contains error information for the answer.
*/
static void
process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
int id, int rcode, struct dns_msg* msg, struct query_info* qinfo,
- struct sock_list* origin)
+ struct sock_list* origin, struct module_qstate* sub_qstate)
{
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
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;
@@ -3107,6 +3150,8 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
dnskey = reply_find_answer_rrset(qinfo, msg->rep);
if(dnskey == NULL) {
+ char* err;
+ char rstr[1024];
/* bad response */
verbose(VERB_DETAIL, "Missing DNSKEY RRset in response to "
"DNSKEY query.");
@@ -3118,17 +3163,22 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
vq->restart_count++;
return;
}
- reason = "No DNSKEY record";
+ err = errinf_to_str_misc(sub_qstate);
+ if(!err) {
+ snprintf(rstr, sizeof(rstr), "No DNSKEY record");
+ } else {
+ snprintf(rstr, sizeof(rstr), "No DNSKEY record "
+ "[%s]", err);
+ }
reason_bogus = LDNS_EDE_DNSKEY_MISSING;
vq->key_entry = key_entry_create_bad(qstate->region,
qinfo->qname, qinfo->qname_len, qinfo->qclass,
- BOGUS_KEY_TTL, reason_bogus, reason,
- *qstate->env->now);
+ BOGUS_KEY_TTL, reason_bogus, rstr, *qstate->env->now);
if(!vq->key_entry) {
log_err("alloc failure in missing dnskey response");
/* key_entry is NULL for failure in Validate */
}
- errinf_ede(qstate, reason, reason_bogus);
+ errinf_ede(qstate, rstr, reason_bogus);
errinf_origin(qstate, origin);
errinf_dname(qstate, "for key", qinfo->qname);
vq->state = VAL_VALIDATE_STATE;
@@ -3142,7 +3192,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");
@@ -3192,10 +3243,13 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
* @param rcode: rcode result value.
* @param msg: result message (if rcode is OK).
* @param origin: the origin of msg.
+ * @param sub_qstate: the sub query state, that is the lookup that fetched
+ * the trust anchor data, it contains error information for the answer.
*/
static void
process_prime_response(struct module_qstate* qstate, struct val_qstate* vq,
- int id, int rcode, struct dns_msg* msg, struct sock_list* origin)
+ int id, int rcode, struct dns_msg* msg, struct sock_list* origin,
+ struct module_qstate* sub_qstate)
{
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
struct ub_packed_rrset_key* dnskey_rrset = NULL;
@@ -3227,7 +3281,8 @@ process_prime_response(struct module_qstate* qstate, struct val_qstate* vq,
return;
}
}
- vq->key_entry = primeResponseToKE(dnskey_rrset, ta, qstate, id);
+ vq->key_entry = primeResponseToKE(dnskey_rrset, ta, qstate, id,
+ sub_qstate);
lock_basic_unlock(&ta->lock);
if(vq->key_entry) {
if(key_entry_isbad(vq->key_entry)
@@ -3278,14 +3333,14 @@ val_inform_super(struct module_qstate* qstate, int id,
if(vq->wait_prime_ta) {
vq->wait_prime_ta = 0;
process_prime_response(super, vq, id, qstate->return_rcode,
- qstate->return_msg, qstate->reply_origin);
+ qstate->return_msg, qstate->reply_origin, qstate);
return;
}
if(qstate->qinfo.qtype == LDNS_RR_TYPE_DS) {
int suspend;
process_ds_response(super, vq, id, qstate->return_rcode,
qstate->return_msg, &qstate->qinfo,
- qstate->reply_origin, &suspend);
+ qstate->reply_origin, &suspend, qstate);
/* If NSEC3 was needed during validation, NULL the NSEC3 cache;
* it will be re-initiated if needed later on.
* Validation (and the cache table) are happening/allocated in
@@ -3306,7 +3361,7 @@ val_inform_super(struct module_qstate* qstate, int id,
} else if(qstate->qinfo.qtype == LDNS_RR_TYPE_DNSKEY) {
process_dnskey_response(super, vq, id, qstate->return_rcode,
qstate->return_msg, &qstate->qinfo,
- qstate->reply_origin);
+ qstate->reply_origin, qstate);
return;
}
log_err("internal error in validator: no inform_supers possible");
@@ -3344,8 +3399,8 @@ val_get_mem(struct module_env* env, int id)
*/
static struct module_func_block val_block = {
"validator",
- &val_init, &val_deinit, &val_operate, &val_inform_super, &val_clear,
- &val_get_mem
+ NULL, NULL, &val_init, &val_deinit, &val_operate, &val_inform_super,
+ &val_clear, &val_get_mem
};
struct module_func_block*