summaryrefslogtreecommitdiffstats
path: root/lib/dnssec
diff options
context:
space:
mode:
authorTomas Krizek <tomas.krizek@nic.cz>2021-03-24 17:44:45 +0100
committerTomas Krizek <tomas.krizek@nic.cz>2021-05-25 14:39:41 +0200
commitf6d1a15cd3bab4b93ff79794fe42d51ec3097575 (patch)
tree12436553f3193ea992a092b7982058a9a744c89d /lib/dnssec
parentlib/dnssec/nsec.h: replace asserts (diff)
downloadknot-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.c4
-rw-r--r--lib/dnssec/nsec3.c207
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(&params, 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, &params, 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(&params);
- }
- 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(&params, nsec3);
- if (ret != 0) {
+ if (ret != 0)
goto fail;
- }
ret = hash_name(&name_hash, &params, 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(&params);
- }
- 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(&params, nsec3);
- if (ret != 0) {
+ if (ret != 0)
goto fail;
- }
ret = hash_name(&name_hash, &params, 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(&params);
- }
- 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 {