diff options
author | Tomas Krizek <tomas.krizek@nic.cz> | 2021-03-24 17:44:45 +0100 |
---|---|---|
committer | Tomas Krizek <tomas.krizek@nic.cz> | 2021-05-25 14:39:41 +0200 |
commit | f6d1a15cd3bab4b93ff79794fe42d51ec3097575 (patch) | |
tree | 12436553f3193ea992a092b7982058a9a744c89d /lib/dnssec | |
parent | lib/dnssec/nsec.h: replace asserts (diff) | |
download | knot-resolver-f6d1a15cd3bab4b93ff79794fe42d51ec3097575.tar.xz knot-resolver-f6d1a15cd3bab4b93ff79794fe42d51ec3097575.zip |
lib/dnssec/nsec3.c: replace asserts
Diffstat (limited to 'lib/dnssec')
-rw-r--r-- | lib/dnssec/nsec.c | 4 | ||||
-rw-r--r-- | lib/dnssec/nsec3.c | 207 |
2 files changed, 83 insertions, 128 deletions
diff --git a/lib/dnssec/nsec.c b/lib/dnssec/nsec.c index 9cf5719f..ae4a4046 100644 --- a/lib/dnssec/nsec.c +++ b/lib/dnssec/nsec.c @@ -103,7 +103,7 @@ static int nsec_covers(const knot_rrset_t *nsec, const knot_dname_t *sname) { if (!kr_assume(nsec && sname)) return kr_error(EINVAL); - if (dname_cmp(sname, nsec->owner) <= 0) { + if (dname_cmp(sname, nsec->owner) <= 0) return abs(ENOENT); /* 'sname' before 'owner', so can't be covered */ /* If NSEC 'owner' >= 'next', it means that there is nothing after 'owner' */ @@ -116,7 +116,7 @@ static int nsec_covers(const knot_rrset_t *nsec, const knot_dname_t *sname) const bool is_last_nsec = dname_cmp(nsec->owner, next) >= 0; const bool in_range = is_last_nsec || dname_cmp(sname, next) < 0; - if (!in_range) { + if (!in_range) return abs(ENOENT); /* Before returning kr_ok(), we have to check a special case: * sname might be under delegation from owner and thus diff --git a/lib/dnssec/nsec3.c b/lib/dnssec/nsec3.c index f3a48c06..04e178ac 100644 --- a/lib/dnssec/nsec3.c +++ b/lib/dnssec/nsec3.c @@ -2,7 +2,6 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -#include <assert.h> #include <string.h> #include <libdnssec/binary.h> @@ -16,6 +15,7 @@ #include "lib/defines.h" #include "lib/dnssec/nsec.h" #include "lib/dnssec/nsec3.h" +#include "lib/utils.h" #define OPT_OUT_BIT 0x01 @@ -34,10 +34,12 @@ */ static int nsec3_parameters(dnssec_nsec3_params_t *params, const knot_rrset_t *nsec3) { - assert(params && nsec3); + if (!kr_assume(params && nsec3)) + return kr_error(EINVAL); const knot_rdata_t *rr = knot_rdataset_at(&nsec3->rrs, 0); - assert(rr); + if (!kr_assume(rr)) + return kr_error(EINVAL); /* Every NSEC3 RR contains data from NSEC3PARAMS. */ const size_t SALT_OFFSET = 5; /* First 5 octets contain { Alg, Flags, Iterations, Salt length } */ @@ -49,9 +51,8 @@ static int nsec3_parameters(dnssec_nsec3_params_t *params, const knot_rrset_t *n return kr_error(EMSGSIZE); int ret = dnssec_nsec3_params_from_rdata(params, &rdata); - if (ret != DNSSEC_EOK) { + if (ret != DNSSEC_EOK) return kr_error(EINVAL); - } return kr_ok(); } @@ -66,11 +67,12 @@ static int nsec3_parameters(dnssec_nsec3_params_t *params, const knot_rrset_t *n static int hash_name(dnssec_binary_t *hash, const dnssec_nsec3_params_t *params, const knot_dname_t *name) { - assert(hash && params); + if (!kr_assume(hash && params)) + return kr_error(EINVAL); if (!name) return kr_error(EINVAL); - if (params->iterations > KR_NSEC3_MAX_ITERATIONS) { - assert(false); // This if is mainly defensive; it shouldn't happen. + if (!kr_assume(params->iterations <= KR_NSEC3_MAX_ITERATIONS)) { + /* This if is mainly defensive; it shouldn't happen. */ return kr_error(EINVAL); } @@ -96,13 +98,12 @@ static int hash_name(dnssec_binary_t *hash, const dnssec_nsec3_params_t *params, */ static int read_owner_hash(dnssec_binary_t *hash, size_t max_hash_size, const knot_rrset_t *nsec3) { - assert(hash && nsec3); - assert(hash->data); + if (!kr_assume(hash && nsec3 && hash->data)) + return kr_error(EINVAL); int32_t ret = base32hex_decode(nsec3->owner + 1, nsec3->owner[0], hash->data, max_hash_size); - if (ret < 0) { + if (ret < 0) return kr_error(EILSEQ); - } hash->size = ret; return kr_ok(); @@ -120,7 +121,8 @@ static int read_owner_hash(dnssec_binary_t *hash, size_t max_hash_size, const kn static int closest_encloser_match(int *flags, const knot_rrset_t *nsec3, const knot_dname_t *name, unsigned *skipped) { - assert(flags && nsec3 && name && skipped); + if (!kr_assume(flags && nsec3 && name && skipped)) + return kr_error(EINVAL); uint8_t hash_data[MAX_HASH_BYTES] = {0, }; dnssec_binary_t owner_hash = { 0, hash_data }; @@ -128,14 +130,12 @@ static int closest_encloser_match(int *flags, const knot_rrset_t *nsec3, dnssec_binary_t name_hash = { 0, }; int ret = read_owner_hash(&owner_hash, MAX_HASH_BYTES, nsec3); - if (ret != 0) { + if (ret != 0) goto fail; - } ret = nsec3_parameters(¶ms, nsec3); - if (ret != 0) { + if (ret != 0) goto fail; - } /* Root label has no encloser */ if (!name[0]) { @@ -148,9 +148,8 @@ static int closest_encloser_match(int *flags, const knot_rrset_t *nsec3, while(encloser) { ret = hash_name(&name_hash, ¶ms, encloser); - if (ret != 0) { + if (ret != 0) goto fail; - } if ((owner_hash.size == name_hash.size) && (memcmp(owner_hash.data, name_hash.data, owner_hash.size) == 0)) { @@ -170,12 +169,10 @@ static int closest_encloser_match(int *flags, const knot_rrset_t *nsec3, ret = kr_ok(); fail: - if (params.salt.data) { + if (params.salt.data) dnssec_nsec3_params_free(¶ms); - } - if (name_hash.data) { + if (name_hash.data) dnssec_binary_free(&name_hash); - } return ret; } @@ -188,7 +185,8 @@ fail: */ static int covers_name(int *flags, const knot_rrset_t *nsec3, const knot_dname_t *name) { - assert(flags && nsec3 && name); + if (!kr_assume(flags && nsec3 && name)) + return kr_error(EINVAL); uint8_t hash_data[MAX_HASH_BYTES] = { 0, }; dnssec_binary_t owner_hash = { 0, hash_data }; @@ -196,19 +194,16 @@ static int covers_name(int *flags, const knot_rrset_t *nsec3, const knot_dname_t dnssec_binary_t name_hash = { 0, }; int ret = read_owner_hash(&owner_hash, MAX_HASH_BYTES, nsec3); - if (ret != 0) { + if (ret != 0) goto fail; - } ret = nsec3_parameters(¶ms, nsec3); - if (ret != 0) { + if (ret != 0) goto fail; - } ret = hash_name(&name_hash, ¶ms, name); - if (ret != 0) { + if (ret != 0) goto fail; - } uint8_t next_size = knot_nsec3_next_len(nsec3->rrs.rdata); const uint8_t *next_hash = knot_nsec3_next(nsec3->rrs.rdata); @@ -254,12 +249,10 @@ static int covers_name(int *flags, const knot_rrset_t *nsec3, const knot_dname_t } fail: - if (params.salt.data) { + if (params.salt.data) dnssec_nsec3_params_free(¶ms); - } - if (name_hash.data) { + if (name_hash.data) dnssec_binary_free(&name_hash); - } return ret; } @@ -272,9 +265,8 @@ fail: */ static bool has_optout(const knot_rrset_t *nsec3) { - if (!nsec3) { + if (!nsec3) return false; - } uint8_t nsec3_flags = knot_nsec3_flags(nsec3->rrs.rdata); if (nsec3_flags & ~OPT_OUT_BIT) { @@ -294,7 +286,8 @@ static bool has_optout(const knot_rrset_t *nsec3) */ static int matches_name(const knot_rrset_t *nsec3, const knot_dname_t *name) { - assert(nsec3 && name); + if (!kr_assume(nsec3 && name)) + return kr_error(EINVAL); uint8_t hash_data[MAX_HASH_BYTES] = { 0, }; dnssec_binary_t owner_hash = { 0, hash_data }; @@ -302,19 +295,16 @@ static int matches_name(const knot_rrset_t *nsec3, const knot_dname_t *name) dnssec_binary_t name_hash = { 0, }; int ret = read_owner_hash(&owner_hash, MAX_HASH_BYTES, nsec3); - if (ret != 0) { + if (ret != 0) goto fail; - } ret = nsec3_parameters(¶ms, nsec3); - if (ret != 0) { + if (ret != 0) goto fail; - } ret = hash_name(&name_hash, ¶ms, name); - if (ret != 0) { + if (ret != 0) goto fail; - } if ((owner_hash.size == name_hash.size) && (memcmp(owner_hash.data, name_hash.data, owner_hash.size) == 0)) { @@ -324,12 +314,10 @@ static int matches_name(const knot_rrset_t *nsec3, const knot_dname_t *name) } fail: - if (params.salt.data) { + if (params.salt.data) dnssec_nsec3_params_free(¶ms); - } - if (name_hash.data) { + if (name_hash.data) dnssec_binary_free(&name_hash); - } return ret; } #undef MAX_HASH_BYTES @@ -343,7 +331,8 @@ fail: */ static int prepend_asterisk(uint8_t *tgt, size_t maxlen, const knot_dname_t *name) { - assert(maxlen >= 3); + if (!kr_assume(maxlen >= 3)) + return kr_error(EINVAL); memcpy(tgt, "\1*", 3); return knot_dname_to_wire(tgt + 2, name, maxlen - 2); } @@ -367,9 +356,8 @@ static int closest_encloser_proof(const knot_pkt_t *pkt, const knot_rrset_t **covering_next_nsec3) { const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id); - if (!sec || !sname) { + if (!sec || !sname) return kr_error(EINVAL); - } const knot_rrset_t *matching = NULL; const knot_rrset_t *covering = NULL; @@ -378,9 +366,8 @@ static int closest_encloser_proof(const knot_pkt_t *pkt, const knot_dname_t *next_closer = NULL; for (unsigned i = 0; i < sec->count; ++i) { const knot_rrset_t *rrset = knot_pkt_rr(sec, i); - if (rrset->type != KNOT_RRTYPE_NSEC3) { + if (rrset->type != KNOT_RRTYPE_NSEC3) continue; - } /* Also skip the NSEC3-to-match an ancestor of sname if it's * a parent-side delegation, as that would mean the owner * does not really exist (authoritatively in this zone, @@ -388,57 +375,49 @@ static int closest_encloser_proof(const knot_pkt_t *pkt, */ const uint8_t *bm = knot_nsec3_bitmap(rrset->rrs.rdata); uint16_t bm_size = knot_nsec3_bitmap_len(rrset->rrs.rdata); - if (kr_nsec_children_in_zone_check(bm, bm_size) != 0) { + if (kr_nsec_children_in_zone_check(bm, bm_size) != 0) continue; /* no fatal errors from bad RRs */ - } /* Match the NSEC3 to sname or one of its ancestors. */ unsigned skipped = 0; flags = 0; int ret = closest_encloser_match(&flags, rrset, sname, &skipped); - if (ret != 0) { + if (ret != 0) return ret; - } - if (!(flags & FLG_CLOSEST_PROVABLE_ENCLOSER)) { + if (!(flags & FLG_CLOSEST_PROVABLE_ENCLOSER)) continue; - } matching = rrset; /* Construct the next closer name and try to cover it. */ --skipped; next_closer = sname; for (unsigned j = 0; j < skipped; ++j) { - assert(next_closer[0]); + if (!kr_assume(next_closer[0])) + return kr_error(EINVAL); next_closer = knot_wire_next_label(next_closer, NULL); } for (unsigned j = 0; j < sec->count; ++j) { const knot_rrset_t *rrset_j = knot_pkt_rr(sec, j); - if (rrset_j->type != KNOT_RRTYPE_NSEC3) { + if (rrset_j->type != KNOT_RRTYPE_NSEC3) continue; - } ret = covers_name(&flags, rrset_j, next_closer); - if (ret != 0) { + if (ret != 0) return ret; - } if (flags & FLG_NAME_COVERED) { covering = rrset_j; break; } } - if (flags & FLG_NAME_COVERED) { + if (flags & FLG_NAME_COVERED) break; - } flags = 0; // } if ((flags & FLG_CLOSEST_PROVABLE_ENCLOSER) && (flags & FLG_NAME_COVERED) && next_closer) { - if (encloser_name && next_closer[0]) { + if (encloser_name && next_closer[0]) *encloser_name = knot_wire_next_label(next_closer, NULL); - } - if (matching_encloser_nsec3) { + if (matching_encloser_nsec3) *matching_encloser_nsec3 = matching; - } - if (covering_next_nsec3) { + if (covering_next_nsec3) *covering_next_nsec3 = covering; - } return kr_ok(); } @@ -459,29 +438,25 @@ static int covers_closest_encloser_wildcard(const knot_pkt_t *pkt, knot_section_ const knot_dname_t *encloser) { const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id); - if (!sec || !encloser) { + if (!sec || !encloser) return kr_error(EINVAL); - } uint8_t wildcard[KNOT_DNAME_MAXLEN]; wildcard[0] = 1; wildcard[1] = '*'; int encloser_len = knot_dname_size(encloser); - if (encloser_len < 0) { + if (encloser_len < 0) return encloser_len; - } memcpy(wildcard + 2, encloser, encloser_len); int flags = 0; for (unsigned i = 0; i < sec->count; ++i) { const knot_rrset_t *rrset = knot_pkt_rr(sec, i); - if (rrset->type != KNOT_RRTYPE_NSEC3) { + if (rrset->type != KNOT_RRTYPE_NSEC3) continue; - } int ret = covers_name(&flags, rrset, wildcard); - if (ret != 0) { + if (ret != 0) return ret; - } if (flags & FLG_NAME_COVERED) { return has_optout(rrset) ? kr_error(KNOT_ERANGE) : kr_ok(); @@ -498,9 +473,8 @@ int kr_nsec3_name_error_response_check(const knot_pkt_t *pkt, knot_section_t sec const knot_rrset_t *covering_next_nsec3 = NULL; int ret = closest_encloser_proof(pkt, section_id, sname, &encloser, NULL, &covering_next_nsec3); - if (ret != 0) { + if (ret != 0) return ret; - } ret = covers_closest_encloser_wildcard(pkt, section_id, encloser); if (ret != 0) { /* OK, but NSEC3 for wildcard at encloser has opt-out; @@ -528,9 +502,8 @@ static int nodata_find(const knot_pkt_t *pkt, knot_section_t section_id, const knot_dname_t *name, const uint16_t type) { const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id); - if (!sec || !name) { + if (!sec || !name) return kr_error(EINVAL); - } for (unsigned i = 0; i < sec->count; ++i) { const knot_rrset_t *nsec3 = knot_pkt_rr(sec, i); @@ -543,9 +516,8 @@ static int nodata_find(const knot_pkt_t *pkt, knot_section_t section_id, const uint8_t *bm = knot_nsec3_bitmap(nsec3->rrs.rdata); uint16_t bm_size = knot_nsec3_bitmap_len(nsec3->rrs.rdata); - if (kr_nsec_bitmap_nodata_check(bm, bm_size, type, nsec3->owner) == kr_ok()) { + if (kr_nsec_bitmap_nodata_check(bm, bm_size, type, nsec3->owner) == kr_ok()) return kr_ok(); - } } return kr_error(ENOENT); @@ -563,16 +535,14 @@ static int matches_closest_encloser_wildcard(const knot_pkt_t *pkt, knot_section const knot_dname_t *encloser, uint16_t stype) { const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id); - if (!sec || !encloser) { + if (!sec || !encloser) return kr_error(EINVAL); - } uint8_t wildcard[KNOT_DNAME_MAXLEN]; /**< the source of synthesis */ int ret = prepend_asterisk(wildcard, sizeof(wildcard), encloser); - if (ret < 0) { + if (ret < 0) return ret; - } - assert(ret >= 3); + kr_require(ret >= 3); return nodata_find(pkt, section_id, wildcard, stype); } @@ -580,22 +550,21 @@ int kr_nsec3_wildcard_answer_response_check(const knot_pkt_t *pkt, knot_section_ const knot_dname_t *sname, int trim_to_next) { const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id); - if (!sec || !sname) { + if (!sec || !sname) return kr_error(EINVAL); - } /* Compute the next closer name. */ for (int i = 0; i < trim_to_next; ++i) { - assert(sname[0]); + if (!kr_assume(sname[0])) + return kr_error(EINVAL); sname = knot_wire_next_label(sname, NULL); } int flags = 0; for (unsigned i = 0; i < sec->count; ++i) { const knot_rrset_t *rrset = knot_pkt_rr(sec, i); - if (rrset->type != KNOT_RRTYPE_NSEC3) { + if (rrset->type != KNOT_RRTYPE_NSEC3) continue; - } if (knot_nsec3_iters(rrset->rrs.rdata) > KR_NSEC3_MAX_ITERATIONS) { /* Avoid hashing with too many iterations. * If we get here, the `sname` wildcard probably ends up bogus, @@ -604,9 +573,8 @@ int kr_nsec3_wildcard_answer_response_check(const knot_pkt_t *pkt, knot_section_ continue; } int ret = covers_name(&flags, rrset, sname); - if (ret != 0) { + if (ret != 0) return ret; - } if (flags & FLG_NAME_COVERED) { return has_optout(rrset) ? kr_error(KNOT_ERANGE) : kr_ok(); @@ -632,11 +600,11 @@ int kr_nsec3_no_data(const knot_pkt_t *pkt, knot_section_t section_id, const knot_rrset_t *covering_next_nsec3 = NULL; ret = closest_encloser_proof(pkt, section_id, sname, &encloser_name, NULL, &covering_next_nsec3); - if (ret != 0) { + if (ret != 0) return ret; - } - assert(encloser_name && covering_next_nsec3); + if (!kr_assume(encloser_name && covering_next_nsec3)) + return kr_error(EFAULT); ret = matches_closest_encloser_wildcard(pkt, section_id, encloser_name, stype); if (ret == 0) { @@ -656,7 +624,7 @@ int kr_nsec3_no_data(const knot_pkt_t *pkt, knot_section_t section_id, /* Bogus */ ret = kr_error(ENOENT); } else { - /* + /* * Satisfies RFC5155 8.6 (QTYPE == DS), 2nd paragraph. * Also satisfies ERRATA 3441 8.5 (QTYPE != DS), 3rd paragraph. * - (wildcard) empty nonterminal @@ -673,40 +641,33 @@ int kr_nsec3_no_data(const knot_pkt_t *pkt, knot_section_t section_id, int kr_nsec3_ref_to_unsigned(const knot_pkt_t *pkt) { const knot_pktsection_t *sec = knot_pkt_section(pkt, KNOT_AUTHORITY); - if (!sec) { + if (!sec) return kr_error(EINVAL); - } for (unsigned i = 0; i < sec->count; ++i) { const knot_rrset_t *ns = knot_pkt_rr(sec, i); - if (ns->type == KNOT_RRTYPE_DS) { + if (ns->type == KNOT_RRTYPE_DS) return kr_error(EEXIST); - } - if (ns->type != KNOT_RRTYPE_NS) { + if (ns->type != KNOT_RRTYPE_NS) continue; - } int flags = 0; bool nsec3_found = false; for (unsigned j = 0; j < sec->count; ++j) { const knot_rrset_t *nsec3 = knot_pkt_rr(sec, j); - if (nsec3->type == KNOT_RRTYPE_DS) { + if (nsec3->type == KNOT_RRTYPE_DS) return kr_error(EEXIST); - } - if (nsec3->type != KNOT_RRTYPE_NSEC3) { + if (nsec3->type != KNOT_RRTYPE_NSEC3) continue; - } nsec3_found = true; /* nsec3 found, check if owner name matches the delegation name. * Just skip in case of *any* errors. */ - if (matches_name(nsec3, ns->owner) != kr_ok()) { + if (matches_name(nsec3, ns->owner) != kr_ok()) continue; - } const uint8_t *bm = knot_nsec3_bitmap(nsec3->rrs.rdata); uint16_t bm_size = knot_nsec3_bitmap_len(nsec3->rrs.rdata); - if (!bm) { + if (!bm) return kr_error(EINVAL); - } if (dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_NS) && !dnssec_nsec_bitmap_contains(bm, bm_size, @@ -717,9 +678,8 @@ int kr_nsec3_ref_to_unsigned(const knot_pkt_t *pkt) return kr_ok(); } } - if (!nsec3_found) { + if (!nsec3_found) return kr_error(DNSSEC_NOT_FOUND); - } if (flags & FLG_NAME_MATCHED) { /* nsec3 which owner matches * the delegation name was found, @@ -735,9 +695,8 @@ int kr_nsec3_ref_to_unsigned(const knot_pkt_t *pkt) const knot_rrset_t *covering_next_nsec3 = NULL; int ret = closest_encloser_proof(pkt, KNOT_AUTHORITY, ns->owner, &encloser_name, NULL, &covering_next_nsec3); - if (ret != 0) { + if (ret != 0) return kr_error(EINVAL); - } if (has_optout(covering_next_nsec3)) { return kr_error(KNOT_ERANGE); @@ -754,19 +713,15 @@ int kr_nsec3_matches_name_and_type(const knot_rrset_t *nsec3, /* It's not secure enough to just check a single bit for (some) other types, * but we don't (currently) only use this API for NS. See RFC 6840 sec. 4. */ - if (type != KNOT_RRTYPE_NS) { - assert(!EINVAL); + if (!kr_assume(type == KNOT_RRTYPE_NS)) return kr_error(EINVAL); - } int ret = matches_name(nsec3, name); - if (ret) { + if (ret) return kr_error(ret); - } const uint8_t *bm = knot_nsec3_bitmap(nsec3->rrs.rdata); uint16_t bm_size = knot_nsec3_bitmap_len(nsec3->rrs.rdata); - if (!bm) { + if (!bm) return kr_error(EINVAL); - } if (dnssec_nsec_bitmap_contains(bm, bm_size, type)) { return kr_ok(); } else { |