]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: always return the validated answers when validating
authorRonan Pigott <ronan@rjp.ie>
Tue, 26 Mar 2024 07:33:19 +0000 (00:33 -0700)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 27 Mar 2024 01:17:15 +0000 (10:17 +0900)
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

index 78f370c7c1d7c794df736827e61d55d0fd549697..392f416c98f63243430f5badc026d9a3fb509a5c 100644 (file)
@@ -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;
                 }