1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

resolved: always return the validated answers when validating

We normally expect sd-resolved only to return the validated subset of a
validated response. In some cases we give up on validating, because we
have enough information already to conclude the answer is bogus.

Let's be sure to always reply with only the validated subset in these
cases too, so that we don't return bogus answers and confuse primitive
clients that won't see the SERVFAIL rcode.
This commit is contained in:
Ronan Pigott 2024-03-26 00:33:19 -07:00 committed by Yu Watanabe
parent 4001710365
commit 0dfea62ee3

View File

@ -898,7 +898,9 @@ static int dns_transaction_dnssec_ready(DnsTransaction *t) {
/* All good. */ /* All good. */
break; break;
case DNS_TRANSACTION_DNSSEC_FAILED: case DNS_TRANSACTION_DNSSEC_FAILED: {
DnsAnswer *empty;
/* We handle DNSSEC failures different from other errors, as we care about the DNSSEC /* We handle DNSSEC failures different from other errors, as we care about the DNSSEC
* validation result */ * validation result */
@ -917,8 +919,16 @@ static int dns_transaction_dnssec_ready(DnsTransaction *t) {
if (r < 0) if (r < 0)
log_oom_debug(); log_oom_debug();
/* The answer would normally be replaced by the validated subset, but at this point
* we aren't going to bother validating the rest, so just drop it. */
empty = dns_answer_new(0);
if (!empty)
return -ENOMEM;
DNS_ANSWER_REPLACE(t->answer, empty);
dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED); dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
return 0; return 0;
}
default: default:
log_debug("Auxiliary DNSSEC RR query failed with %s", dns_transaction_state_to_string(dt->state)); log_debug("Auxiliary DNSSEC RR query failed with %s", dns_transaction_state_to_string(dt->state));
@ -3592,14 +3602,17 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) {
bool have_nsec = false; bool have_nsec = false;
r = dnssec_validate_records(t, phase, &have_nsec, &nvalidations, &validated); r = dnssec_validate_records(t, phase, &have_nsec, &nvalidations, &validated);
if (r <= 0) if (r <= 0) {
DNS_ANSWER_REPLACE(t->answer, TAKE_PTR(validated));
return r; return r;
}
if (nvalidations > DNSSEC_VALIDATION_MAX) { if (nvalidations > DNSSEC_VALIDATION_MAX) {
/* This reply requires an onerous number of signature validations to verify. Let's /* This reply requires an onerous number of signature validations to verify. Let's
* not waste our time trying, as this shouldn't happen for well-behaved domains * not waste our time trying, as this shouldn't happen for well-behaved domains
* anyway. */ * anyway. */
t->answer_dnssec_result = DNSSEC_TOO_MANY_VALIDATIONS; t->answer_dnssec_result = DNSSEC_TOO_MANY_VALIDATIONS;
DNS_ANSWER_REPLACE(t->answer, TAKE_PTR(validated));
return 0; return 0;
} }