diff options
Diffstat (limited to 'external/unbound/validator/val_utils.c')
-rw-r--r-- | external/unbound/validator/val_utils.c | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/external/unbound/validator/val_utils.c b/external/unbound/validator/val_utils.c index 475b0c905..e3677e1d9 100644 --- a/external/unbound/validator/val_utils.c +++ b/external/unbound/validator/val_utils.c @@ -54,6 +54,8 @@ #include "util/net_help.h" #include "util/module.h" #include "util/regional.h" +#include "sldns/wire2str.h" +#include "sldns/parseutil.h" enum val_classification val_classify_response(uint16_t query_flags, struct query_info* origqinf, @@ -217,7 +219,7 @@ val_find_signer(enum val_classification subtype, struct query_info* qinf, { size_t i; - if(subtype == VAL_CLASS_POSITIVE || subtype == VAL_CLASS_ANY) { + if(subtype == VAL_CLASS_POSITIVE) { /* check for the answer rrset */ for(i=skip; i<rep->an_numrrsets; i++) { if(query_dname_compare(qinf->qname, @@ -269,6 +271,29 @@ val_find_signer(enum val_classification subtype, struct query_info* qinf, signer_name, signer_len, &matchcount); } } + } else if(subtype == VAL_CLASS_ANY) { + /* check for one of the answer rrset that has signatures, + * or potentially a DNAME is in use with a different qname */ + for(i=skip; i<rep->an_numrrsets; i++) { + if(query_dname_compare(qinf->qname, + rep->rrsets[i]->rk.dname) == 0) { + val_find_rrset_signer(rep->rrsets[i], + signer_name, signer_len); + if(*signer_name) + return; + } + } + /* no answer RRSIGs with qname, try a DNAME */ + if(skip < rep->an_numrrsets && + ntohs(rep->rrsets[skip]->rk.type) == + LDNS_RR_TYPE_DNAME) { + val_find_rrset_signer(rep->rrsets[skip], + signer_name, signer_len); + if(*signer_name) + return; + } + *signer_name = NULL; + *signer_len = 0; } else if(subtype == VAL_CLASS_REFERRAL) { /* find keys for the item at skip */ if(skip < rep->rrset_count) { @@ -470,16 +495,21 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve, return sec_status_bogus; } - digest_algo = val_favorite_ds_algo(ds_rrset); - if(sigalg) + if(sigalg) { + /* harden against algo downgrade is enabled */ + digest_algo = val_favorite_ds_algo(ds_rrset); algo_needs_init_ds(&needs, ds_rrset, digest_algo, sigalg); + } else { + /* accept any key algo, any digest algo */ + digest_algo = -1; + } num = rrset_get_count(ds_rrset); for(i=0; i<num; i++) { /* Check to see if we can understand this DS. * And check it is the strongest digest */ if(!ds_digest_algo_is_supported(ds_rrset, i) || !ds_key_algo_is_supported(ds_rrset, i) || - ds_get_digest_algo(ds_rrset, i) != digest_algo) { + (sigalg && (ds_get_digest_algo(ds_rrset, i) != digest_algo))) { continue; } @@ -691,6 +721,31 @@ val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset) ds_key_algo_is_supported(ds_rrset, i)) return 1; } + if(verbosity < VERB_ALGO) + return 0; + if(rrset_get_count(ds_rrset) == 0) + verbose(VERB_ALGO, "DS is not usable"); + else { + /* report usability for the first DS RR */ + sldns_lookup_table *lt; + char herr[64], aerr[64]; + lt = sldns_lookup_by_id(sldns_hashes, + (int)ds_get_digest_algo(ds_rrset, i)); + if(lt) snprintf(herr, sizeof(herr), "%s", lt->name); + else snprintf(herr, sizeof(herr), "%d", + (int)ds_get_digest_algo(ds_rrset, i)); + lt = sldns_lookup_by_id(sldns_algorithms, + (int)ds_get_key_algo(ds_rrset, i)); + if(lt) snprintf(aerr, sizeof(aerr), "%s", lt->name); + else snprintf(aerr, sizeof(aerr), "%d", + (int)ds_get_key_algo(ds_rrset, i)); + verbose(VERB_ALGO, "DS unsupported, hash %s %s, " + "key algorithm %s %s", herr, + (ds_digest_algo_is_supported(ds_rrset, 0)? + "(supported)":"(unsupported)"), aerr, + (ds_key_algo_is_supported(ds_rrset, 0)? + "(supported)":"(unsupported)")); + } return 0; } @@ -1088,6 +1143,7 @@ val_find_DS(struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t c, qinfo.qname_len = nmlen; qinfo.qtype = LDNS_RR_TYPE_DS; qinfo.qclass = c; + qinfo.local_alias = NULL; /* do not add SOA to reply message, it is going to be used internal */ msg = val_neg_getmsg(env->neg_cache, &qinfo, region, env->rrset_cache, env->scratch_buffer, *env->now, 0, topname); |