mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
[9.20] new: usr: adds support for EDE code 1 and 2
Add support for EDE codes 1 & 2 which might occurs during DNSSEC validation in case of unsupported RRSIG algorithm or DNSKEY digest. See #2715 Backport of MR !9948 Merge branch 'backport-2715-ede-unsupported-digest-alg-9.20' into 'bind-9.20' See merge request isc-projects/bind9!9996
This commit is contained in:
commit
b3eab79bc1
18 changed files with 314 additions and 16 deletions
|
|
@ -106,6 +106,12 @@ ns.dnskey-unknown A 10.53.0.3
|
|||
dnskey-unsupported NS ns.dnskey-unsupported
|
||||
ns.dnskey-unsupported A 10.53.0.3
|
||||
|
||||
ds-unsupported NS ns.ds-unsupported
|
||||
ns.ds-unsupported A 10.53.0.3
|
||||
|
||||
digest-alg-unsupported NS ns.digest-alg-unsupported
|
||||
ns.digest-alg-unsupported A 10.53.0.3
|
||||
|
||||
dnskey-nsec3-unknown NS ns.dnskey-nsec3-unknown
|
||||
ns.dnskey-nsec3-unknown A 10.53.0.3
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ infile=example.db.in
|
|||
zonefile=example.db
|
||||
|
||||
# Get the DS records for the "example." zone.
|
||||
for subdomain in secure badds bogus dynamic keyless nsec3 optout \
|
||||
for subdomain in digest-alg-unsupported ds-unsupported secure badds \
|
||||
bogus dynamic keyless nsec3 optout \
|
||||
nsec3-unknown optout-unknown multiple rsasha256 rsasha512 \
|
||||
kskonly update-nsec3 auto-nsec auto-nsec3 secure.below-cname \
|
||||
ttlpatch split-dnssec split-smart expired expiring upper lower \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; SPDX-License-Identifier: MPL-2.0
|
||||
;
|
||||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
;
|
||||
; See the COPYRIGHT file distributed with this work for additional
|
||||
; information regarding copyright ownership.
|
||||
|
||||
$TTL 300 ; 5 minutes
|
||||
@ IN SOA mname1. . (
|
||||
2000042407 ; serial
|
||||
20 ; refresh (20 seconds)
|
||||
20 ; retry (20 seconds)
|
||||
1814400 ; expire (3 weeks)
|
||||
3600 ; minimum (1 hour)
|
||||
)
|
||||
NS ns
|
||||
ns A 10.53.0.3
|
||||
a A 10.0.0.1
|
||||
22
bin/tests/system/dnssec/ns3/ds-unsupported.example.db.in
Normal file
22
bin/tests/system/dnssec/ns3/ds-unsupported.example.db.in
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; SPDX-License-Identifier: MPL-2.0
|
||||
;
|
||||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
;
|
||||
; See the COPYRIGHT file distributed with this work for additional
|
||||
; information regarding copyright ownership.
|
||||
|
||||
$TTL 300 ; 5 minutes
|
||||
@ IN SOA mname1. . (
|
||||
2000042407 ; serial
|
||||
20 ; refresh (20 seconds)
|
||||
20 ; retry (20 seconds)
|
||||
1814400 ; expire (3 weeks)
|
||||
3600 ; minimum (1 hour)
|
||||
)
|
||||
NS ns
|
||||
ns A 10.53.0.3
|
||||
a A 10.0.0.1
|
||||
|
|
@ -195,6 +195,18 @@ zone "dnskey-unknown.example" {
|
|||
file "dnskey-unknown.example.db.signed";
|
||||
};
|
||||
|
||||
zone "digest-alg-unsupported.example" {
|
||||
type primary;
|
||||
file "digest-alg-unsupported.example.db.signed";
|
||||
allow-update { any; };
|
||||
};
|
||||
|
||||
zone "ds-unsupported.example" {
|
||||
type primary;
|
||||
file "ds-unsupported.example.db.signed";
|
||||
allow-update { any; };
|
||||
};
|
||||
|
||||
zone "dnskey-unsupported.example" {
|
||||
type primary;
|
||||
file "dnskey-unsupported.example.db.signed";
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ g A 10.0.0.7
|
|||
z A 10.0.0.26
|
||||
a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
|
||||
x CNAME a
|
||||
badalg A 10.53.0.4
|
||||
|
||||
private NS ns.private
|
||||
ns.private A 10.53.0.2
|
||||
|
|
|
|||
|
|
@ -298,6 +298,48 @@ awk '$4 == "DNSKEY" { $7 = 255 } $4 == "RRSIG" { $6 = 255 } { print }' ${zonefil
|
|||
DSFILE="dsset-${zone}."
|
||||
$DSFROMKEY -A -f ${zonefile}.signed "$zone" >"$DSFILE"
|
||||
|
||||
#
|
||||
# A zone which uses an unsupported algorithm for a DNSKEY and an unsupported
|
||||
# digest for another DNSKEY
|
||||
#
|
||||
zone=digest-alg-unsupported.example.
|
||||
infile=digest-alg-unsupported.example.db.in
|
||||
zonefile=digest-alg-unsupported.example.db
|
||||
|
||||
cnameandkey=$("$KEYGEN" -T KEY -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n host "cnameandkey.$zone")
|
||||
dnameandkey=$("$KEYGEN" -T KEY -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n host "dnameandkey.$zone")
|
||||
keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
|
||||
keyname2=$("$KEYGEN" -q -a ED448 -b "$DEFAULT_BITS" -n zone "$zone")
|
||||
|
||||
cat "$infile" "$cnameandkey.key" "$dnameandkey.key" "$keyname.key" "$keyname2.key" >"$zonefile"
|
||||
|
||||
"$SIGNER" -z -D -o "$zone" "$zonefile" >/dev/null
|
||||
cat "$zonefile" "$zonefile".signed >"$zonefile".tmp
|
||||
mv "$zonefile".tmp "$zonefile".signed
|
||||
|
||||
# override generated DS record file so we can set different digest to each keys
|
||||
DSFILE="dsset-${zone}"
|
||||
$DSFROMKEY -1 -A -f ${zonefile}.signed "$zone" | head -n 1 >"$DSFILE"
|
||||
$DSFROMKEY -2 -A -f ${zonefile}.signed "$zone" | tail -1 >>"$DSFILE"
|
||||
|
||||
#
|
||||
# A zone which is fine by itself (supported algorithm) but that is used
|
||||
# to mimic unsupported DS digest (see ns8).
|
||||
#
|
||||
zone=ds-unsupported.example.
|
||||
infile=ds-unsupported.example.db.in
|
||||
zonefile=ds-unsupported.example.db
|
||||
|
||||
cnameandkey=$("$KEYGEN" -T KEY -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n host "cnameandkey.$zone")
|
||||
dnameandkey=$("$KEYGEN" -T KEY -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n host "dnameandkey.$zone")
|
||||
keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
|
||||
|
||||
cat "$infile" "$cnameandkey.key" "$dnameandkey.key" "$keyname.key" >"$zonefile"
|
||||
|
||||
"$SIGNER" -z -D -o "$zone" "$zonefile" >/dev/null
|
||||
cat "$zonefile" "$zonefile".signed >"$zonefile".tmp
|
||||
mv "$zonefile".tmp "$zonefile".signed
|
||||
|
||||
#
|
||||
# A zone with a published unsupported DNSKEY algorithm (Reserved).
|
||||
# Different from above because this key is not intended for signing.
|
||||
|
|
|
|||
|
|
@ -28,9 +28,13 @@ options {
|
|||
|
||||
nta-lifetime 12s;
|
||||
nta-recheck 9s;
|
||||
|
||||
validate-except { corp; };
|
||||
|
||||
disable-algorithms "digest-alg-unsupported.example." { ED448; };
|
||||
disable-ds-digests "digest-alg-unsupported.example." { "SHA1"; "SHA-1"; };
|
||||
disable-ds-digests "ds-unsupported.example." {"SHA1"; "SHA-1"; "SHA256"; "SHA-256"; "SHA384"; "SHA-384"; };
|
||||
disable-algorithms "badalg.secure.example." { ECDSAP256SHA256; };
|
||||
|
||||
# Note: We only reference the bind.keys file here to confirm that it
|
||||
# is *not* being used. It contains the real root key, and we're
|
||||
# using a local toy root zone for the tests, so it wouldn't work.
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ options {
|
|||
dnssec-validation auto;
|
||||
bindkeys-file "managed.conf";
|
||||
minimal-responses no;
|
||||
disable-algorithms "digest-alg-unsupported.example." { ED448; };
|
||||
disable-ds-digests "digest-alg-unsupported.example." { "SHA1"; "SHA-1"; };
|
||||
disable-ds-digests "ds-unsupported.example." {"SHA1"; "SHA-1"; "SHA256"; "SHA-256"; "SHA384"; "SHA-384"; };
|
||||
disable-algorithms "badalg.secure.example." { ECDSAP256SHA256; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ options {
|
|||
bindkeys-file "managed.conf";
|
||||
dnssec-accept-expired yes;
|
||||
minimal-responses no;
|
||||
disable-algorithms "digest-alg-unsupported.example." { ED448; };
|
||||
disable-ds-digests "digest-alg-unsupported.example." { "SHA1"; "SHA-1"; };
|
||||
disable-ds-digests "ds-unsupported.example." {"SHA1"; "SHA-1"; "SHA256"; "SHA-256"; "SHA384"; "SHA-384"; };
|
||||
disable-algorithms "badalg.secure.example." { ECDSAP256SHA256; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@ options {
|
|||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.4; };
|
||||
listen-on-v6 { none; };
|
||||
disable-algorithms "digest-alg-unsupported.example." { ED448; };
|
||||
disable-ds-digests "digest-alg-unsupported.example." { "SHA1"; "SHA-1"; };
|
||||
disable-ds-digests "ds-unsupported.example." {"SHA1"; "SHA-1"; "SHA256"; "SHA-256"; "SHA384"; "SHA-384"; };
|
||||
disable-algorithms "badalg.secure.example." { ECDSAP256SHA256; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
|
|
|
|||
|
|
@ -3677,6 +3677,35 @@ dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unsupported.exa
|
|||
dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-unsupported.example A >dig.out.ns4.test$n
|
||||
grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
|
||||
grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1
|
||||
grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (255 dnskey-unsupported.example/SOA)" dig.out.ns4.test$n >/dev/null || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "checking EDE code 2 for unsupported DS digest ($n)"
|
||||
ret=0
|
||||
dig_with_opts @10.53.0.4 a.ds-unsupported.example >dig.out.ns4.test$n || ret=1
|
||||
grep "; EDE: 2 (Unsupported DS Digest Type): (SHA-256 ds-unsupported.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "checking EDE code 1 for bad alg mnemonic ($n)"
|
||||
ret=0
|
||||
dig_with_opts @10.53.0.4 badalg.secure.example >dig.out.ns4.test$n || ret=1
|
||||
grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (ECDSAP256SHA256 badalg.secure.example/A)" dig.out.ns4.test$n >/dev/null || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "checking both EDE code 1 and 2 for unsupported digest on one DNSKEY and alg on the other ($n)"
|
||||
ret=0
|
||||
dig_with_opts @10.53.0.4 a.digest-alg-unsupported.example >dig.out.ns4.test$n || ret=1
|
||||
grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (ED448 digest-alg-unsupported.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1
|
||||
grep "; EDE: 2 (Unsupported DS Digest Type): (SHA-1 digest-alg-unsupported.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
|
|
@ -3974,6 +4003,7 @@ dig_with_opts @10.53.0.8 a.secure.trusted A >dig.out.ns8.test$n
|
|||
grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
|
||||
grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null || ret=1
|
||||
grep "; EDE: " dig.out.ns8.test$n >/dev/null && ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
|
@ -3985,6 +4015,7 @@ dig_with_opts @10.53.0.8 a.secure.managed A >dig.out.ns8.test$n
|
|||
grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
|
||||
grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null || ret=1
|
||||
grep "; EDE: " dig.out.ns8.test$n >/dev/null && ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
|
@ -3999,6 +4030,7 @@ dig_with_opts @10.53.0.3 a.unsupported.trusted A >dig.out.ns3.test$n
|
|||
dig_with_opts @10.53.0.8 a.unsupported.trusted A >dig.out.ns8.test$n
|
||||
grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
|
||||
grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1
|
||||
grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (255 ns3.unsupported.trusted (cached))" dig.out.ns8.test$n >/dev/null || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
|
|
@ -4010,6 +4042,7 @@ dig_with_opts @10.53.0.3 a.unsupported.managed A >dig.out.ns3.test$n
|
|||
dig_with_opts @10.53.0.8 a.unsupported.managed A >dig.out.ns8.test$n
|
||||
grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
|
||||
grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1
|
||||
grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (255 ns3.unsupported.managed (cached))" dig.out.ns8.test$n >/dev/null || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ pytestmark = pytest.mark.extra_artifacts(
|
|||
"ns3/dnskey-unsupported.example.db",
|
||||
"ns3/dnskey-unsupported.example.db.tmp",
|
||||
"ns3/dynamic.example.db",
|
||||
"ns3/digest-alg-unsupported.example.db",
|
||||
"ns3/enabled.managed.db",
|
||||
"ns3/enabled.trusted.db",
|
||||
"ns3/example.bk",
|
||||
|
|
@ -131,6 +132,7 @@ pytestmark = pytest.mark.extra_artifacts(
|
|||
"ns3/update-nsec3.example.db.signed",
|
||||
"ns3/upper.example.db",
|
||||
"ns3/upper.example.db.lower",
|
||||
"ns3/ds-unsupported.example.db",
|
||||
"ns4/managed.conf",
|
||||
"ns4/managed-keys.bind",
|
||||
"ns4/named.secroots",
|
||||
|
|
|
|||
|
|
@ -265,6 +265,8 @@ ISC_REFCOUNT_TRACE_DECL(dns_resolver);
|
|||
ISC_REFCOUNT_DECL(dns_resolver);
|
||||
#endif
|
||||
|
||||
typedef struct fetchctx fetchctx_t;
|
||||
|
||||
isc_result_t
|
||||
dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
|
||||
dns_rdatatype_t type, const dns_name_t *domain,
|
||||
|
|
@ -646,4 +648,32 @@ dns_resolver_freefresp(dns_fetchresponse_t **frespp);
|
|||
* \li 'frespp' is valid. No-op if *frespp == NULL
|
||||
*/
|
||||
|
||||
void
|
||||
dns_resolver_edeappend(fetchctx_t *fctx, uint16_t info_code, const char *what,
|
||||
const dns_name_t *name, dns_rdatatype_t type);
|
||||
/*%<
|
||||
* Helper for EDE message creation in resolver context. Creates message
|
||||
* containing the "what" context message as well as the "name"/"type" being
|
||||
* resolved
|
||||
*
|
||||
* Requires:
|
||||
* \li "fctx" is valid
|
||||
* \li "what" is valid
|
||||
* \li "info_code" is within the range of defined EDE codes
|
||||
* \li "name" is valid
|
||||
*/
|
||||
|
||||
void
|
||||
dns_resolver_copyede(dns_fetch_t *from, fetchctx_t *to);
|
||||
/*%<
|
||||
* Copy all EDE messages from the fetchctx_t "from->private" to the fetchctx_t
|
||||
* "to". The fetchctx_t from "from" is not locked. This is reponsability of the
|
||||
* caller to lock it if this function is called in a context needing "from"
|
||||
* synchronization.
|
||||
*
|
||||
* Requires:
|
||||
* \li "from" is valid
|
||||
* \li "to" is valid
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
|
|
|||
|
|
@ -148,13 +148,20 @@ struct dns_validator {
|
|||
isc_stdtime_t start;
|
||||
|
||||
bool digest_sha1;
|
||||
bool supported_algorithm;
|
||||
uint8_t unsupported_algorithm;
|
||||
uint8_t unsupported_digest;
|
||||
dns_rdata_t rdata;
|
||||
bool resume;
|
||||
uint32_t *nvalidations;
|
||||
uint32_t *nfails;
|
||||
isc_counter_t *qc;
|
||||
isc_counter_t *gqc;
|
||||
|
||||
/*
|
||||
* opaque type here, used to send EDE errors during DNSSEC valiration
|
||||
* to the fetch context.
|
||||
*/
|
||||
fetchctx_t *fctx;
|
||||
};
|
||||
|
||||
/*%
|
||||
|
|
@ -173,7 +180,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
|
|||
dns_message_t *message, unsigned int options,
|
||||
isc_loop_t *loop, isc_job_cb cb, void *arg,
|
||||
uint32_t *nvalidations, uint32_t *nfails,
|
||||
isc_counter_t *qc, isc_counter_t *gqc,
|
||||
isc_counter_t *qc, isc_counter_t *gqc, fetchctx_t *fctx,
|
||||
dns_validator_t **validatorp);
|
||||
/*%<
|
||||
* Start a DNSSEC validation.
|
||||
|
|
|
|||
|
|
@ -988,7 +988,7 @@ valcreate(fetchctx_t *fctx, dns_message_t *message, dns_adbaddrinfo_t *addrinfo,
|
|||
result = dns_validator_create(
|
||||
fctx->res->view, name, type, rdataset, sigrdataset, message,
|
||||
valoptions, fctx->loop, validated, valarg, &fctx->nvalidations,
|
||||
&fctx->nfails, fctx->qc, fctx->gqc, &validator);
|
||||
&fctx->nfails, fctx->qc, fctx->gqc, fctx, &validator);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
inc_stats(fctx->res, dns_resstatscounter_val);
|
||||
if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
|
||||
|
|
@ -1337,8 +1337,6 @@ fctx_cleanup(fetchctx_t *fctx) {
|
|||
ISC_LIST_UNLINK(fctx->altaddrs, addr, publink);
|
||||
dns_adb_freeaddrinfo(fctx->adb, &addr);
|
||||
}
|
||||
|
||||
dns_ede_unlinkall(fctx->mctx, &fctx->edelist);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1603,7 +1601,7 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
|
|||
|
||||
/*
|
||||
* Copy EDE that occured during the resolution to all
|
||||
* clients
|
||||
* clients.
|
||||
*/
|
||||
for (dns_ede_t *ede = ISC_LIST_HEAD(fctx->edelist); ede != NULL;
|
||||
ede = ISC_LIST_NEXT(ede, link))
|
||||
|
|
@ -4201,6 +4199,7 @@ resume_qmin(void *arg) {
|
|||
}
|
||||
UNLOCK(&fctx->lock);
|
||||
|
||||
dns_resolver_copyede(fctx->qminfetch, fctx);
|
||||
dns_resolver_destroyfetch(&fctx->qminfetch);
|
||||
|
||||
/*
|
||||
|
|
@ -4339,7 +4338,6 @@ fctx_destroy(fetchctx_t *fctx) {
|
|||
REQUIRE(ISC_LIST_EMPTY(fctx->queries));
|
||||
REQUIRE(ISC_LIST_EMPTY(fctx->finds));
|
||||
REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
|
||||
REQUIRE(ISC_LIST_EMPTY(fctx->edelist));
|
||||
REQUIRE(atomic_load_acquire(&fctx->pending) == 0);
|
||||
REQUIRE(ISC_LIST_EMPTY(fctx->validators));
|
||||
REQUIRE(fctx->state != fetchstate_active);
|
||||
|
|
@ -4375,6 +4373,8 @@ fctx_destroy(fetchctx_t *fctx) {
|
|||
isc_mem_put(fctx->mctx, sa, sizeof(*sa));
|
||||
}
|
||||
|
||||
dns_ede_unlinkall(fctx->mctx, &fctx->edelist);
|
||||
|
||||
isc_counter_detach(&fctx->qc);
|
||||
if (fctx->gqc != NULL) {
|
||||
isc_counter_detach(&fctx->gqc);
|
||||
|
|
@ -7208,6 +7208,7 @@ resume_dslookup(void *arg) {
|
|||
}
|
||||
|
||||
cleanup:
|
||||
dns_resolver_copyede(fetch, fctx);
|
||||
dns_resolver_destroyfetch(&fetch);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -11114,3 +11115,44 @@ dns_resolver_freefresp(dns_fetchresponse_t **frespp) {
|
|||
dns_ede_unlinkall(fresp->mctx, &fresp->edelist);
|
||||
isc_mem_putanddetach(&fresp->mctx, fresp, sizeof(*fresp));
|
||||
}
|
||||
|
||||
void
|
||||
dns_resolver_edeappend(fetchctx_t *fctx, uint16_t info_code, const char *what,
|
||||
const dns_name_t *name, dns_rdatatype_t type) {
|
||||
REQUIRE(VALID_FCTX(fctx));
|
||||
REQUIRE(what);
|
||||
REQUIRE(name);
|
||||
|
||||
char extra[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE +
|
||||
DNS_EDE_EXTRATEXT_LEN];
|
||||
size_t offset = 0;
|
||||
|
||||
/*
|
||||
* -2 to leave room for separator "/" and NULL terminator
|
||||
*/
|
||||
snprintf(extra, DNS_EDE_EXTRATEXT_LEN - 2, "%s ", what);
|
||||
offset += strlen(extra);
|
||||
dns_name_format(name, extra + offset, DNS_NAME_FORMATSIZE);
|
||||
offset = strlcat(extra, "/", sizeof(extra));
|
||||
dns_rdatatype_format(type, extra + offset,
|
||||
DNS_RDATATYPE_FORMATSIZE + 1);
|
||||
|
||||
LOCK(&fctx->lock);
|
||||
dns_ede_append(fctx->mctx, &fctx->edelist, info_code, extra);
|
||||
UNLOCK(&fctx->lock)
|
||||
}
|
||||
|
||||
void
|
||||
dns_resolver_copyede(dns_fetch_t *from, fetchctx_t *to) {
|
||||
REQUIRE(DNS_FETCH_VALID(from));
|
||||
REQUIRE(VALID_FCTX(to));
|
||||
|
||||
LOCK(&to->lock);
|
||||
for (dns_ede_t *ede = ISC_LIST_HEAD(from->private->edelist);
|
||||
ede != NULL; ede = ISC_LIST_NEXT(ede, link))
|
||||
{
|
||||
dns_ede_append(to->mctx, &to->edelist, ede->info_code,
|
||||
ede->extra_text);
|
||||
}
|
||||
UNLOCK(&to->lock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,6 +173,9 @@ expire_rdatasets(dns_validator_t *val) {
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
validate_extendederror(dns_validator_t *val);
|
||||
|
||||
/*%
|
||||
* Ensure the validator's rdatasets are disassociated.
|
||||
*/
|
||||
|
|
@ -410,6 +413,7 @@ fetch_callback_dnskey(void *arg) {
|
|||
}
|
||||
|
||||
validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_dnskey");
|
||||
dns_resolver_copyede(val->fetch, val->fctx);
|
||||
dns_resolver_destroyfetch(&val->fetch);
|
||||
|
||||
if (CANCELED(val) || CANCELING(val)) {
|
||||
|
|
@ -484,6 +488,7 @@ fetch_callback_ds(void *arg) {
|
|||
}
|
||||
|
||||
validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_ds");
|
||||
dns_resolver_copyede(val->fetch, val->fctx);
|
||||
dns_resolver_destroyfetch(&val->fetch);
|
||||
|
||||
if (CANCELED(val) || CANCELING(val)) {
|
||||
|
|
@ -976,7 +981,7 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
|
|||
result = dns_validator_create(val->view, name, type, rdataset, sig,
|
||||
NULL, vopts, val->loop, cb, val,
|
||||
val->nvalidations, val->nfails, val->qc,
|
||||
val->gqc, &val->subvalidator);
|
||||
val->gqc, val->fctx, &val->subvalidator);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
dns_validator_attach(val, &val->subvalidator->parent);
|
||||
val->subvalidator->depth = val->depth + 1;
|
||||
|
|
@ -1536,6 +1541,8 @@ cleanup:
|
|||
return;
|
||||
}
|
||||
|
||||
val->unsupported_algorithm = 0;
|
||||
val->unsupported_digest = 0;
|
||||
result = validate_async_run(val, validate_answer_process);
|
||||
INSIST(result == DNS_R_WAIT);
|
||||
}
|
||||
|
|
@ -1656,6 +1663,9 @@ validate_answer_process(void *arg) {
|
|||
if (!dns_resolver_algorithm_supported(val->view->resolver, val->name,
|
||||
val->siginfo->algorithm))
|
||||
{
|
||||
if (val->unsupported_algorithm == 0) {
|
||||
val->unsupported_algorithm = val->siginfo->algorithm;
|
||||
}
|
||||
goto next_key;
|
||||
}
|
||||
|
||||
|
|
@ -1779,6 +1789,10 @@ validate_answer_iter_done(dns_validator_t *val, isc_result_t result) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (result != ISC_R_SUCCESS && result != DNS_R_WAIT) {
|
||||
validate_extendederror(val);
|
||||
}
|
||||
|
||||
validator_log(val, ISC_LOG_INFO, "no valid signature found");
|
||||
validate_async_done(val, val->result);
|
||||
}
|
||||
|
|
@ -1979,12 +1993,15 @@ validate_dnskey_dsset_done(dns_validator_t *val, isc_result_t result) {
|
|||
validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)");
|
||||
break;
|
||||
case ISC_R_NOMORE:
|
||||
if (!val->supported_algorithm) {
|
||||
if (val->unsupported_algorithm != 0 ||
|
||||
val->unsupported_digest != 0)
|
||||
{
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"no supported algorithm/digest (DS)");
|
||||
result = markanswer(
|
||||
val, "validate_dnskey (3)",
|
||||
"no supported algorithm/digest (DS)");
|
||||
validate_extendederror(val);
|
||||
break;
|
||||
}
|
||||
FALLTHROUGH;
|
||||
|
|
@ -2021,17 +2038,21 @@ validate_dnskey_dsset(dns_validator_t *val) {
|
|||
if (!dns_resolver_ds_digest_supported(val->view->resolver, val->name,
|
||||
ds.digest_type))
|
||||
{
|
||||
if (val->unsupported_digest == 0) {
|
||||
val->unsupported_digest = ds.digest_type;
|
||||
}
|
||||
return DNS_R_BADALG;
|
||||
}
|
||||
|
||||
if (!dns_resolver_algorithm_supported(val->view->resolver, val->name,
|
||||
ds.algorithm))
|
||||
{
|
||||
if (val->unsupported_algorithm == 0) {
|
||||
val->unsupported_algorithm = ds.algorithm;
|
||||
}
|
||||
return DNS_R_BADALG;
|
||||
}
|
||||
|
||||
val->supported_algorithm = true;
|
||||
|
||||
/*
|
||||
* Find the DNSKEY matching the DS...
|
||||
*/
|
||||
|
|
@ -2203,8 +2224,8 @@ validate_dnskey(void *arg) {
|
|||
* key set and the matching signature. For each such key, attempt
|
||||
* verification.
|
||||
*/
|
||||
|
||||
val->supported_algorithm = false;
|
||||
val->unsupported_algorithm = 0;
|
||||
val->unsupported_digest = 0;
|
||||
|
||||
/*
|
||||
* If DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present we
|
||||
|
|
@ -2942,6 +2963,13 @@ check_ds_algs(dns_validator_t *val, dns_name_t *name,
|
|||
}
|
||||
dns_rdata_reset(&dsrdata);
|
||||
}
|
||||
|
||||
/*
|
||||
* No unsupported alg/digest EDE error is raised here because the prove
|
||||
* unsecure flow always runs after a validate/validatenx flow. So if an
|
||||
* unsupported alg/digest was found while building the chain of trust,
|
||||
* it would be raised already.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -3392,7 +3420,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
|
|||
dns_message_t *message, unsigned int options,
|
||||
isc_loop_t *loop, isc_job_cb cb, void *arg,
|
||||
uint32_t *nvalidations, uint32_t *nfails,
|
||||
isc_counter_t *qc, isc_counter_t *gqc,
|
||||
isc_counter_t *qc, isc_counter_t *gqc, fetchctx_t *fctx,
|
||||
dns_validator_t **validatorp) {
|
||||
isc_result_t result = ISC_R_FAILURE;
|
||||
dns_validator_t *val = NULL;
|
||||
|
|
@ -3425,6 +3453,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
|
|||
.rdata = DNS_RDATA_INIT,
|
||||
.nvalidations = nvalidations,
|
||||
.nfails = nfails,
|
||||
.fctx = fctx,
|
||||
};
|
||||
|
||||
isc_refcount_init(&val->references, 1);
|
||||
|
|
@ -3532,8 +3561,10 @@ destroy_validator(dns_validator_t *val) {
|
|||
if (val->gqc != NULL) {
|
||||
isc_counter_detach(&val->gqc);
|
||||
}
|
||||
|
||||
dns_view_detach(&val->view);
|
||||
isc_loop_detach(&val->loop);
|
||||
|
||||
isc_mem_put(mctx, val, sizeof(*val));
|
||||
}
|
||||
|
||||
|
|
@ -3632,6 +3663,25 @@ validator_logcreate(dns_validator_t *val, dns_name_t *name,
|
|||
caller, operation, namestr, typestr);
|
||||
}
|
||||
|
||||
static void
|
||||
validate_extendederror(dns_validator_t *val) {
|
||||
char txt[32];
|
||||
|
||||
REQUIRE(VALID_VALIDATOR(val));
|
||||
|
||||
if (val->unsupported_algorithm != 0) {
|
||||
dns_secalg_format(val->unsupported_algorithm, txt, sizeof(txt));
|
||||
dns_resolver_edeappend(val->fctx, DNS_EDE_DNSKEYALG, txt,
|
||||
val->name, val->type);
|
||||
}
|
||||
|
||||
if (val->unsupported_digest != 0) {
|
||||
dns_dsdigest_format(val->unsupported_digest, txt, sizeof(txt));
|
||||
dns_resolver_edeappend(val->fctx, DNS_EDE_DSDIGESTTYPE, txt,
|
||||
val->name, val->type);
|
||||
}
|
||||
}
|
||||
|
||||
#if DNS_VALIDATOR_TRACE
|
||||
ISC_REFCOUNT_TRACE_IMPL(dns_validator, destroy_validator);
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -2499,6 +2499,18 @@ validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
|
|||
if (!dns_resolver_algorithm_supported(client->view->resolver,
|
||||
name, rrsig.algorithm))
|
||||
{
|
||||
char txt[DNS_NAME_FORMATSIZE + 32];
|
||||
isc_buffer_t buffer;
|
||||
|
||||
isc_buffer_init(&buffer, txt, sizeof(txt));
|
||||
dns_secalg_totext(rrsig.algorithm, &buffer);
|
||||
isc_buffer_putstr(&buffer, " ");
|
||||
dns_name_totext(name, DNS_NAME_OMITFINALDOT, &buffer);
|
||||
isc_buffer_putstr(&buffer, " (cached)");
|
||||
isc_buffer_putuint8(&buffer, 0);
|
||||
|
||||
ns_client_extendederror(client, DNS_EDE_DNSKEYALG,
|
||||
isc_buffer_base(&buffer));
|
||||
continue;
|
||||
}
|
||||
if (!dns_name_issubdomain(name, &rrsig.signer)) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue