From 0dfea62ee3293891e92c33de28f9a6a9557d86eb Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Tue, 26 Mar 2024 00:33:19 -0700 Subject: [PATCH] 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. --- src/resolve/resolved-dns-transaction.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 78f370c7c1d..392f416c98f 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -898,7 +898,9 @@ static int dns_transaction_dnssec_ready(DnsTransaction *t) { /* All good. */ 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 * validation result */ @@ -917,8 +919,16 @@ static int dns_transaction_dnssec_ready(DnsTransaction *t) { if (r < 0) 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); return 0; + } default: 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; 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; + } if (nvalidations > DNSSEC_VALIDATION_MAX) { /* 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 * anyway. */ t->answer_dnssec_result = DNSSEC_TOO_MANY_VALIDATIONS; + DNS_ANSWER_REPLACE(t->answer, TAKE_PTR(validated)); return 0; }