From 42d7cdb7d58425456fc6607db89c8a70e8f4d68b Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 14 Oct 2020 14:46:59 +0200 Subject: [PATCH] zonemd, region freed, and qstate not used when not in a query, and nsec and nsec3 bitmap checks. --- services/authzone.c | 71 ++++++++++++++++++++++++++++++---------- validator/val_sigcrypt.c | 2 +- 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/services/authzone.c b/services/authzone.c index df77b12a2..0507c66ca 100644 --- a/services/authzone.c +++ b/services/authzone.c @@ -67,6 +67,7 @@ #include "sldns/parseutil.h" #include "sldns/keyraw.h" #include "validator/val_nsec3.h" +#include "validator/val_nsec.h" #include "validator/val_secalgo.h" #include "validator/val_sigcrypt.h" #include "validator/val_anchor.h" @@ -7516,8 +7517,10 @@ int auth_zone_generate_zonemd_check(struct auth_zone* z, int scheme, } /** log auth zone message with zone name in front. */ -static void auth_zone_log(uint8_t* name, enum verbosity_value level, const char* format, ...) ATTR_FORMAT(printf, 3, 4); -static void auth_zone_log(uint8_t* name, enum verbosity_value level, const char* format, ...) +static void auth_zone_log(uint8_t* name, enum verbosity_value level, + const char* format, ...) ATTR_FORMAT(printf, 3, 4); +static void auth_zone_log(uint8_t* name, enum verbosity_value level, + const char* format, ...) { va_list args; va_start(args, format); @@ -7532,8 +7535,9 @@ static void auth_zone_log(uint8_t* name, enum verbosity_value level, const char* } /** ZONEMD, dnssec verify the rrset with the dnskey */ -static int zonemd_dnssec_verify(struct auth_zone* z, struct module_env* env, - struct ub_packed_rrset_key* dnskey, struct auth_rrset* rrset) +static int zonemd_dnssec_verify_rrset(struct auth_zone* z, + struct module_env* env, struct ub_packed_rrset_key* dnskey, + struct auth_data* node, struct auth_rrset* rrset) { struct ub_packed_rrset_key pk; enum sec_status sec; @@ -7543,7 +7547,7 @@ static int zonemd_dnssec_verify(struct auth_zone* z, struct module_env* env, m = modstack_find(&env->mesh->mods, "validator"); if(m == -1) { auth_zone_log(z->name, VERB_ALGO, "zonemd dnssec verify: have " - "trust anchor, but no validator module"); + "DNSKEY chain of trust, but no validator module"); return 0; } ve = (struct val_env*)env->modinfo[m]; @@ -7551,17 +7555,14 @@ static int zonemd_dnssec_verify(struct auth_zone* z, struct module_env* env, memset(&pk, 0, sizeof(pk)); pk.entry.key = &pk; pk.entry.data = rrset->data; - pk.rk.dname = z->name; - pk.rk.dname_len = z->namelen; + pk.rk.dname = node->name; + pk.rk.dname_len = node->namelen; pk.rk.type = htons(rrset->type); pk.rk.rrset_class = htons(z->dclass); auth_zone_log(z->name, VERB_ALGO, "zonemd: verify RRset with DNSKEY"); - /* pass NULL for qstate, it is only used for qtype NSEC to realloc - * a new name in the qstate region */ sec = dnskeyset_verify_rrset(env, ve, &pk, dnskey, NULL, &why_bogus, LDNS_SECTION_ANSWER, NULL); - regional_free_all(env->scratch); if(sec == sec_status_secure) { return 1; } @@ -7570,6 +7571,30 @@ static int zonemd_dnssec_verify(struct auth_zone* z, struct module_env* env, return 0; } +/** check for nsec3, the RR with params equal, if bitmap has the type */ +static int nsec3_of_param_has_type(struct auth_rrset* nsec3, int algo, + size_t iter, uint8_t* salt, size_t saltlen, uint16_t rrtype) +{ + size_t i; + struct ub_packed_rrset_key pk; + memset(&pk, 0, sizeof(pk)); + pk.entry.data = nsec3->data; + for(i=0; idata->count; i++) { + int rralgo; + size_t rriter, rrsaltlen; + uint8_t* rrsalt; + if(!nsec3_get_params(&pk, i, &rralgo, &rriter, &rrsalt, + &rrsaltlen)) + continue; /* no parameters, malformed */ + if(rralgo != algo || rriter != iter || rrsaltlen != saltlen || + memcmp(rrsalt, salt, saltlen) != 0) + continue; /* different parameters */ + if(nsec3_has_type(&pk, i, rrtype)) + return 1; + } + return 0; +} + /** Verify the absence of ZONEMD with DNSSEC by checking NSEC, NSEC3 type flag. * return false on failure, reason contains description of failure. */ static int zonemd_check_dnssec_absence(struct auth_zone* z, @@ -7583,12 +7608,19 @@ static int zonemd_check_dnssec_absence(struct auth_zone* z, } nsec = az_domain_rrset(apex, LDNS_RR_TYPE_NSEC); if(nsec) { + struct ub_packed_rrset_key pk; /* dnssec verify the NSEC */ - if(!zonemd_dnssec_verify(z, env, dnskey, nsec)) { + if(!zonemd_dnssec_verify_rrset(z, env, dnskey, apex, nsec)) { *reason = "DNSSEC verify failed for NSEC RRset"; return 0; } /* check type bitmap */ + memset(&pk, 0, sizeof(pk)); + pk.entry.data = nsec->data; + if(nsec_has_type(&pk, LDNS_RR_TYPE_ZONEMD)) { + *reason = "DNSSEC NSEC bitmap says type ZONEMD exists"; + return 0; + } } else { /* NSEC3 perhaps ? */ int algo; @@ -7619,11 +7651,16 @@ static int zonemd_check_dnssec_absence(struct auth_zone* z, return 0; } /* dnssec verify the NSEC3 */ - if(!zonemd_dnssec_verify(z, env, dnskey, nsec3)) { + if(!zonemd_dnssec_verify_rrset(z, env, dnskey, match, nsec3)) { *reason = "DNSSEC verify failed for NSEC3 RRset"; return 0; } /* check type bitmap */ + if(nsec3_of_param_has_type(nsec3, algo, iter, salt, saltlen, + LDNS_RR_TYPE_ZONEMD)) { + *reason = "DNSSEC NSEC3 bitmap says type ZONEMD exists"; + return 0; + } } return 1; @@ -7646,11 +7683,11 @@ static int zonemd_check_dnssec_soazonemd(struct auth_zone* z, *reason = "zone has no SOA RRset"; return 0; } - if(!zonemd_dnssec_verify(z, env, dnskey, soa)) { + if(!zonemd_dnssec_verify_rrset(z, env, dnskey, apex, soa)) { *reason = "DNSSEC verify failed for SOA RRset"; return 0; } - if(!zonemd_dnssec_verify(z, env, dnskey, zonemd_rrset)) { + if(!zonemd_dnssec_verify_rrset(z, env, dnskey, apex, zonemd_rrset)) { *reason = "DNSSEC verify failed for ZONEMD RRset"; return 0; } @@ -7797,8 +7834,6 @@ zonemd_get_dnskey_from_anchor(struct auth_zone* z, struct module_env* env, keystorage->rk.rrset_class = htons(z->dclass); auth_zone_log(z->name, VERB_QUERY, "zonemd: verify DNSKEY RRset with trust anchor"); - /* pass NULL for qstate, it is only used when type NSEC needs a - * name reallocated to get the qstate region for that */ sec = val_verify_DNSKEY_with_TA(env, ve, keystorage, anchor->ds_rrset, anchor->dnskey_rrset, NULL, reason, NULL); regional_free_all(env->scratch); @@ -7842,7 +7877,7 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf, if(!reason) reason = "lookup of DNSKEY was bogus"; auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of DNSKEY was bogus: %s", why_bogus); + "zonemd lookup of DNSKEY was bogus: %s", reason); } else if(rcode == LDNS_RCODE_NOERROR) { uint16_t wanted_qtype = LDNS_RR_TYPE_DNSKEY; struct regional* temp = env->scratch; @@ -7894,6 +7929,7 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf, } auth_zone_verify_zonemd_with_key(z, env, dnskey, is_insecure); + regional_free_all(env->scratch); lock_rw_unlock(&z->lock); } @@ -7998,4 +8034,5 @@ void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env) } auth_zone_verify_zonemd_with_key(z, env, dnskey, is_insecure); + regional_free_all(env->scratch); } diff --git a/validator/val_sigcrypt.c b/validator/val_sigcrypt.c index 10cf2caee..14e13da06 100644 --- a/validator/val_sigcrypt.c +++ b/validator/val_sigcrypt.c @@ -1187,7 +1187,7 @@ rrset_canonical(struct regional* region, sldns_buffer* buf, * section, to prevent that a wildcard synthesized NSEC can be used in * the non-existence proves. */ if(ntohs(k->rk.type) == LDNS_RR_TYPE_NSEC && - section == LDNS_SECTION_AUTHORITY) { + section == LDNS_SECTION_AUTHORITY && qstate) { k->rk.dname = regional_alloc_init(qstate->region, can_owner, can_owner_len); if(!k->rk.dname) -- 2.47.2