diff options
Diffstat (limited to 'validator')
| -rw-r--r-- | validator/autotrust.c | 3 | ||||
| -rw-r--r-- | validator/val_nsec.c | 12 | ||||
| -rw-r--r-- | validator/val_nsec.h | 4 | ||||
| -rw-r--r-- | validator/val_nsec3.c | 9 | ||||
| -rw-r--r-- | validator/val_nsec3.h | 4 | ||||
| -rw-r--r-- | validator/val_secalgo.c | 8 | ||||
| -rw-r--r-- | validator/val_sigcrypt.c | 19 | ||||
| -rw-r--r-- | validator/val_sigcrypt.h | 12 | ||||
| -rw-r--r-- | validator/val_utils.c | 82 | ||||
| -rw-r--r-- | validator/val_utils.h | 26 | ||||
| -rw-r--r-- | validator/validator.c | 129 |
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* |
