diff options
Diffstat (limited to 'validator/val_sigcrypt.c')
| -rw-r--r-- | validator/val_sigcrypt.c | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/validator/val_sigcrypt.c b/validator/val_sigcrypt.c index 37730f179676..f4b866366f3c 100644 --- a/validator/val_sigcrypt.c +++ b/validator/val_sigcrypt.c @@ -79,6 +79,9 @@ #include <openssl/engine.h> #endif +/** Maximum number of RRSIG validations for an RRset. */ +#define MAX_VALIDATE_RRSIGS 8 + /** return number of rrs in an rrset */ static size_t rrset_get_count(struct ub_packed_rrset_key* rrset) @@ -542,6 +545,8 @@ int algo_needs_missing(struct algo_needs* n) * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure. * @param section: section of packet where this rrset comes from. * @param qstate: qstate with region. + * @param numverified: incremented when the number of RRSIG validations + * increases. * @return secure if any key signs *this* signature. bogus if no key signs it, * unchecked on error, or indeterminate if all keys are not supported by * the crypto library (openssl3+ only). @@ -552,7 +557,8 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve, struct ub_packed_rrset_key* dnskey, size_t sig_idx, struct rbtree_type** sortree, char** reason, sldns_ede_code *reason_bogus, - sldns_pkt_section section, struct module_qstate* qstate) + sldns_pkt_section section, struct module_qstate* qstate, + int* numverified) { /* find matching keys and check them */ enum sec_status sec = sec_status_bogus; @@ -576,6 +582,7 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve, tag != dnskey_calc_keytag(dnskey, i)) continue; numchecked ++; + (*numverified)++; /* see if key verifies */ sec = dnskey_verify_rrset_sig(env->scratch, @@ -586,6 +593,13 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve, return sec; else if(sec == sec_status_indeterminate) numindeterminate ++; + if(*numverified > MAX_VALIDATE_RRSIGS) { + *reason = "too many RRSIG validations"; + if(reason_bogus) + *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; + verbose(VERB_ALGO, "verify sig: too many RRSIG validations"); + return sec_status_bogus; + } } if(numchecked == 0) { *reason = "signatures from unknown keys"; @@ -609,7 +623,7 @@ 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) + sldns_pkt_section section, struct module_qstate* qstate, int* verified) { enum sec_status sec; size_t i, num; @@ -617,6 +631,7 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve, /* make sure that for all DNSKEY algorithms there are valid sigs */ struct algo_needs needs; int alg; + *verified = 0; num = rrset_get_sigcount(rrset); if(num == 0) { @@ -641,7 +656,7 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve, for(i=0; i<num; i++) { sec = dnskeyset_verify_rrset_sig(env, ve, *env->now, rrset, dnskey, i, &sortree, reason, reason_bogus, - section, qstate); + section, qstate, verified); /* see which algorithm has been fixed up */ if(sec == sec_status_secure) { if(!sigalg) @@ -653,6 +668,13 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve, algo_needs_set_bogus(&needs, (uint8_t)rrset_get_sig_algo(rrset, i)); } + if(*verified > MAX_VALIDATE_RRSIGS) { + verbose(VERB_QUERY, "rrset failed to verify, too many RRSIG validations"); + *reason = "too many RRSIG validations"; + if(reason_bogus) + *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; + return sec_status_bogus; + } } if(sigalg && (alg=algo_needs_missing(&needs)) != 0) { verbose(VERB_ALGO, "rrset failed to verify: " @@ -691,6 +713,7 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve, int buf_canon = 0; uint16_t tag = dnskey_calc_keytag(dnskey, dnskey_idx); int algo = dnskey_get_algo(dnskey, dnskey_idx); + int numverified = 0; num = rrset_get_sigcount(rrset); if(num == 0) { @@ -714,8 +737,16 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve, if(sec == sec_status_secure) return sec; numchecked ++; + numverified ++; if(sec == sec_status_indeterminate) numindeterminate ++; + if(numverified > MAX_VALIDATE_RRSIGS) { + verbose(VERB_QUERY, "rrset failed to verify, too many RRSIG validations"); + *reason = "too many RRSIG validations"; + if(reason_bogus) + *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; + return sec_status_bogus; + } } verbose(VERB_ALGO, "rrset failed to verify: all signatures are bogus"); if(!numchecked) { |
