- dns64: fix CNAME problems (#203) It still won't work with policy.STUB.
- hints: better interpretation of hosts-like files (#204)
also, error out if a bad entry is encountered in the file
+- dnssec: handle unknown DNSKEY/DS algorithms (#210)
Improvements
------------
return vctx->result;
}
+/* Fallbacks: implemented in newer libdnssec.
+ * Note: changing some from true to false is NOT enough to fully remove the support. */
+#if KNOT_VERSION_HEX < ((2 << 16) | (6 << 8) | 0)
+ static bool dnssec_algorithm_key_support(dnssec_key_algorithm_t algo)
+ {
+ switch (algo) {
+ case DNSSEC_KEY_ALGORITHM_DSA_SHA1:
+ case DNSSEC_KEY_ALGORITHM_DSA_SHA1_NSEC3:
+ case DNSSEC_KEY_ALGORITHM_RSA_SHA1:
+ case DNSSEC_KEY_ALGORITHM_RSA_SHA1_NSEC3:
+ case DNSSEC_KEY_ALGORITHM_RSA_SHA256:
+ case DNSSEC_KEY_ALGORITHM_RSA_SHA512:
+ case DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256:
+ case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384:
+ return true;
+ //case DNSSEC_KEY_ALGORITHM_ED25519:
+ //case DNSSEC_KEY_ALGORITHM_ED448:
+ default:
+ return false;
+ }
+ }
+
+ static bool dnssec_algorithm_digest_support(dnssec_key_digest_t algo)
+ {
+ switch (algo) {
+ case DNSSEC_KEY_DIGEST_SHA1:
+ case DNSSEC_KEY_DIGEST_SHA256:
+ case DNSSEC_KEY_DIGEST_SHA384:
+ return true;
+ default:
+ return false;
+ };
+ }
+#endif
+
+static bool kr_ds_algo_support(const knot_rrset_t *ta)
+{
+ for (uint16_t i = 0; i < ta->rrs.rr_count; ++i) {
+ if (dnssec_algorithm_digest_support(knot_ds_digest_type(&ta->rrs, i))
+ && dnssec_algorithm_key_support(knot_ds_alg(&ta->rrs, i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
int kr_dnskeys_trusted(kr_rrset_validation_ctx_t *vctx, const knot_rrset_t *ta)
{
const knot_pkt_t *pkt = vctx->pkt;
const knot_rrset_t *keys = vctx->keys;
- if (!pkt || !keys || !ta) {
+ const bool ok = pkt && keys && ta && ta->rrs.rr_count && ta->rrs.data
+ && ta->type == KNOT_RRTYPE_DS;
+ if (!ok) {
+ assert(false);
return kr_error(EINVAL);
}
+ /* Check if at least one DS has a usable algorithm pair. */
+ if (!kr_ds_algo_support(ta)) {
+ /* See RFC6840 5.2. */
+ return vctx->result = kr_error(DNSSEC_INVALID_DS_ALGORITHM);
+ }
+
/* RFC4035 5.2, bullet 1
* The supplied DS record has been authenticated.
* It has been validated or is part of a configured trust anchor.
assert (vctx->result == 0);
return vctx->result;
}
+
/* No useable key found */
vctx->result = kr_error(ENOENT);
return vctx->result;
ret = dnssec_key_set_rdata(new_key, &binary_key);
if (ret != DNSSEC_EOK) {
dnssec_key_free(new_key);
- return kr_error(ENOMEM);
+ return kr_error(ret);
}
if (kown) {
ret = dnssec_key_set_dname(new_key, kown);
size_t key_pos, const struct dseckey *key);
/**
* Check whether the DNSKEY rrset matches the supplied trust anchor RRSet.
- * @param vctx Pointer to validation context.
- * @param ta Trust anchor RRSet against which to validate the DNSKEY RRSet.
- * @return 0 or error code, same as vctx->result.
+ * @param vctx Pointer to validation context.
+ * @param ta Trust anchor RRSet against which to validate the DNSKEY RRSet.
+ * @return 0 or error code, same as vctx->result. In particular,
+ * DNSSEC_INVALID_DS_ALGORITHM if *each* DS records is unusable
+ * due to unimplemented DNSKEY or DS algorithm.
*/
int kr_dnskeys_trusted(kr_rrset_validation_ctx_t *vctx, const knot_rrset_t *ta);
* @param kown DNSKEY owner name.
* @param rdata DNSKEY RDATA
* @param rdlen DNSKEY RDATA length
+ * @return 0 or error code; in particular: DNSSEC_INVALID_KEY_ALGORITHM
*/
int kr_dnssec_key_from_rdata(struct dseckey **key, const knot_dname_t *kown, const uint8_t *rdata, size_t rdlen);
dnssec_binary_t computed_ds = {0, };
int ret = dnssec_key_create_ds(key, digest_type, &computed_ds);
if (ret != DNSSEC_EOK) {
- ret = kr_error(ENOMEM);
goto fail;
}
fail:
dnssec_binary_free(&computed_ds);
- return ret;
+ return kr_error(ret);
}
int kr_authenticate_referral(const knot_rrset_t *ref, const dnssec_key_t *key)
};
ret = authenticate_ds(key, &ds_rdata, knot_ds_digest_type(&ref->rrs, i));
if (ret == 0) { /* Found a good DS */
- break;
+ return kr_ok();
}
rd = kr_rdataset_next(rd);
}
- return ret;
+
+ return kr_error(ret);
}
/**
* Performs referral authentication according to RFC4035 5.2, bullet 2
* @param ref Referral RRSet. Currently only DS can be used.
* @param key Already parsed key.
- * @return 0 or error code.
+ * @return 0 or error code. In particular: DNSSEC_INVALID_DS_ALGORITHM
+ * in case *all* DSs in ref use an unimplemented algorithm.
*/
int kr_authenticate_referral(const knot_rrset_t *ref, const dnssec_key_t *key);
if (ret == kr_error(EAGAIN)) {
VERBOSE_MSG(qry, ">< cut changed, needs revalidation\n");
return KR_STATE_YIELD;
+ } else if (ret == kr_error(DNSSEC_INVALID_DS_ALGORITHM)) {
+ VERBOSE_MSG(qry, ">< all DS entries use unsupported algorithm pairs, going insecure\n");
+ /* ^ the message is a bit imprecise to avoid being too verbose */
+ qry->flags &= ~QUERY_DNSSEC_WANT;
+ qry->flags |= QUERY_DNSSEC_INSECURE;
+ rank_records(ctx, KR_RANK_INSECURE);
+ mark_insecure_parents(qry);
+ return KR_STATE_DONE;
} else if (ret != 0) {
VERBOSE_MSG(qry, "<= bad keys, broken trust chain\n");
qry->flags |= QUERY_DNSSEC_BOGUS;