]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-transaction.c
tree-wide: define iterator inside of the macro
[thirdparty/systemd.git] / src / resolve / resolved-dns-transaction.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
ec2c5e43 2
62cc1c55 3#include "sd-messages.h"
beef6a5f 4
ec2c5e43 5#include "af-list.h"
b5efdb8a 6#include "alloc-util.h"
f52e61da 7#include "dns-domain.h"
7cc6ed7b 8#include "errno-list.h"
c3fecddf 9#include "errno-util.h"
3ffd4af2
LP
10#include "fd-util.h"
11#include "random-util.h"
7778dfff 12#include "resolved-dns-cache.h"
3ffd4af2 13#include "resolved-dns-transaction.h"
6016fcb0 14#include "resolved-dnstls.h"
aedf00a2 15#include "resolved-llmnr.h"
6016fcb0 16#include "string-table.h"
5d67a7ae 17
b214dc0f 18#define TRANSACTIONS_MAX 4096
dc349f5f 19#define TRANSACTION_TCP_TIMEOUT_USEC (10U*USEC_PER_SEC)
b214dc0f 20
dbc4661a
MCO
21/* After how much time to repeat classic DNS requests */
22#define DNS_TIMEOUT_USEC (SD_RESOLVED_QUERY_TIMEOUT_USEC / DNS_TRANSACTION_ATTEMPTS_MAX)
23
c61d2b44
LP
24static void dns_transaction_reset_answer(DnsTransaction *t) {
25 assert(t);
26
27 t->received = dns_packet_unref(t->received);
28 t->answer = dns_answer_unref(t->answer);
29 t->answer_rcode = 0;
30 t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
31 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
32 t->answer_authenticated = false;
d3760be0 33 t->answer_nsec_ttl = (uint32_t) -1;
7cc6ed7b 34 t->answer_errno = 0;
c61d2b44
LP
35}
36
c5b4f861
LP
37static void dns_transaction_flush_dnssec_transactions(DnsTransaction *t) {
38 DnsTransaction *z;
39
40 assert(t);
41
42 while ((z = set_steal_first(t->dnssec_transactions))) {
43 set_remove(z->notify_transactions, t);
35aa04e9 44 set_remove(z->notify_transactions_done, t);
c5b4f861
LP
45 dns_transaction_gc(z);
46 }
47}
48
f32f0e57
LP
49static void dns_transaction_close_connection(DnsTransaction *t) {
50 assert(t);
51
b30bf55d
LP
52 if (t->stream) {
53 /* Let's detach the stream from our transaction, in case something else keeps a reference to it. */
98767d75
IT
54 LIST_REMOVE(transactions_by_stream, t->stream->transactions, t);
55
56 /* Remove packet in case it's still in the queue */
57 dns_packet_unref(ordered_set_remove(t->stream->write_queue, t->sent));
58
b30bf55d
LP
59 t->stream = dns_stream_unref(t->stream);
60 }
61
f32f0e57
LP
62 t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source);
63 t->dns_udp_fd = safe_close(t->dns_udp_fd);
64}
65
f535705a 66static void dns_transaction_stop_timeout(DnsTransaction *t) {
97cc656c
LP
67 assert(t);
68
69 t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
97cc656c
LP
70}
71
ec2c5e43 72DnsTransaction* dns_transaction_free(DnsTransaction *t) {
801ad6a6 73 DnsQueryCandidate *c;
ec2c5e43 74 DnsZoneItem *i;
547973de 75 DnsTransaction *z;
ec2c5e43
LP
76
77 if (!t)
78 return NULL;
79
51e399bc
LP
80 log_debug("Freeing transaction %" PRIu16 ".", t->id);
81
f32f0e57 82 dns_transaction_close_connection(t);
f535705a 83 dns_transaction_stop_timeout(t);
ec2c5e43 84
ec2c5e43 85 dns_packet_unref(t->sent);
c61d2b44 86 dns_transaction_reset_answer(t);
ec2c5e43 87
8300ba21 88 dns_server_unref(t->server);
ec2c5e43
LP
89
90 if (t->scope) {
f9ebb22a
LP
91 hashmap_remove_value(t->scope->transactions_by_key, t->key, t);
92 LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
ec2c5e43
LP
93
94 if (t->id != 0)
95 hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
96 }
97
547973de 98 while ((c = set_steal_first(t->notify_query_candidates)))
801ad6a6 99 set_remove(c->transactions, t);
547973de 100 set_free(t->notify_query_candidates);
801ad6a6 101
35aa04e9
LP
102 while ((c = set_steal_first(t->notify_query_candidates_done)))
103 set_remove(c->transactions, t);
104 set_free(t->notify_query_candidates_done);
105
547973de 106 while ((i = set_steal_first(t->notify_zone_items)))
ec2c5e43 107 i->probe_transaction = NULL;
547973de
LP
108 set_free(t->notify_zone_items);
109
35aa04e9
LP
110 while ((i = set_steal_first(t->notify_zone_items_done)))
111 i->probe_transaction = NULL;
112 set_free(t->notify_zone_items_done);
113
547973de
LP
114 while ((z = set_steal_first(t->notify_transactions)))
115 set_remove(z->dnssec_transactions, t);
116 set_free(t->notify_transactions);
117
35aa04e9
LP
118 while ((z = set_steal_first(t->notify_transactions_done)))
119 set_remove(z->dnssec_transactions, t);
120 set_free(t->notify_transactions_done);
121
c5b4f861 122 dns_transaction_flush_dnssec_transactions(t);
547973de
LP
123 set_free(t->dnssec_transactions);
124
125 dns_answer_unref(t->validated_keys);
97cc656c 126 dns_resource_key_unref(t->key);
97cc656c 127
6b430fdb 128 return mfree(t);
ec2c5e43
LP
129}
130
131DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
132
51e399bc 133bool dns_transaction_gc(DnsTransaction *t) {
ec2c5e43
LP
134 assert(t);
135
136 if (t->block_gc > 0)
51e399bc 137 return true;
ec2c5e43 138
547973de 139 if (set_isempty(t->notify_query_candidates) &&
35aa04e9 140 set_isempty(t->notify_query_candidates_done) &&
547973de 141 set_isempty(t->notify_zone_items) &&
35aa04e9
LP
142 set_isempty(t->notify_zone_items_done) &&
143 set_isempty(t->notify_transactions) &&
144 set_isempty(t->notify_transactions_done)) {
ec2c5e43 145 dns_transaction_free(t);
51e399bc
LP
146 return false;
147 }
148
149 return true;
ec2c5e43
LP
150}
151
4dd15077
LP
152static uint16_t pick_new_id(Manager *m) {
153 uint16_t new_id;
154
155 /* Find a fresh, unused transaction id. Note that this loop is bounded because there's a limit on the number of
156 * transactions, and it's much lower than the space of IDs. */
157
158 assert_cc(TRANSACTIONS_MAX < 0xFFFF);
159
160 do
161 random_bytes(&new_id, sizeof(new_id));
162 while (new_id == 0 ||
163 hashmap_get(m->dns_transactions, UINT_TO_PTR(new_id)));
164
165 return new_id;
166}
167
f52e61da 168int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key) {
ec2c5e43
LP
169 _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL;
170 int r;
171
172 assert(ret);
173 assert(s);
f52e61da 174 assert(key);
ec2c5e43 175
9eae2bf3 176 /* Don't allow looking up invalid or pseudo RRs */
c463eb78 177 if (!dns_type_is_valid_query(key->type))
9eae2bf3 178 return -EINVAL;
d0129ddb
LP
179 if (dns_type_is_obsolete(key->type))
180 return -EOPNOTSUPP;
9eae2bf3
LP
181
182 /* We only support the IN class */
4c701096 183 if (!IN_SET(key->class, DNS_CLASS_IN, DNS_CLASS_ANY))
9eae2bf3
LP
184 return -EOPNOTSUPP;
185
b214dc0f
LP
186 if (hashmap_size(s->manager->dns_transactions) >= TRANSACTIONS_MAX)
187 return -EBUSY;
188
d5099efc 189 r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL);
ec2c5e43
LP
190 if (r < 0)
191 return r;
192
f9ebb22a 193 r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops);
da0c630e
LP
194 if (r < 0)
195 return r;
196
ec2c5e43
LP
197 t = new0(DnsTransaction, 1);
198 if (!t)
199 return -ENOMEM;
200
4667e00a 201 t->dns_udp_fd = -1;
c3bc53e6 202 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
019036a4 203 t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
d3760be0 204 t->answer_nsec_ttl = (uint32_t) -1;
f52e61da 205 t->key = dns_resource_key_ref(key);
274b8748 206 t->current_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID;
d001e0a3 207 t->clamp_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID;
ec2c5e43 208
4dd15077 209 t->id = pick_new_id(s->manager);
ec2c5e43
LP
210
211 r = hashmap_put(s->manager->dns_transactions, UINT_TO_PTR(t->id), t);
212 if (r < 0) {
213 t->id = 0;
214 return r;
215 }
216
f9ebb22a 217 r = hashmap_replace(s->transactions_by_key, t->key, t);
da0c630e
LP
218 if (r < 0) {
219 hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id));
220 return r;
221 }
222
f9ebb22a 223 LIST_PREPEND(transactions_by_scope, s->transactions, t);
ec2c5e43
LP
224 t->scope = s;
225
313cefa1 226 s->manager->n_transactions_total++;
a150ff5e 227
ec2c5e43
LP
228 if (ret)
229 *ret = t;
230
231 t = NULL;
232
233 return 0;
234}
235
4dd15077
LP
236static void dns_transaction_shuffle_id(DnsTransaction *t) {
237 uint16_t new_id;
238 assert(t);
239
240 /* Pick a new ID for this transaction. */
241
242 new_id = pick_new_id(t->scope->manager);
243 assert_se(hashmap_remove_and_put(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id), UINT_TO_PTR(new_id), t) >= 0);
244
245 log_debug("Transaction %" PRIu16 " is now %" PRIu16 ".", t->id, new_id);
246 t->id = new_id;
247
248 /* Make sure we generate a new packet with the new ID */
249 t->sent = dns_packet_unref(t->sent);
250}
251
ec2c5e43 252static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
2fb3034c 253 _cleanup_free_ char *pretty = NULL;
202b76ae 254 char key_str[DNS_RESOURCE_KEY_STRING_MAX];
ec2c5e43 255 DnsZoneItem *z;
ec2c5e43
LP
256
257 assert(t);
258 assert(p);
259
260 if (manager_our_packet(t->scope->manager, p) != 0)
261 return;
262
164d025d 263 (void) in_addr_to_string(p->family, &p->sender, &pretty);
2fb3034c 264
a5784c49
LP
265 log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s got tentative packet from %s.",
266 t->id,
202b76ae 267 dns_resource_key_to_string(t->key, key_str, sizeof key_str),
ec2c5e43 268 dns_protocol_to_string(t->scope->protocol),
6ff79f76 269 t->scope->link ? t->scope->link->ifname : "*",
202b76ae 270 af_to_name_short(t->scope->family),
164d025d 271 strnull(pretty));
ec2c5e43 272
a4076574
LP
273 /* RFC 4795, Section 4.1 says that the peer with the
274 * lexicographically smaller IP address loses */
4d91eec4
LP
275 if (memcmp(&p->sender, &p->destination, FAMILY_ADDRESS_SIZE(p->family)) >= 0) {
276 log_debug("Peer has lexicographically larger IP address and thus lost in the conflict.");
a4076574
LP
277 return;
278 }
279
4d91eec4 280 log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
a4076574 281
ec2c5e43 282 t->block_gc++;
35aa04e9 283
547973de 284 while ((z = set_first(t->notify_zone_items))) {
3ef64445
LP
285 /* First, make sure the zone item drops the reference
286 * to us */
287 dns_zone_item_probe_stop(z);
288
289 /* Secondly, report this as conflict, so that we might
290 * look for a different hostname */
ec2c5e43 291 dns_zone_item_conflict(z);
3ef64445 292 }
ec2c5e43
LP
293 t->block_gc--;
294
295 dns_transaction_gc(t);
296}
297
298void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
801ad6a6 299 DnsQueryCandidate *c;
ec2c5e43 300 DnsZoneItem *z;
547973de 301 DnsTransaction *d;
7cc6ed7b 302 const char *st;
202b76ae 303 char key_str[DNS_RESOURCE_KEY_STRING_MAX];
ec2c5e43
LP
304
305 assert(t);
547973de 306 assert(!DNS_TRANSACTION_IS_LIVE(state));
e56187ca 307
202b76ae
ZJS
308 if (state == DNS_TRANSACTION_DNSSEC_FAILED) {
309 dns_resource_key_to_string(t->key, key_str, sizeof key_str);
310
f61dfddb 311 log_struct(LOG_NOTICE,
2b044526 312 "MESSAGE_ID=" SD_MESSAGE_DNSSEC_FAILURE_STR,
202b76ae 313 LOG_MESSAGE("DNSSEC validation failed for question %s: %s", key_str, dnssec_result_to_string(t->answer_dnssec_result)),
f61dfddb 314 "DNS_TRANSACTION=%" PRIu16, t->id,
202b76ae 315 "DNS_QUESTION=%s", key_str,
f61dfddb 316 "DNSSEC_RESULT=%s", dnssec_result_to_string(t->answer_dnssec_result),
8aa5afd2 317 "DNS_SERVER=%s", strna(dns_server_string_full(t->server)),
a1230ff9 318 "DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(t->server->possible_feature_level));
202b76ae 319 }
f61dfddb 320
ec2c5e43
LP
321 /* Note that this call might invalidate the query. Callers
322 * should hence not attempt to access the query or transaction
323 * after calling this function. */
324
7cc6ed7b
LP
325 if (state == DNS_TRANSACTION_ERRNO)
326 st = errno_to_name(t->answer_errno);
327 else
328 st = dns_transaction_state_to_string(state);
329
a5784c49
LP
330 log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s now complete with <%s> from %s (%s).",
331 t->id,
202b76ae 332 dns_resource_key_to_string(t->key, key_str, sizeof key_str),
ec2c5e43 333 dns_protocol_to_string(t->scope->protocol),
6ff79f76 334 t->scope->link ? t->scope->link->ifname : "*",
202b76ae 335 af_to_name_short(t->scope->family),
7cc6ed7b 336 st,
a5784c49
LP
337 t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source),
338 t->answer_authenticated ? "authenticated" : "unsigned");
ec2c5e43
LP
339
340 t->state = state;
341
f32f0e57 342 dns_transaction_close_connection(t);
f535705a 343 dns_transaction_stop_timeout(t);
ec2c5e43
LP
344
345 /* Notify all queries that are interested, but make sure the
346 * transaction isn't freed while we are still looking at it */
347 t->block_gc++;
f7014757 348
35aa04e9 349 SET_FOREACH_MOVE(c, t->notify_query_candidates_done, t->notify_query_candidates)
547973de 350 dns_query_candidate_notify(c);
35aa04e9 351 SWAP_TWO(t->notify_query_candidates, t->notify_query_candidates_done);
ec2c5e43 352
35aa04e9
LP
353 SET_FOREACH_MOVE(z, t->notify_zone_items_done, t->notify_zone_items)
354 dns_zone_item_notify(z);
355 SWAP_TWO(t->notify_zone_items, t->notify_zone_items_done);
8d67e72c 356 if (t->probing && t->state == DNS_TRANSACTION_ATTEMPTS_MAX_REACHED)
1a63fc54 357 (void) dns_scope_announce(t->scope, false);
f7014757 358
35aa04e9
LP
359 SET_FOREACH_MOVE(d, t->notify_transactions_done, t->notify_transactions)
360 dns_transaction_notify(d, t);
361 SWAP_TWO(t->notify_transactions, t->notify_transactions_done);
f7014757
LP
362
363 t->block_gc--;
ec2c5e43
LP
364 dns_transaction_gc(t);
365}
366
fd8a3017
LP
367static void dns_transaction_complete_errno(DnsTransaction *t, int error) {
368 assert(t);
369 assert(error != 0);
370
371 t->answer_errno = abs(error);
372 dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
373}
374
519ef046
LP
375static int dns_transaction_pick_server(DnsTransaction *t) {
376 DnsServer *server;
377
378 assert(t);
379 assert(t->scope->protocol == DNS_PROTOCOL_DNS);
380
d001e0a3
LP
381 /* Pick a DNS server and a feature level for it. */
382
519ef046
LP
383 server = dns_scope_get_dns_server(t->scope);
384 if (!server)
385 return -ESRCH;
386
d001e0a3
LP
387 /* If we changed the server invalidate the feature level clamping, as the new server might have completely
388 * different properties. */
389 if (server != t->server)
390 t->clamp_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID;
391
274b8748 392 t->current_feature_level = dns_server_possible_feature_level(server);
519ef046 393
d001e0a3
LP
394 /* Clamp the feature level if that is requested. */
395 if (t->clamp_feature_level != _DNS_SERVER_FEATURE_LEVEL_INVALID &&
396 t->current_feature_level > t->clamp_feature_level)
397 t->current_feature_level = t->clamp_feature_level;
398
399 log_debug("Using feature level %s for transaction %u.", dns_server_feature_level_to_string(t->current_feature_level), t->id);
400
519ef046
LP
401 if (server == t->server)
402 return 0;
403
404 dns_server_unref(t->server);
405 t->server = dns_server_ref(server);
406
44db02d0
LP
407 t->n_picked_servers ++;
408
8aa5afd2 409 log_debug("Using DNS server %s for transaction %u.", strna(dns_server_string_full(t->server)), t->id);
d001e0a3 410
519ef046
LP
411 return 1;
412}
413
d001e0a3 414static void dns_transaction_retry(DnsTransaction *t, bool next_server) {
8d10d620
LP
415 int r;
416
417 assert(t);
418
419 log_debug("Retrying transaction %" PRIu16 ".", t->id);
420
421 /* Before we try again, switch to a new server. */
d001e0a3
LP
422 if (next_server)
423 dns_scope_next_dns_server(t->scope);
8d10d620
LP
424
425 r = dns_transaction_go(t);
fd8a3017
LP
426 if (r < 0)
427 dns_transaction_complete_errno(t, r);
8d10d620
LP
428}
429
c02cf2f4 430static int dns_transaction_maybe_restart(DnsTransaction *t) {
5278bbfe
LP
431 int r;
432
c02cf2f4
LP
433 assert(t);
434
5278bbfe
LP
435 /* Returns > 0 if the transaction was restarted, 0 if not */
436
c02cf2f4
LP
437 if (!t->server)
438 return 0;
439
440 if (t->current_feature_level <= dns_server_possible_feature_level(t->server))
441 return 0;
442
443 /* The server's current feature level is lower than when we sent the original query. We learnt something from
444 the response or possibly an auxiliary DNSSEC response that we didn't know before. We take that as reason to
445 restart the whole transaction. This is a good idea to deal with servers that respond rubbish if we include
446 OPT RR or DO bit. One of these cases is documented here, for example:
447 https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html */
448
4dd15077
LP
449 log_debug("Server feature level is now lower than when we began our transaction. Restarting with new ID.");
450 dns_transaction_shuffle_id(t);
5278bbfe
LP
451
452 r = dns_transaction_go(t);
453 if (r < 0)
454 return r;
455
456 return 1;
c02cf2f4
LP
457}
458
98767d75
IT
459static void on_transaction_stream_error(DnsTransaction *t, int error) {
460 assert(t);
ec2c5e43 461
b30bf55d 462 dns_transaction_close_connection(t);
ec2c5e43 463
a1a3f73a 464 if (ERRNO_IS_DISCONNECT(error)) {
0791110f
LP
465 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
466 /* If the LLMNR/TCP connection failed, the host doesn't support LLMNR, and we cannot answer the
467 * question on this scope. */
468 dns_transaction_complete(t, DNS_TRANSACTION_NOT_FOUND);
daab72ea 469 return;
0791110f
LP
470 }
471
d001e0a3 472 dns_transaction_retry(t, true);
daab72ea 473 return;
ac720200 474 }
fd8a3017
LP
475 if (error != 0)
476 dns_transaction_complete_errno(t, error);
98767d75
IT
477}
478
479static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsPacket *p) {
480 assert(t);
481 assert(p);
482
483 dns_transaction_close_connection(t);
ec2c5e43 484
a4076574 485 if (dns_packet_validate_reply(p) <= 0) {
a20b9592 486 log_debug("Invalid TCP reply packet.");
a4076574
LP
487 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
488 return 0;
489 }
490
491 dns_scope_check_conflicts(t->scope, p);
492
ec2c5e43
LP
493 t->block_gc++;
494 dns_transaction_process_reply(t, p);
495 t->block_gc--;
496
519ef046
LP
497 /* If the response wasn't useful, then complete the transition
498 * now. After all, we are the worst feature set now with TCP
499 * sockets, and there's really no point in retrying. */
ec2c5e43
LP
500 if (t->state == DNS_TRANSACTION_PENDING)
501 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
598f44bd
LP
502 else
503 dns_transaction_gc(t);
ec2c5e43
LP
504
505 return 0;
506}
507
98767d75 508static int on_stream_complete(DnsStream *s, int error) {
7172e4ee 509 assert(s);
98767d75
IT
510
511 if (ERRNO_IS_DISCONNECT(error) && s->protocol != DNS_PROTOCOL_LLMNR) {
98767d75
IT
512 log_debug_errno(error, "Connection failure for DNS TCP stream: %m");
513
514 if (s->transactions) {
97d5d905
LP
515 DnsTransaction *t;
516
98767d75 517 t = s->transactions;
3da3cdd5 518 dns_server_packet_lost(t->server, IPPROTO_TCP, t->current_feature_level);
98767d75
IT
519 }
520 }
521
97d5d905
LP
522 if (error != 0) {
523 DnsTransaction *t, *n;
524
525 LIST_FOREACH_SAFE(transactions_by_stream, t, n, s->transactions)
98767d75 526 on_transaction_stream_error(t, error);
97d5d905 527 }
98767d75 528
97d5d905 529 return 0;
98767d75
IT
530}
531
747a8a74 532static int on_stream_packet(DnsStream *s) {
98767d75 533 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
98767d75
IT
534 DnsTransaction *t;
535
aa337a5e
LP
536 assert(s);
537
98767d75 538 /* Take ownership of packet to be able to receive new packets */
aa337a5e
LP
539 p = dns_stream_take_read_packet(s);
540 assert(p);
98767d75
IT
541
542 t = hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
aa337a5e
LP
543 if (t)
544 return dns_transaction_on_stream_packet(t, p);
98767d75 545
8227cfa1 546 /* Ignore incorrect transaction id as an old transaction can have been canceled. */
30f9e0bf 547 log_debug("Received unexpected TCP reply packet with id %" PRIu16 ", ignoring.", DNS_PACKET_ID(p));
aa337a5e 548 return 0;
98767d75
IT
549}
550
da9de738
YW
551static uint16_t dns_transaction_port(DnsTransaction *t) {
552 if (t->server->port > 0)
553 return t->server->port;
554 return DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) ? 853 : 53;
ec962fba
LP
555}
556
98767d75 557static int dns_transaction_emit_tcp(DnsTransaction *t) {
98767d75 558 _cleanup_(dns_stream_unrefp) DnsStream *s = NULL;
652ba568 559 _cleanup_close_ int fd = -1;
91ccab1e 560 union sockaddr_union sa;
652ba568 561 DnsStreamType type;
ec2c5e43
LP
562 int r;
563
564 assert(t);
565
519ef046 566 dns_transaction_close_connection(t);
ec2c5e43 567
106784eb 568 switch (t->scope->protocol) {
519ef046 569
106784eb 570 case DNS_PROTOCOL_DNS:
519ef046
LP
571 r = dns_transaction_pick_server(t);
572 if (r < 0)
573 return r;
574
92ec902a 575 if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(t->key->type))
91adc4db
LP
576 return -EOPNOTSUPP;
577
274b8748 578 r = dns_server_adjust_opt(t->server, t->sent, t->current_feature_level);
519ef046
LP
579 if (r < 0)
580 return r;
581
5d67a7ae 582 if (t->server->stream && (DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) == t->server->stream->encrypted))
98767d75
IT
583 s = dns_stream_ref(t->server->stream);
584 else
da9de738 585 fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, dns_transaction_port(t), &sa);
98767d75 586
652ba568 587 type = DNS_STREAM_LOOKUP;
106784eb 588 break;
ec2c5e43 589
106784eb 590 case DNS_PROTOCOL_LLMNR:
a8f6397f 591 /* When we already received a reply to this (but it was truncated), send to its sender address */
ec2c5e43 592 if (t->received)
91ccab1e 593 fd = dns_scope_socket_tcp(t->scope, t->received->family, &t->received->sender, NULL, t->received->sender_port, &sa);
ec2c5e43
LP
594 else {
595 union in_addr_union address;
a7f7d1bd 596 int family = AF_UNSPEC;
ec2c5e43
LP
597
598 /* Otherwise, try to talk to the owner of a
599 * the IP address, in case this is a reverse
600 * PTR lookup */
f52e61da 601
1c02e7ba 602 r = dns_name_address(dns_resource_key_name(t->key), &family, &address);
ec2c5e43
LP
603 if (r < 0)
604 return r;
605 if (r == 0)
606 return -EINVAL;
9e08a6e0 607 if (family != t->scope->family)
9318cdd3 608 return -ESRCH;
ec2c5e43 609
91ccab1e 610 fd = dns_scope_socket_tcp(t->scope, family, &address, NULL, LLMNR_PORT, &sa);
ec2c5e43 611 }
106784eb 612
652ba568 613 type = DNS_STREAM_LLMNR_SEND;
106784eb
DM
614 break;
615
616 default:
ec2c5e43 617 return -EAFNOSUPPORT;
106784eb 618 }
ec2c5e43 619
98767d75
IT
620 if (!s) {
621 if (fd < 0)
622 return fd;
ec2c5e43 623
652ba568 624 r = dns_stream_new(t->scope->manager, &s, type, t->scope->protocol, fd, &sa);
98767d75
IT
625 if (r < 0)
626 return r;
627
628 fd = -1;
629
56ddbf10 630#if ENABLE_DNS_OVER_TLS
199dda9c
LP
631 if (t->scope->protocol == DNS_PROTOCOL_DNS &&
632 DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level)) {
633
b02a7e1a 634 assert(t->server);
6016fcb0 635 r = dnstls_stream_connect_tls(s, t->server);
5d67a7ae
IT
636 if (r < 0)
637 return r;
638 }
639#endif
640
19feb28f 641 if (t->server) {
904dcaf9 642 dns_server_unref_stream(t->server);
19feb28f 643 s->server = dns_server_ref(t->server);
8227cfa1 644 t->server->stream = dns_stream_ref(s);
19feb28f
IT
645 }
646
98767d75 647 s->complete = on_stream_complete;
747a8a74 648 s->on_packet = on_stream_packet;
98767d75
IT
649
650 /* The interface index is difficult to determine if we are
651 * connecting to the local host, hence fill this in right away
652 * instead of determining it from the socket */
653 s->ifindex = dns_scope_ifindex(t->scope);
654 }
655
656 t->stream = TAKE_PTR(s);
657 LIST_PREPEND(transactions_by_stream, t->stream->transactions, t);
ec2c5e43
LP
658
659 r = dns_stream_write_packet(t->stream, t->sent);
660 if (r < 0) {
98767d75 661 dns_transaction_close_connection(t);
ec2c5e43
LP
662 return r;
663 }
664
519ef046
LP
665 dns_transaction_reset_answer(t);
666
cbe4216d
LP
667 t->tried_stream = true;
668
ec2c5e43
LP
669 return 0;
670}
671
547973de 672static void dns_transaction_cache_answer(DnsTransaction *t) {
547973de
LP
673 assert(t);
674
675 /* For mDNS we cache whenever we get the packet, rather than
676 * in each transaction. */
677 if (!IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR))
678 return;
679
ceeddf79 680 /* Caching disabled? */
37d7a7d9 681 if (t->scope->manager->enable_cache == DNS_CACHE_MODE_NO)
ceeddf79
MP
682 return;
683
547973de
LP
684 /* We never cache if this packet is from the local host, under
685 * the assumption that a locally running DNS server would
686 * cache this anyway, and probably knows better when to flush
687 * the cache then we could. */
688 if (!DNS_PACKET_SHALL_CACHE(t->received))
689 return;
690
547973de 691 dns_cache_put(&t->scope->cache,
37d7a7d9 692 t->scope->manager->enable_cache,
547973de
LP
693 t->key,
694 t->answer_rcode,
695 t->answer,
547973de 696 t->answer_authenticated,
d3760be0 697 t->answer_nsec_ttl,
547973de
LP
698 0,
699 t->received->family,
700 &t->received->sender);
701}
702
105e1512
LP
703static bool dns_transaction_dnssec_is_live(DnsTransaction *t) {
704 DnsTransaction *dt;
105e1512
LP
705
706 assert(t);
707
90e74a66 708 SET_FOREACH(dt, t->dnssec_transactions)
105e1512
LP
709 if (DNS_TRANSACTION_IS_LIVE(dt->state))
710 return true;
711
712 return false;
713}
714
942eb2e7
LP
715static int dns_transaction_dnssec_ready(DnsTransaction *t) {
716 DnsTransaction *dt;
942eb2e7
LP
717
718 assert(t);
719
720 /* Checks whether the auxiliary DNSSEC transactions of our transaction have completed, or are still
721 * ongoing. Returns 0, if we aren't ready for the DNSSEC validation, positive if we are. */
722
90e74a66 723 SET_FOREACH(dt, t->dnssec_transactions) {
942eb2e7
LP
724
725 switch (dt->state) {
726
727 case DNS_TRANSACTION_NULL:
728 case DNS_TRANSACTION_PENDING:
729 case DNS_TRANSACTION_VALIDATING:
730 /* Still ongoing */
731 return 0;
732
733 case DNS_TRANSACTION_RCODE_FAILURE:
b3c6b00a 734 if (!IN_SET(dt->answer_rcode, DNS_RCODE_NXDOMAIN, DNS_RCODE_SERVFAIL)) {
942eb2e7
LP
735 log_debug("Auxiliary DNSSEC RR query failed with rcode=%s.", dns_rcode_to_string(dt->answer_rcode));
736 goto fail;
737 }
738
b3c6b00a 739 /* Fall-through: NXDOMAIN/SERVFAIL is good enough for us. This is because some DNS servers
5238e957 740 * erroneously return NXDOMAIN/SERVFAIL for empty non-terminals (Akamai...) or missing DS
b3c6b00a
LP
741 * records (Facebook), and we need to handle that nicely, when asking for parent SOA or similar
742 * RRs to make unsigned proofs. */
942eb2e7
LP
743
744 case DNS_TRANSACTION_SUCCESS:
745 /* All good. */
746 break;
747
748 case DNS_TRANSACTION_DNSSEC_FAILED:
749 /* We handle DNSSEC failures different from other errors, as we care about the DNSSEC
750 * validationr result */
751
752 log_debug("Auxiliary DNSSEC RR query failed validation: %s", dnssec_result_to_string(dt->answer_dnssec_result));
753 t->answer_dnssec_result = dt->answer_dnssec_result; /* Copy error code over */
754 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
755 return 0;
756
942eb2e7
LP
757 default:
758 log_debug("Auxiliary DNSSEC RR query failed with %s", dns_transaction_state_to_string(dt->state));
759 goto fail;
760 }
761 }
762
763 /* All is ready, we can go and validate */
764 return 1;
765
766fail:
767 t->answer_dnssec_result = DNSSEC_FAILED_AUXILIARY;
768 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
769 return 0;
770}
771
547973de
LP
772static void dns_transaction_process_dnssec(DnsTransaction *t) {
773 int r;
774
775 assert(t);
776
777 /* Are there ongoing DNSSEC transactions? If so, let's wait for them. */
942eb2e7 778 r = dns_transaction_dnssec_ready(t);
7cc6ed7b
LP
779 if (r < 0)
780 goto fail;
942eb2e7 781 if (r == 0) /* We aren't ready yet (or one of our auxiliary transactions failed, and we shouldn't validate now */
547973de
LP
782 return;
783
c02cf2f4
LP
784 /* See if we learnt things from the additional DNSSEC transactions, that we didn't know before, and better
785 * restart the lookup immediately. */
786 r = dns_transaction_maybe_restart(t);
7cc6ed7b
LP
787 if (r < 0)
788 goto fail;
c02cf2f4
LP
789 if (r > 0) /* Transaction got restarted... */
790 return;
791
547973de
LP
792 /* All our auxiliary DNSSEC transactions are complete now. Try
793 * to validate our RRset now. */
794 r = dns_transaction_validate_dnssec(t);
fcfaff12
LP
795 if (r == -EBADMSG) {
796 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
797 return;
798 }
7cc6ed7b
LP
799 if (r < 0)
800 goto fail;
547973de 801
b652d4a2
LP
802 if (t->answer_dnssec_result == DNSSEC_INCOMPATIBLE_SERVER &&
803 t->scope->dnssec_mode == DNSSEC_YES) {
e82b1132
LP
804
805 /* We are not in automatic downgrade mode, and the server is bad. Let's try a different server, maybe
806 * that works. */
807
808 if (t->n_picked_servers < dns_scope_get_n_dns_servers(t->scope)) {
809 /* We tried fewer servers on this transaction than we know, let's try another one then */
810 dns_transaction_retry(t, true);
811 return;
812 }
813
814 /* OK, let's give up, apparently all servers we tried didn't work. */
b652d4a2
LP
815 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
816 return;
817 }
818
019036a4 819 if (!IN_SET(t->answer_dnssec_result,
b652d4a2
LP
820 _DNSSEC_RESULT_INVALID, /* No DNSSEC validation enabled */
821 DNSSEC_VALIDATED, /* Answer is signed and validated successfully */
822 DNSSEC_UNSIGNED, /* Answer is right-fully unsigned */
823 DNSSEC_INCOMPATIBLE_SERVER)) { /* Server does not do DNSSEC (Yay, we are downgrade attack vulnerable!) */
547973de
LP
824 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
825 return;
826 }
827
1e02e182
LP
828 if (t->answer_dnssec_result == DNSSEC_INCOMPATIBLE_SERVER)
829 dns_server_warn_downgrade(t->server);
830
547973de
LP
831 dns_transaction_cache_answer(t);
832
833 if (t->answer_rcode == DNS_RCODE_SUCCESS)
834 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
835 else
3bbdc31d 836 dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE);
7cc6ed7b
LP
837
838 return;
839
840fail:
fd8a3017 841 dns_transaction_complete_errno(t, r);
547973de
LP
842}
843
eac7cda2
LP
844static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) {
845 int r;
846
847 assert(t);
848
849 /* Checks whether the answer is positive, i.e. either a direct
850 * answer to the question, or a CNAME/DNAME for it */
851
852 r = dns_answer_match_key(t->answer, t->key, flags);
853 if (r != 0)
854 return r;
855
856 r = dns_answer_find_cname_or_dname(t->answer, t->key, NULL, flags);
857 if (r != 0)
858 return r;
859
860 return false;
861}
862
863static int dns_transaction_fix_rcode(DnsTransaction *t) {
864 int r;
865
866 assert(t);
867
868 /* Fix up the RCODE to SUCCESS if we get at least one matching RR in a response. Note that this contradicts the
869 * DNS RFCs a bit. Specifically, RFC 6604 Section 3 clarifies that the RCODE shall say something about a
870 * CNAME/DNAME chain element coming after the last chain element contained in the message, and not the first
871 * one included. However, it also indicates that not all DNS servers implement this correctly. Moreover, when
872 * using DNSSEC we usually only can prove the first element of a CNAME/DNAME chain anyway, hence let's settle
873 * on always processing the RCODE as referring to the immediate look-up we do, i.e. the first element of a
874 * CNAME/DNAME chain. This way, we uniformly handle CNAME/DNAME chains, regardless if the DNS server
875 * incorrectly implements RCODE, whether DNSSEC is in use, or whether the DNS server only supplied us with an
876 * incomplete CNAME/DNAME chain.
877 *
878 * Or in other words: if we get at least one positive reply in a message we patch NXDOMAIN to become SUCCESS,
879 * and then rely on the CNAME chasing logic to figure out that there's actually a CNAME error with a new
880 * lookup. */
881
882 if (t->answer_rcode != DNS_RCODE_NXDOMAIN)
883 return 0;
884
885 r = dns_transaction_has_positive_answer(t, NULL);
886 if (r <= 0)
887 return r;
888
889 t->answer_rcode = DNS_RCODE_SUCCESS;
890 return 0;
891}
892
ec2c5e43 893void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
9df3ba6c 894 usec_t ts;
ec2c5e43
LP
895 int r;
896
897 assert(t);
898 assert(p);
9df3ba6c
TG
899 assert(t->scope);
900 assert(t->scope->manager);
ec2c5e43 901
5a7e41a3
LP
902 if (t->state != DNS_TRANSACTION_PENDING)
903 return;
904
ec2c5e43
LP
905 /* Note that this call might invalidate the query. Callers
906 * should hence not attempt to access the query or transaction
907 * after calling this function. */
908
11833205
ZJS
909 log_debug("Processing incoming packet on transaction %" PRIu16" (rcode=%s).",
910 t->id, dns_rcode_to_string(DNS_PACKET_RCODE(p)));
b5efcf29 911
106784eb 912 switch (t->scope->protocol) {
b5efcf29 913
106784eb 914 case DNS_PROTOCOL_LLMNR:
97ebebbc 915 /* For LLMNR we will not accept any packets from other interfaces */
ec2c5e43 916
97ebebbc 917 if (p->ifindex != dns_scope_ifindex(t->scope))
ec2c5e43
LP
918 return;
919
920 if (p->family != t->scope->family)
921 return;
922
923 /* Tentative packets are not full responses but still
924 * useful for identifying uniqueness conflicts during
925 * probing. */
8b757a38 926 if (DNS_PACKET_LLMNR_T(p)) {
ec2c5e43
LP
927 dns_transaction_tentative(t, p);
928 return;
929 }
106784eb
DM
930
931 break;
932
4e5bf5e1 933 case DNS_PROTOCOL_MDNS:
4e5bf5e1 934 /* For mDNS we will not accept any packets from other interfaces */
97ebebbc
LP
935
936 if (p->ifindex != dns_scope_ifindex(t->scope))
4e5bf5e1
DM
937 return;
938
939 if (p->family != t->scope->family)
940 return;
941
942 break;
943
106784eb 944 case DNS_PROTOCOL_DNS:
8ad182a1
LP
945 /* Note that we do not need to verify the
946 * addresses/port numbers of incoming traffic, as we
947 * invoked connect() on our UDP socket in which case
948 * the kernel already does the needed verification for
949 * us. */
106784eb
DM
950 break;
951
952 default:
9c56a6f3 953 assert_not_reached("Invalid DNS protocol.");
ec2c5e43
LP
954 }
955
ec2c5e43
LP
956 if (t->received != p) {
957 dns_packet_unref(t->received);
958 t->received = dns_packet_ref(p);
959 }
960
c3bc53e6
LP
961 t->answer_source = DNS_TRANSACTION_NETWORK;
962
ec2c5e43
LP
963 if (p->ipproto == IPPROTO_TCP) {
964 if (DNS_PACKET_TC(p)) {
965 /* Truncated via TCP? Somebody must be fucking with us */
966 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
967 return;
968 }
969
970 if (DNS_PACKET_ID(p) != t->id) {
971 /* Not the reply to our query? Somebody must be fucking with us */
972 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
973 return;
974 }
975 }
976
38a03f06 977 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
9df3ba6c
TG
978
979 switch (t->scope->protocol) {
8af5b883 980
9df3ba6c
TG
981 case DNS_PROTOCOL_DNS:
982 assert(t->server);
983
4e0b8b17
TG
984 if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
985
8af5b883 986 /* Request failed, immediately try again with reduced features */
4e0b8b17 987
7d581a65 988 if (t->current_feature_level <= DNS_SERVER_FEATURE_LEVEL_UDP) {
44db02d0 989
7d581a65 990 /* This was already at UDP feature level? If so, it doesn't make sense to downgrade
44db02d0
LP
991 * this transaction anymore, but let's see if it might make sense to send the request
992 * to a different DNS server instead. If not let's process the response, and accept the
7d581a65
LP
993 * rcode. Note that we don't retry on TCP, since that's a suitable way to mitigate
994 * packet loss, but is not going to give us better rcodes should we actually have
995 * managed to get them already at UDP level. */
996
44db02d0
LP
997 if (t->n_picked_servers < dns_scope_get_n_dns_servers(t->scope)) {
998 /* We tried fewer servers on this transaction than we know, let's try another one then */
999 dns_transaction_retry(t, true);
1000 return;
1001 }
1002
1003 /* Give up, accept the rcode */
d001e0a3
LP
1004 log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p)));
1005 break;
1006 }
1007
1008 /* Reduce this feature level by one and try again. */
5d67a7ae
IT
1009 switch (t->current_feature_level) {
1010 case DNS_SERVER_FEATURE_LEVEL_TLS_DO:
1011 t->clamp_feature_level = DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN;
1012 break;
1013 case DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN + 1:
1014 /* Skip plain TLS when TLS is not supported */
1015 t->clamp_feature_level = DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN - 1;
1016 break;
1017 default:
1018 t->clamp_feature_level = t->current_feature_level - 1;
1019 }
d001e0a3
LP
1020
1021 log_debug("Server returned error %s, retrying transaction with reduced feature level %s.",
1022 dns_rcode_to_string(DNS_PACKET_RCODE(p)),
1023 dns_server_feature_level_to_string(t->clamp_feature_level));
1024
1025 dns_transaction_retry(t, false /* use the same server */);
4e0b8b17 1026 return;
eb08640a
LP
1027 }
1028
1029 if (DNS_PACKET_RCODE(p) == DNS_RCODE_REFUSED) {
1030 /* This server refused our request? If so, try again, use a different server */
1031 log_debug("Server returned REFUSED, switching servers, and retrying.");
1032 dns_transaction_retry(t, true /* pick a new server */);
1033 return;
1034 }
1035
1036 if (DNS_PACKET_TC(p))
274b8748 1037 dns_server_packet_truncated(t->server, t->current_feature_level);
9df3ba6c
TG
1038
1039 break;
8af5b883 1040
9df3ba6c
TG
1041 case DNS_PROTOCOL_LLMNR:
1042 case DNS_PROTOCOL_MDNS:
1043 dns_scope_packet_received(t->scope, ts - t->start_usec);
9df3ba6c 1044 break;
8af5b883 1045
9df3ba6c 1046 default:
8af5b883 1047 assert_not_reached("Invalid DNS protocol.");
9df3ba6c
TG
1048 }
1049
ec2c5e43 1050 if (DNS_PACKET_TC(p)) {
547493c5
DM
1051
1052 /* Truncated packets for mDNS are not allowed. Give up immediately. */
1053 if (t->scope->protocol == DNS_PROTOCOL_MDNS) {
1054 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
1055 return;
1056 }
1057
f757cd85
LP
1058 log_debug("Reply truncated, retrying via TCP.");
1059
ec2c5e43 1060 /* Response was truncated, let's try again with good old TCP */
98767d75 1061 r = dns_transaction_emit_tcp(t);
ec2c5e43
LP
1062 if (r == -ESRCH) {
1063 /* No servers found? Damn! */
1064 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
1065 return;
1066 }
91adc4db
LP
1067 if (r == -EOPNOTSUPP) {
1068 /* Tried to ask for DNSSEC RRs, on a server that doesn't do DNSSEC */
1069 dns_transaction_complete(t, DNS_TRANSACTION_RR_TYPE_UNSUPPORTED);
1070 return;
1071 }
ec2c5e43 1072 if (r < 0) {
8af5b883 1073 /* On LLMNR, if we cannot connect to the host,
ec2c5e43 1074 * we immediately give up */
7cc6ed7b
LP
1075 if (t->scope->protocol != DNS_PROTOCOL_DNS)
1076 goto fail;
ec2c5e43
LP
1077
1078 /* On DNS, couldn't send? Try immediately again, with a new server */
d001e0a3 1079 dns_transaction_retry(t, true);
ec2c5e43 1080 }
2a6658ef
LP
1081
1082 return;
ec2c5e43
LP
1083 }
1084
de54e62b 1085 /* After the superficial checks, actually parse the message. */
ec2c5e43
LP
1086 r = dns_packet_extract(p);
1087 if (r < 0) {
1088 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
1089 return;
1090 }
1091
ed9717fc 1092 if (t->server) {
d001e0a3
LP
1093 /* Report that we successfully received a valid packet with a good rcode after we initially got a bad
1094 * rcode and subsequently downgraded the protocol */
1095
1096 if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN) &&
1097 t->clamp_feature_level != _DNS_SERVER_FEATURE_LEVEL_INVALID)
1098 dns_server_packet_rcode_downgrade(t->server, t->clamp_feature_level);
1099
1100 /* Report that the OPT RR was missing */
ed9717fc
LP
1101 if (!p->opt)
1102 dns_server_packet_bad_opt(t->server, t->current_feature_level);
1103
d001e0a3 1104 /* Report that we successfully received a packet */
dbc4661a 1105 dns_server_packet_received(t->server, p->ipproto, t->current_feature_level, p->size);
ed9717fc 1106 }
de54e62b 1107
c02cf2f4
LP
1108 /* See if we know things we didn't know before that indicate we better restart the lookup immediately. */
1109 r = dns_transaction_maybe_restart(t);
7cc6ed7b
LP
1110 if (r < 0)
1111 goto fail;
c02cf2f4
LP
1112 if (r > 0) /* Transaction got restarted... */
1113 return;
1114
8b419837 1115 if (IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR, DNS_PROTOCOL_MDNS)) {
b5efcf29 1116
8b419837
DR
1117 /* When dealing with protocols other than mDNS only consider responses with
1118 * equivalent query section to the request. For mDNS this check doesn't make
1119 * sense, because the section 6 of RFC6762 states that "Multicast DNS responses MUST NOT
1120 * contain any questions in the Question Section". */
1121 if (t->scope->protocol != DNS_PROTOCOL_MDNS) {
1122 r = dns_packet_is_reply_for(p, t->key);
1123 if (r < 0)
1124 goto fail;
1125 if (r == 0) {
1126 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
1127 return;
1128 }
547493c5 1129 }
29815b6c 1130
547493c5
DM
1131 /* Install the answer as answer to the transaction */
1132 dns_answer_unref(t->answer);
1133 t->answer = dns_answer_ref(p->answer);
1134 t->answer_rcode = DNS_PACKET_RCODE(p);
919c2ae0 1135 t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
105e1512 1136 t->answer_authenticated = false;
79e24931 1137
eac7cda2
LP
1138 r = dns_transaction_fix_rcode(t);
1139 if (r < 0)
1140 goto fail;
1141
51e399bc
LP
1142 /* Block GC while starting requests for additional DNSSEC RRs */
1143 t->block_gc++;
547973de 1144 r = dns_transaction_request_dnssec_keys(t);
51e399bc
LP
1145 t->block_gc--;
1146
1147 /* Maybe the transaction is ready for GC'ing now? If so, free it and return. */
1148 if (!dns_transaction_gc(t))
1149 return;
1150
1151 /* Requesting additional keys might have resulted in
1152 * this transaction to fail, since the auxiliary
1153 * request failed for some reason. If so, we are not
1154 * in pending state anymore, and we should exit
1155 * quickly. */
1156 if (t->state != DNS_TRANSACTION_PENDING)
1157 return;
7cc6ed7b
LP
1158 if (r < 0)
1159 goto fail;
547973de
LP
1160 if (r > 0) {
1161 /* There are DNSSEC transactions pending now. Update the state accordingly. */
1162 t->state = DNS_TRANSACTION_VALIDATING;
f535705a
LP
1163 dns_transaction_close_connection(t);
1164 dns_transaction_stop_timeout(t);
547973de
LP
1165 return;
1166 }
547493c5 1167 }
ec2c5e43 1168
547973de 1169 dns_transaction_process_dnssec(t);
7cc6ed7b
LP
1170 return;
1171
1172fail:
fd8a3017 1173 dns_transaction_complete_errno(t, r);
ec2c5e43
LP
1174}
1175
c19ffd9f
TG
1176static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1177 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1178 DnsTransaction *t = userdata;
1179 int r;
1180
1181 assert(t);
1182 assert(t->scope);
1183
1184 r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p);
95d2155a 1185 if (ERRNO_IS_DISCONNECT(r)) {
7e1851e3 1186 usec_t usec;
c19ffd9f 1187
f731fd5b
ZJS
1188 /* UDP connection failures get reported via ICMP and then are possibly delivered to us on the
1189 * next recvmsg(). Treat this like a lost packet. */
7e1851e3 1190
92ec902a 1191 log_debug_errno(r, "Connection failure for DNS UDP packet: %m");
7e1851e3 1192 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &usec) >= 0);
3da3cdd5 1193 dns_server_packet_lost(t->server, IPPROTO_UDP, t->current_feature_level);
7e1851e3 1194
d001e0a3 1195 dns_transaction_retry(t, true);
7e1851e3
LP
1196 return 0;
1197 }
1198 if (r < 0) {
fd8a3017 1199 dns_transaction_complete_errno(t, r);
7e1851e3
LP
1200 return 0;
1201 }
f731fd5b
ZJS
1202 if (r == 0)
1203 /* Spurious wakeup without any data */
1204 return 0;
7e1851e3
LP
1205
1206 r = dns_packet_validate_reply(p);
1207 if (r < 0) {
1208 log_debug_errno(r, "Received invalid DNS packet as response, ignoring: %m");
1209 return 0;
1210 }
1211 if (r == 0) {
e09f605e 1212 log_debug("Received inappropriate DNS packet as response, ignoring.");
7e1851e3
LP
1213 return 0;
1214 }
1215
1216 if (DNS_PACKET_ID(p) != t->id) {
e09f605e 1217 log_debug("Received packet with incorrect transaction ID, ignoring.");
7e1851e3
LP
1218 return 0;
1219 }
c19ffd9f 1220
7e1851e3 1221 dns_transaction_process_reply(t, p);
c19ffd9f
TG
1222 return 0;
1223}
1224
49cce12d 1225static int dns_transaction_emit_udp(DnsTransaction *t) {
c19ffd9f
TG
1226 int r;
1227
1228 assert(t);
c19ffd9f 1229
519ef046 1230 if (t->scope->protocol == DNS_PROTOCOL_DNS) {
c19ffd9f 1231
519ef046 1232 r = dns_transaction_pick_server(t);
471d40d9
TG
1233 if (r < 0)
1234 return r;
c19ffd9f 1235
5d67a7ae 1236 if (t->current_feature_level < DNS_SERVER_FEATURE_LEVEL_UDP || DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level))
7d581a65 1237 return -EAGAIN; /* Sorry, can't do UDP, try TCP! */
519ef046 1238
92ec902a 1239 if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(t->key->type))
91adc4db
LP
1240 return -EOPNOTSUPP;
1241
519ef046
LP
1242 if (r > 0 || t->dns_udp_fd < 0) { /* Server changed, or no connection yet. */
1243 int fd;
1244
1245 dns_transaction_close_connection(t);
c19ffd9f 1246
da9de738 1247 fd = dns_scope_socket_udp(t->scope, t->server);
519ef046
LP
1248 if (fd < 0)
1249 return fd;
1250
1251 r = sd_event_add_io(t->scope->manager->event, &t->dns_udp_event_source, fd, EPOLLIN, on_dns_packet, t);
1252 if (r < 0) {
1253 safe_close(fd);
1254 return r;
1255 }
1256
aa4a9deb 1257 (void) sd_event_source_set_description(t->dns_udp_event_source, "dns-transaction-udp");
519ef046
LP
1258 t->dns_udp_fd = fd;
1259 }
1260
274b8748 1261 r = dns_server_adjust_opt(t->server, t->sent, t->current_feature_level);
519ef046
LP
1262 if (r < 0)
1263 return r;
1264 } else
1265 dns_transaction_close_connection(t);
1266
1267 r = dns_scope_emit_udp(t->scope, t->dns_udp_fd, t->sent);
471d40d9
TG
1268 if (r < 0)
1269 return r;
c19ffd9f 1270
519ef046 1271 dns_transaction_reset_answer(t);
be808ea0 1272
471d40d9 1273 return 0;
c19ffd9f
TG
1274}
1275
ec2c5e43
LP
1276static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
1277 DnsTransaction *t = userdata;
ec2c5e43
LP
1278
1279 assert(s);
1280 assert(t);
1281
ef7ce6df
DM
1282 if (!t->initial_jitter_scheduled || t->initial_jitter_elapsed) {
1283 /* Timeout reached? Increase the timeout for the server used */
1284 switch (t->scope->protocol) {
49cce12d 1285
ef7ce6df
DM
1286 case DNS_PROTOCOL_DNS:
1287 assert(t->server);
3da3cdd5 1288 dns_server_packet_lost(t->server, t->stream ? IPPROTO_TCP : IPPROTO_UDP, t->current_feature_level);
ef7ce6df 1289 break;
49cce12d 1290
ef7ce6df
DM
1291 case DNS_PROTOCOL_LLMNR:
1292 case DNS_PROTOCOL_MDNS:
1293 dns_scope_packet_lost(t->scope, usec - t->start_usec);
ef7ce6df 1294 break;
49cce12d 1295
ef7ce6df
DM
1296 default:
1297 assert_not_reached("Invalid DNS protocol.");
1298 }
1299
1300 if (t->initial_jitter_scheduled)
1301 t->initial_jitter_elapsed = true;
be808ea0
TG
1302 }
1303
423659ab
LP
1304 log_debug("Timeout reached on transaction %" PRIu16 ".", t->id);
1305
d001e0a3 1306 dns_transaction_retry(t, true);
ec2c5e43
LP
1307 return 0;
1308}
1309
9df3ba6c
TG
1310static usec_t transaction_get_resend_timeout(DnsTransaction *t) {
1311 assert(t);
1312 assert(t->scope);
1313
1314 switch (t->scope->protocol) {
49cce12d 1315
9df3ba6c 1316 case DNS_PROTOCOL_DNS:
dc349f5f
LP
1317
1318 /* When we do TCP, grant a much longer timeout, as in this case there's no need for us to quickly
1319 * resend, as the kernel does that anyway for us, and we really don't want to interrupt it in that
1320 * needlessly. */
1321 if (t->stream)
1322 return TRANSACTION_TCP_TIMEOUT_USEC;
1323
dbc4661a 1324 return DNS_TIMEOUT_USEC;
49cce12d 1325
9df3ba6c 1326 case DNS_PROTOCOL_MDNS:
11a27c2e 1327 assert(t->n_attempts > 0);
53fda2bb
DR
1328 if (t->probing)
1329 return MDNS_PROBING_INTERVAL_USEC;
1330 else
1331 return (1 << (t->n_attempts - 1)) * USEC_PER_SEC;
49cce12d 1332
11a27c2e 1333 case DNS_PROTOCOL_LLMNR:
9df3ba6c 1334 return t->scope->resend_timeout;
49cce12d 1335
9df3ba6c
TG
1336 default:
1337 assert_not_reached("Invalid DNS protocol.");
1338 }
1339}
1340
c842ff24 1341static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
ec2c5e43
LP
1342 int r;
1343
1344 assert(t);
1345
f535705a 1346 dns_transaction_stop_timeout(t);
ec2c5e43 1347
86b112a3 1348 if (!dns_scope_network_good(t->scope)) {
edbcc1fd
LP
1349 dns_transaction_complete(t, DNS_TRANSACTION_NETWORK_DOWN);
1350 return 0;
1351 }
1352
ec2c5e43 1353 if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
e53b8cc5
ZJS
1354 DnsTransactionState result;
1355
1356 if (t->scope->protocol == DNS_PROTOCOL_LLMNR)
1357 /* If we didn't find anything on LLMNR, it's not an error, but a failure to resolve
1358 * the name. */
1359 result = DNS_TRANSACTION_NOT_FOUND;
1360 else
1361 result = DNS_TRANSACTION_ATTEMPTS_MAX_REACHED;
1362
1363 dns_transaction_complete(t, result);
ec2c5e43
LP
1364 return 0;
1365 }
1366
cbe4216d 1367 if (t->scope->protocol == DNS_PROTOCOL_LLMNR && t->tried_stream) {
ec2c5e43
LP
1368 /* If we already tried via a stream, then we don't
1369 * retry on LLMNR. See RFC 4795, Section 2.7. */
1370 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
1371 return 0;
1372 }
1373
1374 t->n_attempts++;
9df3ba6c 1375 t->start_usec = ts;
c61d2b44
LP
1376
1377 dns_transaction_reset_answer(t);
c5b4f861 1378 dns_transaction_flush_dnssec_transactions(t);
ec2c5e43 1379
0d2cd476
LP
1380 /* Check the trust anchor. Do so only on classic DNS, since DNSSEC does not apply otherwise. */
1381 if (t->scope->protocol == DNS_PROTOCOL_DNS) {
8e54f5d9 1382 r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, t->key, &t->answer);
0d2cd476
LP
1383 if (r < 0)
1384 return r;
1385 if (r > 0) {
1386 t->answer_rcode = DNS_RCODE_SUCCESS;
1387 t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
931851e8 1388 t->answer_authenticated = true;
0d2cd476
LP
1389 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
1390 return 0;
1391 }
b2b796b8 1392
1c02e7ba 1393 if (dns_name_is_root(dns_resource_key_name(t->key)) &&
b2b796b8
LP
1394 t->key->type == DNS_TYPE_DS) {
1395
1396 /* Hmm, this is a request for the root DS? A
1397 * DS RR doesn't exist in the root zone, and
1398 * if our trust anchor didn't know it either,
1399 * this means we cannot do any DNSSEC logic
1400 * anymore. */
1401
1ed8c0fb 1402 if (t->scope->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE) {
b2b796b8
LP
1403 /* We are in downgrade mode. In this
1404 * case, synthesize an unsigned empty
1405 * response, so that the any lookup
1406 * depending on this one can continue
1407 * assuming there was no DS, and hence
1408 * the root zone was unsigned. */
1409
1410 t->answer_rcode = DNS_RCODE_SUCCESS;
1411 t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
1412 t->answer_authenticated = false;
1413 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
1414 } else
1415 /* If we are not in downgrade mode,
1416 * then fail the lookup, because we
1417 * cannot reasonably answer it. There
1418 * might be DS RRs, but we don't know
1419 * them, and the DNS server won't tell
1420 * them to us (and even if it would,
202b76ae 1421 * we couldn't validate and trust them. */
b2b796b8
LP
1422 dns_transaction_complete(t, DNS_TRANSACTION_NO_TRUST_ANCHOR);
1423
1424 return 0;
1425 }
0d2cd476
LP
1426 }
1427
1428 /* Check the zone, but only if this transaction is not used
d746bb3e 1429 * for probing or verifying a zone item. */
547973de 1430 if (set_isempty(t->notify_zone_items)) {
d746bb3e 1431
97ebebbc 1432 r = dns_zone_lookup(&t->scope->zone, t->key, dns_scope_ifindex(t->scope), &t->answer, NULL, NULL);
d746bb3e
LP
1433 if (r < 0)
1434 return r;
1435 if (r > 0) {
ae6a4bbf 1436 t->answer_rcode = DNS_RCODE_SUCCESS;
c3bc53e6 1437 t->answer_source = DNS_TRANSACTION_ZONE;
931851e8 1438 t->answer_authenticated = true;
d746bb3e
LP
1439 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
1440 return 0;
1441 }
1442 }
1443
4d926a69
LP
1444 /* Check the cache, but only if this transaction is not used
1445 * for probing or verifying a zone item. */
547973de 1446 if (set_isempty(t->notify_zone_items)) {
2c27fbca 1447
4d926a69
LP
1448 /* Before trying the cache, let's make sure we figured out a
1449 * server to use. Should this cause a change of server this
1450 * might flush the cache. */
5cdb8930 1451 (void) dns_scope_get_dns_server(t->scope);
2c27fbca 1452
4d926a69
LP
1453 /* Let's then prune all outdated entries */
1454 dns_cache_prune(&t->scope->cache);
1455
17c8de63 1456 r = dns_cache_lookup(&t->scope->cache, t->key, t->clamp_ttl, &t->answer_rcode, &t->answer, &t->answer_authenticated);
4d926a69
LP
1457 if (r < 0)
1458 return r;
1459 if (r > 0) {
c3bc53e6 1460 t->answer_source = DNS_TRANSACTION_CACHE;
ae6a4bbf 1461 if (t->answer_rcode == DNS_RCODE_SUCCESS)
4d926a69
LP
1462 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
1463 else
3bbdc31d 1464 dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE);
4d926a69
LP
1465 return 0;
1466 }
ec2c5e43
LP
1467 }
1468
1effe965
DM
1469 return 1;
1470}
1471
0afa57e2
DM
1472static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
1473
1474 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
7778dfff 1475 bool add_known_answers = false;
0afa57e2 1476 DnsTransaction *other;
0d5ee47d
DR
1477 DnsResourceKey *tkey;
1478 _cleanup_set_free_ Set *keys = NULL;
0afa57e2 1479 unsigned qdcount;
0d5ee47d 1480 unsigned nscount = 0;
0afa57e2
DM
1481 usec_t ts;
1482 int r;
1483
1484 assert(t);
1485 assert(t->scope->protocol == DNS_PROTOCOL_MDNS);
1486
e5abebab 1487 /* Discard any previously prepared packet, so we can start over and coalesce again */
0afa57e2
DM
1488 t->sent = dns_packet_unref(t->sent);
1489
1490 r = dns_packet_new_query(&p, t->scope->protocol, 0, false);
1491 if (r < 0)
1492 return r;
1493
58ab31d5 1494 r = dns_packet_append_key(p, t->key, 0, NULL);
0afa57e2
DM
1495 if (r < 0)
1496 return r;
1497
1498 qdcount = 1;
1499
7778dfff
DM
1500 if (dns_key_is_shared(t->key))
1501 add_known_answers = true;
1502
0d5ee47d 1503 if (t->key->type == DNS_TYPE_ANY) {
de7fef4b 1504 r = set_ensure_put(&keys, &dns_resource_key_hash_ops, t->key);
0d5ee47d
DR
1505 if (r < 0)
1506 return r;
1507 }
1508
0afa57e2
DM
1509 /*
1510 * For mDNS, we want to coalesce as many open queries in pending transactions into one single
1511 * query packet on the wire as possible. To achieve that, we iterate through all pending transactions
5238e957 1512 * in our current scope, and see whether their timing constraints allow them to be sent.
0afa57e2
DM
1513 */
1514
1515 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
1516
1517 LIST_FOREACH(transactions_by_scope, other, t->scope->transactions) {
1518
1519 /* Skip ourselves */
1520 if (other == t)
1521 continue;
1522
1523 if (other->state != DNS_TRANSACTION_PENDING)
1524 continue;
1525
1526 if (other->next_attempt_after > ts)
1527 continue;
1528
1529 if (qdcount >= UINT16_MAX)
1530 break;
1531
58ab31d5 1532 r = dns_packet_append_key(p, other->key, 0, NULL);
0afa57e2
DM
1533
1534 /*
1535 * If we can't stuff more questions into the packet, just give up.
1536 * One of the 'other' transactions will fire later and take care of the rest.
1537 */
1538 if (r == -EMSGSIZE)
1539 break;
1540
1541 if (r < 0)
1542 return r;
1543
c842ff24 1544 r = dns_transaction_prepare(other, ts);
0afa57e2
DM
1545 if (r <= 0)
1546 continue;
1547
1548 ts += transaction_get_resend_timeout(other);
1549
1550 r = sd_event_add_time(
1551 other->scope->manager->event,
1552 &other->timeout_event_source,
1553 clock_boottime_or_monotonic(),
1554 ts, 0,
1555 on_transaction_timeout, other);
1556 if (r < 0)
1557 return r;
1558
ff537038 1559 (void) sd_event_source_set_description(other->timeout_event_source, "dns-transaction-timeout");
aa4a9deb 1560
0afa57e2
DM
1561 other->state = DNS_TRANSACTION_PENDING;
1562 other->next_attempt_after = ts;
1563
313cefa1 1564 qdcount++;
7778dfff
DM
1565
1566 if (dns_key_is_shared(other->key))
1567 add_known_answers = true;
0d5ee47d
DR
1568
1569 if (other->key->type == DNS_TYPE_ANY) {
de7fef4b 1570 r = set_ensure_put(&keys, &dns_resource_key_hash_ops, other->key);
0d5ee47d
DR
1571 if (r < 0)
1572 return r;
1573 }
0afa57e2
DM
1574 }
1575
1576 DNS_PACKET_HEADER(p)->qdcount = htobe16(qdcount);
0afa57e2 1577
7778dfff
DM
1578 /* Append known answer section if we're asking for any shared record */
1579 if (add_known_answers) {
1580 r = dns_cache_export_shared_to_packet(&t->scope->cache, p);
1581 if (r < 0)
1582 return r;
1583 }
1584
90e74a66 1585 SET_FOREACH(tkey, keys) {
0d5ee47d
DR
1586 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1587 bool tentative;
1588
1589 r = dns_zone_lookup(&t->scope->zone, tkey, t->scope->link->ifindex, &answer, NULL, &tentative);
1590 if (r < 0)
1591 return r;
1592
1593 r = dns_packet_append_answer(p, answer);
1594 if (r < 0)
1595 return r;
1596
1597 nscount += dns_answer_size(answer);
1598 }
1599 DNS_PACKET_HEADER(p)->nscount = htobe16(nscount);
1600
1cc6c93a 1601 t->sent = TAKE_PTR(p);
0afa57e2
DM
1602
1603 return 0;
1604}
1605
1606static int dns_transaction_make_packet(DnsTransaction *t) {
1607 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1608 int r;
1609
1610 assert(t);
1611
1612 if (t->scope->protocol == DNS_PROTOCOL_MDNS)
1613 return dns_transaction_make_packet_mdns(t);
1614
1615 if (t->sent)
1616 return 0;
1617
b652d4a2 1618 r = dns_packet_new_query(&p, t->scope->protocol, 0, t->scope->dnssec_mode != DNSSEC_NO);
0afa57e2
DM
1619 if (r < 0)
1620 return r;
1621
58ab31d5 1622 r = dns_packet_append_key(p, t->key, 0, NULL);
0afa57e2
DM
1623 if (r < 0)
1624 return r;
1625
1626 DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
1627 DNS_PACKET_HEADER(p)->id = t->id;
1628
1cc6c93a 1629 t->sent = TAKE_PTR(p);
0afa57e2
DM
1630
1631 return 0;
1632}
1633
1effe965
DM
1634int dns_transaction_go(DnsTransaction *t) {
1635 usec_t ts;
1636 int r;
202b76ae 1637 char key_str[DNS_RESOURCE_KEY_STRING_MAX];
1effe965
DM
1638
1639 assert(t);
1640
5278bbfe
LP
1641 /* Returns > 0 if the transaction is now pending, returns 0 if could be processed immediately and has finished
1642 * now. */
1643
1effe965 1644 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
547973de 1645
c842ff24 1646 r = dns_transaction_prepare(t, ts);
1effe965
DM
1647 if (r <= 0)
1648 return r;
1649
202b76ae 1650 log_debug("Transaction %" PRIu16 " for <%s> scope %s on %s/%s.",
a5784c49 1651 t->id,
202b76ae 1652 dns_resource_key_to_string(t->key, key_str, sizeof key_str),
a5784c49 1653 dns_protocol_to_string(t->scope->protocol),
6ff79f76 1654 t->scope->link ? t->scope->link->ifname : "*",
202b76ae 1655 af_to_name_short(t->scope->family));
1effe965 1656
ef7ce6df 1657 if (!t->initial_jitter_scheduled &&
3742095b 1658 IN_SET(t->scope->protocol, DNS_PROTOCOL_LLMNR, DNS_PROTOCOL_MDNS)) {
ea12bcc7 1659 usec_t jitter, accuracy;
6e068472
LP
1660
1661 /* RFC 4795 Section 2.7 suggests all queries should be
1662 * delayed by a random time from 0 to JITTER_INTERVAL. */
1663
ef7ce6df 1664 t->initial_jitter_scheduled = true;
6e068472
LP
1665
1666 random_bytes(&jitter, sizeof(jitter));
ea12bcc7
DM
1667
1668 switch (t->scope->protocol) {
519ef046 1669
ea12bcc7
DM
1670 case DNS_PROTOCOL_LLMNR:
1671 jitter %= LLMNR_JITTER_INTERVAL_USEC;
1672 accuracy = LLMNR_JITTER_INTERVAL_USEC;
1673 break;
519ef046 1674
ea12bcc7
DM
1675 case DNS_PROTOCOL_MDNS:
1676 jitter %= MDNS_JITTER_RANGE_USEC;
1677 jitter += MDNS_JITTER_MIN_USEC;
1678 accuracy = MDNS_JITTER_RANGE_USEC;
1679 break;
1680 default:
1681 assert_not_reached("bad protocol");
1682 }
6e068472
LP
1683
1684 r = sd_event_add_time(
1685 t->scope->manager->event,
1686 &t->timeout_event_source,
1687 clock_boottime_or_monotonic(),
ea12bcc7 1688 ts + jitter, accuracy,
6e068472
LP
1689 on_transaction_timeout, t);
1690 if (r < 0)
1691 return r;
1692
aa4a9deb
LP
1693 (void) sd_event_source_set_description(t->timeout_event_source, "dns-transaction-timeout");
1694
6e068472 1695 t->n_attempts = 0;
a9da14e1 1696 t->next_attempt_after = ts;
6e068472
LP
1697 t->state = DNS_TRANSACTION_PENDING;
1698
ea12bcc7 1699 log_debug("Delaying %s transaction for " USEC_FMT "us.", dns_protocol_to_string(t->scope->protocol), jitter);
6e068472
LP
1700 return 0;
1701 }
1702
ec2c5e43
LP
1703 /* Otherwise, we need to ask the network */
1704 r = dns_transaction_make_packet(t);
ec2c5e43
LP
1705 if (r < 0)
1706 return r;
1707
1708 if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
1c02e7ba
ZJS
1709 (dns_name_endswith(dns_resource_key_name(t->key), "in-addr.arpa") > 0 ||
1710 dns_name_endswith(dns_resource_key_name(t->key), "ip6.arpa") > 0)) {
ec2c5e43
LP
1711
1712 /* RFC 4795, Section 2.4. says reverse lookups shall
1713 * always be made via TCP on LLMNR */
98767d75 1714 r = dns_transaction_emit_tcp(t);
ec2c5e43 1715 } else {
be808ea0
TG
1716 /* Try via UDP, and if that fails due to large size or lack of
1717 * support try via TCP */
49cce12d 1718 r = dns_transaction_emit_udp(t);
29ab0552
LP
1719 if (r == -EMSGSIZE)
1720 log_debug("Sending query via TCP since it is too large.");
dc349f5f 1721 else if (r == -EAGAIN)
5d67a7ae 1722 log_debug("Sending query via TCP since UDP isn't supported.");
4c701096 1723 if (IN_SET(r, -EMSGSIZE, -EAGAIN))
98767d75 1724 r = dns_transaction_emit_tcp(t);
ec2c5e43 1725 }
be808ea0 1726
ec2c5e43
LP
1727 if (r == -ESRCH) {
1728 /* No servers to send this to? */
1729 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
1730 return 0;
91adc4db
LP
1731 }
1732 if (r == -EOPNOTSUPP) {
1733 /* Tried to ask for DNSSEC RRs, on a server that doesn't do DNSSEC */
1734 dns_transaction_complete(t, DNS_TRANSACTION_RR_TYPE_UNSUPPORTED);
1735 return 0;
1736 }
95d2155a 1737 if (t->scope->protocol == DNS_PROTOCOL_LLMNR && ERRNO_IS_DISCONNECT(r)) {
e94968ba 1738 /* On LLMNR, if we cannot connect to a host via TCP when doing reverse lookups. This means we cannot
0791110f
LP
1739 * answer this request with this protocol. */
1740 dns_transaction_complete(t, DNS_TRANSACTION_NOT_FOUND);
1741 return 0;
1742 }
91adc4db 1743 if (r < 0) {
7cc6ed7b
LP
1744 if (t->scope->protocol != DNS_PROTOCOL_DNS)
1745 return r;
13b551ac 1746
ec2c5e43 1747 /* Couldn't send? Try immediately again, with a new server */
519ef046 1748 dns_scope_next_dns_server(t->scope);
ec2c5e43
LP
1749
1750 return dns_transaction_go(t);
1751 }
1752
a9da14e1
DM
1753 ts += transaction_get_resend_timeout(t);
1754
9a015429
LP
1755 r = sd_event_add_time(
1756 t->scope->manager->event,
1757 &t->timeout_event_source,
1758 clock_boottime_or_monotonic(),
a9da14e1 1759 ts, 0,
9a015429 1760 on_transaction_timeout, t);
ec2c5e43
LP
1761 if (r < 0)
1762 return r;
1763
aa4a9deb
LP
1764 (void) sd_event_source_set_description(t->timeout_event_source, "dns-transaction-timeout");
1765
ec2c5e43 1766 t->state = DNS_TRANSACTION_PENDING;
a9da14e1
DM
1767 t->next_attempt_after = ts;
1768
ec2c5e43
LP
1769 return 1;
1770}
1771
f2992dc1
LP
1772static int dns_transaction_find_cyclic(DnsTransaction *t, DnsTransaction *aux) {
1773 DnsTransaction *n;
f2992dc1
LP
1774 int r;
1775
1776 assert(t);
1777 assert(aux);
1778
1779 /* Try to find cyclic dependencies between transaction objects */
1780
1781 if (t == aux)
1782 return 1;
1783
90e74a66 1784 SET_FOREACH(n, aux->dnssec_transactions) {
f2992dc1
LP
1785 r = dns_transaction_find_cyclic(t, n);
1786 if (r != 0)
1787 return r;
1788 }
1789
3eb6aa00 1790 return 0;
f2992dc1
LP
1791}
1792
547973de 1793static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResourceKey *key, DnsTransaction **ret) {
29bd6012 1794 _cleanup_(dns_transaction_gcp) DnsTransaction *aux = NULL;
547973de
LP
1795 int r;
1796
1797 assert(t);
1798 assert(ret);
1799 assert(key);
1800
1801 aux = dns_scope_find_transaction(t->scope, key, true);
1802 if (!aux) {
1803 r = dns_transaction_new(&aux, t->scope, key);
1804 if (r < 0)
1805 return r;
1806 } else {
1807 if (set_contains(t->dnssec_transactions, aux)) {
1808 *ret = aux;
1809 return 0;
1810 }
f2992dc1
LP
1811
1812 r = dns_transaction_find_cyclic(t, aux);
1813 if (r < 0)
1814 return r;
1815 if (r > 0) {
202b76ae
ZJS
1816 char s[DNS_RESOURCE_KEY_STRING_MAX], saux[DNS_RESOURCE_KEY_STRING_MAX];
1817
baaa35ad
ZJS
1818 return log_debug_errno(SYNTHETIC_ERRNO(ELOOP),
1819 "Potential cyclic dependency, refusing to add transaction %" PRIu16 " (%s) as dependency for %" PRIu16 " (%s).",
1820 aux->id,
1821 dns_resource_key_to_string(t->key, s, sizeof s),
1822 t->id,
1823 dns_resource_key_to_string(aux->key, saux, sizeof saux));
f2992dc1 1824 }
547973de
LP
1825 }
1826
35aa04e9
LP
1827 r = set_ensure_allocated(&aux->notify_transactions_done, NULL);
1828 if (r < 0)
29bd6012 1829 return r;
547973de 1830
de7fef4b 1831 r = set_ensure_put(&t->dnssec_transactions, NULL, aux);
547973de 1832 if (r < 0)
a75cb4e2 1833 return r;
547973de 1834
de7fef4b 1835 r = set_ensure_put(&aux->notify_transactions, NULL, t);
547973de
LP
1836 if (r < 0) {
1837 (void) set_remove(t->dnssec_transactions, aux);
29bd6012 1838 return r;
547973de
LP
1839 }
1840
29bd6012 1841 *ret = TAKE_PTR(aux);
547973de 1842 return 1;
547973de
LP
1843}
1844
1845static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *key) {
1846 _cleanup_(dns_answer_unrefp) DnsAnswer *a = NULL;
1847 DnsTransaction *aux;
1848 int r;
1849
1850 assert(t);
1851 assert(key);
1852
1853 /* Try to get the data from the trust anchor */
8e54f5d9 1854 r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, key, &a);
547973de
LP
1855 if (r < 0)
1856 return r;
1857 if (r > 0) {
1858 r = dns_answer_extend(&t->validated_keys, a);
1859 if (r < 0)
1860 return r;
1861
1862 return 0;
1863 }
1864
1865 /* This didn't work, ask for it via the network/cache then. */
1866 r = dns_transaction_add_dnssec_transaction(t, key, &aux);
f2992dc1
LP
1867 if (r == -ELOOP) /* This would result in a cyclic dependency */
1868 return 0;
547973de
LP
1869 if (r < 0)
1870 return r;
1871
1872 if (aux->state == DNS_TRANSACTION_NULL) {
1873 r = dns_transaction_go(aux);
1874 if (r < 0)
1875 return r;
1876 }
1877
f2992dc1 1878 return 1;
547973de
LP
1879}
1880
8a516214
LP
1881static int dns_transaction_negative_trust_anchor_lookup(DnsTransaction *t, const char *name) {
1882 int r;
1883
1884 assert(t);
1885
c629ff58 1886 /* Check whether the specified name is in the NTA
8a516214
LP
1887 * database, either in the global one, or the link-local
1888 * one. */
1889
1890 r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, name);
1891 if (r != 0)
1892 return r;
1893
1894 if (!t->scope->link)
1895 return 0;
1896
1897 return set_contains(t->scope->link->dnssec_negative_trust_anchors, name);
1898}
1899
105e1512
LP
1900static int dns_transaction_has_unsigned_negative_answer(DnsTransaction *t) {
1901 int r;
1902
1903 assert(t);
1904
1905 /* Checks whether the answer is negative, and lacks NSEC/NSEC3
1906 * RRs to prove it */
1907
1908 r = dns_transaction_has_positive_answer(t, NULL);
1909 if (r < 0)
1910 return r;
1911 if (r > 0)
1912 return false;
1913
8e54f5d9
LP
1914 /* Is this key explicitly listed as a negative trust anchor?
1915 * If so, it's nothing we need to care about */
1c02e7ba 1916 r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(t->key));
8e54f5d9
LP
1917 if (r < 0)
1918 return r;
1919 if (r > 0)
1920 return false;
1921
105e1512
LP
1922 /* The answer does not contain any RRs that match to the
1923 * question. If so, let's see if there are any NSEC/NSEC3 RRs
1924 * included. If not, the answer is unsigned. */
1925
1926 r = dns_answer_contains_nsec_or_nsec3(t->answer);
1927 if (r < 0)
1928 return r;
1929 if (r > 0)
1930 return false;
1931
1932 return true;
1933}
1934
1935static int dns_transaction_is_primary_response(DnsTransaction *t, DnsResourceRecord *rr) {
1936 int r;
1937
1938 assert(t);
1939 assert(rr);
1940
1941 /* Check if the specified RR is the "primary" response,
1942 * i.e. either matches the question precisely or is a
4cb94977 1943 * CNAME/DNAME for it. */
105e1512
LP
1944
1945 r = dns_resource_key_match_rr(t->key, rr, NULL);
1946 if (r != 0)
1947 return r;
1948
4cb94977 1949 return dns_resource_key_match_cname_or_dname(t->key, rr->key, NULL);
105e1512
LP
1950}
1951
92ec902a
LP
1952static bool dns_transaction_dnssec_supported(DnsTransaction *t) {
1953 assert(t);
1954
1955 /* Checks whether our transaction's DNS server is assumed to be compatible with DNSSEC. Returns false as soon
1956 * as we changed our mind about a server, and now believe it is incompatible with DNSSEC. */
1957
1958 if (t->scope->protocol != DNS_PROTOCOL_DNS)
1959 return false;
1960
1961 /* If we have picked no server, then we are working from the cache or some other source, and DNSSEC might well
1962 * be supported, hence return true. */
1963 if (!t->server)
1964 return true;
1965
d001e0a3
LP
1966 /* Note that we do not check the feature level actually used for the transaction but instead the feature level
1967 * the server is known to support currently, as the transaction feature level might be lower than what the
1968 * server actually supports, since we might have downgraded this transaction's feature level because we got a
1969 * SERVFAIL earlier and wanted to check whether downgrading fixes it. */
92ec902a
LP
1970
1971 return dns_server_dnssec_supported(t->server);
1972}
1973
1974static bool dns_transaction_dnssec_supported_full(DnsTransaction *t) {
1975 DnsTransaction *dt;
92ec902a
LP
1976
1977 assert(t);
1978
1979 /* Checks whether our transaction our any of the auxiliary transactions couldn't do DNSSEC. */
1980
1981 if (!dns_transaction_dnssec_supported(t))
1982 return false;
1983
90e74a66 1984 SET_FOREACH(dt, t->dnssec_transactions)
92ec902a
LP
1985 if (!dns_transaction_dnssec_supported(dt))
1986 return false;
1987
1988 return true;
1989}
1990
547973de
LP
1991int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
1992 DnsResourceRecord *rr;
105e1512 1993
547973de
LP
1994 int r;
1995
1996 assert(t);
1997
105e1512
LP
1998 /*
1999 * Retrieve all auxiliary RRs for the answer we got, so that
2000 * we can verify signatures or prove that RRs are rightfully
2001 * unsigned. Specifically:
2002 *
2003 * - For RRSIG we get the matching DNSKEY
2004 * - For DNSKEY we get the matching DS
2005 * - For unsigned SOA/NS we get the matching DS
b63fca62 2006 * - For unsigned CNAME/DNAME/DS we get the parent SOA RR
105e1512 2007 * - For other unsigned RRs we get the matching SOA RR
4bbc06cc
LP
2008 * - For SOA/NS queries with no matching response RR, and no NSEC/NSEC3, the DS RR
2009 * - For DS queries with no matching response RRs, and no NSEC/NSEC3, the parent's SOA RR
105e1512
LP
2010 * - For other queries with no matching response RRs, and no NSEC/NSEC3, the SOA RR
2011 */
2012
b652d4a2 2013 if (t->scope->dnssec_mode == DNSSEC_NO)
547973de 2014 return 0;
92ec902a
LP
2015 if (t->answer_source != DNS_TRANSACTION_NETWORK)
2016 return 0; /* We only need to validate stuff from the network */
2017 if (!dns_transaction_dnssec_supported(t))
5238e957 2018 return 0; /* If we can't do DNSSEC anyway there's no point in getting the auxiliary RRs */
b652d4a2 2019
547973de
LP
2020 DNS_ANSWER_FOREACH(rr, t->answer) {
2021
105e1512
LP
2022 if (dns_type_is_pseudo(rr->key->type))
2023 continue;
2024
8e54f5d9 2025 /* If this RR is in the negative trust anchor, we don't need to validate it. */
1c02e7ba 2026 r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(rr->key));
8e54f5d9
LP
2027 if (r < 0)
2028 return r;
2029 if (r > 0)
2030 continue;
2031
547973de
LP
2032 switch (rr->key->type) {
2033
2034 case DNS_TYPE_RRSIG: {
2035 /* For each RRSIG we request the matching DNSKEY */
2036 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *dnskey = NULL;
2037
2038 /* If this RRSIG is about a DNSKEY RR and the
2039 * signer is the same as the owner, then we
2040 * already have the DNSKEY, and we don't have
2041 * to look for more. */
2042 if (rr->rrsig.type_covered == DNS_TYPE_DNSKEY) {
1c02e7ba 2043 r = dns_name_equal(rr->rrsig.signer, dns_resource_key_name(rr->key));
547973de
LP
2044 if (r < 0)
2045 return r;
2046 if (r > 0)
2047 continue;
2048 }
2049
105e1512
LP
2050 /* If the signer is not a parent of our
2051 * original query, then this is about an
2052 * auxiliary RRset, but not anything we asked
2053 * for. In this case we aren't interested,
2054 * because we don't want to request additional
2055 * RRs for stuff we didn't really ask for, and
2056 * also to avoid request loops, where
2057 * additional RRs from one transaction result
5238e957 2058 * in another transaction whose additional RRs
105e1512
LP
2059 * point back to the original transaction, and
2060 * we deadlock. */
1c02e7ba 2061 r = dns_name_endswith(dns_resource_key_name(t->key), rr->rrsig.signer);
547973de
LP
2062 if (r < 0)
2063 return r;
2064 if (r == 0)
2065 continue;
2066
2067 dnskey = dns_resource_key_new(rr->key->class, DNS_TYPE_DNSKEY, rr->rrsig.signer);
2068 if (!dnskey)
2069 return -ENOMEM;
2070
1c02e7ba
ZJS
2071 log_debug("Requesting DNSKEY to validate transaction %" PRIu16" (%s, RRSIG with key tag: %" PRIu16 ").",
2072 t->id, dns_resource_key_name(rr->key), rr->rrsig.key_tag);
547973de
LP
2073 r = dns_transaction_request_dnssec_rr(t, dnskey);
2074 if (r < 0)
2075 return r;
2076 break;
2077 }
2078
2079 case DNS_TYPE_DNSKEY: {
2080 /* For each DNSKEY we request the matching DS */
2081 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
2082
105e1512
LP
2083 /* If the DNSKEY we are looking at is not for
2084 * zone we are interested in, nor any of its
2085 * parents, we aren't interested, and don't
2086 * request it. After all, we don't want to end
2087 * up in request loops, and want to keep
2088 * additional traffic down. */
2089
1c02e7ba 2090 r = dns_name_endswith(dns_resource_key_name(t->key), dns_resource_key_name(rr->key));
105e1512
LP
2091 if (r < 0)
2092 return r;
2093 if (r == 0)
2094 continue;
2095
1c02e7ba 2096 ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, dns_resource_key_name(rr->key));
547973de
LP
2097 if (!ds)
2098 return -ENOMEM;
2099
1c02e7ba
ZJS
2100 log_debug("Requesting DS to validate transaction %" PRIu16" (%s, DNSKEY with key tag: %" PRIu16 ").",
2101 t->id, dns_resource_key_name(rr->key), dnssec_keytag(rr, false));
105e1512
LP
2102 r = dns_transaction_request_dnssec_rr(t, ds);
2103 if (r < 0)
2104 return r;
547973de 2105
105e1512
LP
2106 break;
2107 }
2108
105e1512
LP
2109 case DNS_TYPE_SOA:
2110 case DNS_TYPE_NS: {
2111 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
2112
2113 /* For an unsigned SOA or NS, try to acquire
2114 * the matching DS RR, as we are at a zone cut
2115 * then, and whether a DS exists tells us
2116 * whether the zone is signed. Do so only if
2117 * this RR matches our original question,
2118 * however. */
2119
2120 r = dns_resource_key_match_rr(t->key, rr, NULL);
2121 if (r < 0)
2122 return r;
6993d264
LP
2123 if (r == 0) {
2124 /* Hmm, so this SOA RR doesn't match our original question. In this case, maybe this is
2125 * a negative reply, and we need the a SOA RR's TTL in order to cache a negative entry?
2126 * If so, we need to validate it, too. */
2127
2128 r = dns_answer_match_key(t->answer, t->key, NULL);
2129 if (r < 0)
2130 return r;
2131 if (r > 0) /* positive reply, we won't need the SOA and hence don't need to validate
2132 * it. */
2133 continue;
d5acaa51
LP
2134
2135 /* Only bother with this if the SOA/NS RR we are looking at is actually a parent of
2136 * what we are looking for, otherwise there's no value in it for us. */
2137 r = dns_name_endswith(dns_resource_key_name(t->key), dns_resource_key_name(rr->key));
2138 if (r < 0)
2139 return r;
2140 if (r == 0)
2141 continue;
6993d264 2142 }
105e1512
LP
2143
2144 r = dnssec_has_rrsig(t->answer, rr->key);
2145 if (r < 0)
2146 return r;
2147 if (r > 0)
2148 continue;
2149
1c02e7ba 2150 ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, dns_resource_key_name(rr->key));
105e1512
LP
2151 if (!ds)
2152 return -ENOMEM;
2153
1c02e7ba
ZJS
2154 log_debug("Requesting DS to validate transaction %" PRIu16 " (%s, unsigned SOA/NS RRset).",
2155 t->id, dns_resource_key_name(rr->key));
547973de
LP
2156 r = dns_transaction_request_dnssec_rr(t, ds);
2157 if (r < 0)
2158 return r;
2159
2160 break;
105e1512
LP
2161 }
2162
b63fca62 2163 case DNS_TYPE_DS:
105e1512
LP
2164 case DNS_TYPE_CNAME:
2165 case DNS_TYPE_DNAME: {
2166 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
2167 const char *name;
2168
2169 /* CNAMEs and DNAMEs cannot be located at a
2170 * zone apex, hence ask for the parent SOA for
2171 * unsigned CNAME/DNAME RRs, maybe that's the
2172 * apex. But do all that only if this is
2173 * actually a response to our original
b63fca62
LP
2174 * question.
2175 *
2176 * Similar for DS RRs, which are signed when
2177 * the parent SOA is signed. */
105e1512
LP
2178
2179 r = dns_transaction_is_primary_response(t, rr);
2180 if (r < 0)
2181 return r;
2182 if (r == 0)
2183 continue;
2184
2185 r = dnssec_has_rrsig(t->answer, rr->key);
2186 if (r < 0)
2187 return r;
2188 if (r > 0)
2189 continue;
2190
43e6779a
LP
2191 r = dns_answer_has_dname_for_cname(t->answer, rr);
2192 if (r < 0)
2193 return r;
2194 if (r > 0)
2195 continue;
2196
1c02e7ba 2197 name = dns_resource_key_name(rr->key);
105e1512
LP
2198 r = dns_name_parent(&name);
2199 if (r < 0)
2200 return r;
2201 if (r == 0)
2202 continue;
2203
2204 soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, name);
2205 if (!soa)
2206 return -ENOMEM;
2207
1c02e7ba
ZJS
2208 log_debug("Requesting parent SOA to validate transaction %" PRIu16 " (%s, unsigned CNAME/DNAME/DS RRset).",
2209 t->id, dns_resource_key_name(rr->key));
105e1512
LP
2210 r = dns_transaction_request_dnssec_rr(t, soa);
2211 if (r < 0)
2212 return r;
2213
2214 break;
2215 }
2216
2217 default: {
2218 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
2219
b63fca62
LP
2220 /* For other unsigned RRsets (including
2221 * NSEC/NSEC3!), look for proof the zone is
2222 * unsigned, by requesting the SOA RR of the
2223 * zone. However, do so only if they are
2224 * directly relevant to our original
105e1512
LP
2225 * question. */
2226
2227 r = dns_transaction_is_primary_response(t, rr);
2228 if (r < 0)
2229 return r;
2230 if (r == 0)
2231 continue;
2232
2233 r = dnssec_has_rrsig(t->answer, rr->key);
2234 if (r < 0)
2235 return r;
2236 if (r > 0)
2237 continue;
2238
1c02e7ba 2239 soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, dns_resource_key_name(rr->key));
105e1512
LP
2240 if (!soa)
2241 return -ENOMEM;
2242
1c02e7ba
ZJS
2243 log_debug("Requesting SOA to validate transaction %" PRIu16 " (%s, unsigned non-SOA/NS RRset <%s>).",
2244 t->id, dns_resource_key_name(rr->key), dns_resource_record_to_string(rr));
105e1512
LP
2245 r = dns_transaction_request_dnssec_rr(t, soa);
2246 if (r < 0)
2247 return r;
2248 break;
547973de
LP
2249 }}
2250 }
2251
105e1512
LP
2252 /* Above, we requested everything necessary to validate what
2253 * we got. Now, let's request what we need to validate what we
2254 * didn't get... */
2255
2256 r = dns_transaction_has_unsigned_negative_answer(t);
2257 if (r < 0)
2258 return r;
2259 if (r > 0) {
2260 const char *name;
4bbc06cc 2261 uint16_t type = 0;
105e1512 2262
1c02e7ba 2263 name = dns_resource_key_name(t->key);
105e1512 2264
4bbc06cc
LP
2265 /* If this was a SOA or NS request, then check if there's a DS RR for the same domain. Note that this
2266 * could also be used as indication that we are not at a zone apex, but in real world setups there are
2267 * too many broken DNS servers (Hello, incapdns.net!) where non-terminal zones return NXDOMAIN even
2268 * though they have further children. If this was a DS request, then it's signed when the parent zone
2269 * is signed, hence ask the parent SOA in that case. If this was any other RR then ask for the SOA RR,
2270 * to see if that is signed. */
105e1512 2271
4bbc06cc 2272 if (t->key->type == DNS_TYPE_DS) {
105e1512 2273 r = dns_name_parent(&name);
4bbc06cc
LP
2274 if (r > 0) {
2275 type = DNS_TYPE_SOA;
6d72da2f
LP
2276 log_debug("Requesting parent SOA (→ %s) to validate transaction %" PRIu16 " (%s, unsigned empty DS response).",
2277 name, t->id, dns_resource_key_name(t->key));
4bbc06cc 2278 } else
105e1512 2279 name = NULL;
4bbc06cc
LP
2280
2281 } else if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS)) {
2282
2283 type = DNS_TYPE_DS;
6d72da2f
LP
2284 log_debug("Requesting DS (→ %s) to validate transaction %" PRIu16 " (%s, unsigned empty SOA/NS response).",
2285 name, t->id, name);
4bbc06cc
LP
2286
2287 } else {
2288 type = DNS_TYPE_SOA;
6d72da2f
LP
2289 log_debug("Requesting SOA (→ %s) to validate transaction %" PRIu16 " (%s, unsigned empty non-SOA/NS/DS response).",
2290 name, t->id, name);
4bbc06cc 2291 }
105e1512
LP
2292
2293 if (name) {
2294 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
2295
4bbc06cc 2296 soa = dns_resource_key_new(t->key->class, type, name);
105e1512
LP
2297 if (!soa)
2298 return -ENOMEM;
2299
2300 r = dns_transaction_request_dnssec_rr(t, soa);
2301 if (r < 0)
2302 return r;
2303 }
2304 }
2305
2306 return dns_transaction_dnssec_is_live(t);
547973de
LP
2307}
2308
2309void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source) {
547973de 2310 assert(t);
547973de
LP
2311 assert(source);
2312
942eb2e7
LP
2313 /* Invoked whenever any of our auxiliary DNSSEC transactions completed its work. If the state is still PENDING,
2314 we are still in the loop that adds further DNSSEC transactions, hence don't check if we are ready yet. If
2315 the state is VALIDATING however, we should check if we are complete now. */
105e1512 2316
942eb2e7
LP
2317 if (t->state == DNS_TRANSACTION_VALIDATING)
2318 dns_transaction_process_dnssec(t);
547973de
LP
2319}
2320
105e1512
LP
2321static int dns_transaction_validate_dnskey_by_ds(DnsTransaction *t) {
2322 DnsResourceRecord *rr;
2323 int ifindex, r;
2324
2325 assert(t);
2326
2327 /* Add all DNSKEY RRs from the answer that are validated by DS
2328 * RRs from the list of validated keys to the list of
2329 * validated keys. */
2330
2331 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, t->answer) {
2332
96bb7673 2333 r = dnssec_verify_dnskey_by_ds_search(rr, t->validated_keys);
105e1512
LP
2334 if (r < 0)
2335 return r;
2336 if (r == 0)
2337 continue;
2338
2339 /* If so, the DNSKEY is validated too. */
2340 r = dns_answer_add_extend(&t->validated_keys, rr, ifindex, DNS_ANSWER_AUTHENTICATED);
2341 if (r < 0)
2342 return r;
2343 }
2344
2345 return 0;
2346}
2347
2348static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *rr) {
56352fe9
LP
2349 int r;
2350
2351 assert(t);
2352 assert(rr);
2353
105e1512
LP
2354 /* Checks if the RR we are looking for must be signed with an
2355 * RRSIG. This is used for positive responses. */
24a5b982 2356
b652d4a2 2357 if (t->scope->dnssec_mode == DNSSEC_NO)
105e1512 2358 return false;
56352fe9 2359
105e1512
LP
2360 if (dns_type_is_pseudo(rr->key->type))
2361 return -EINVAL;
56352fe9 2362
1c02e7ba 2363 r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(rr->key));
8e54f5d9
LP
2364 if (r < 0)
2365 return r;
2366 if (r > 0)
2367 return false;
2368
105e1512 2369 switch (rr->key->type) {
56352fe9 2370
105e1512
LP
2371 case DNS_TYPE_RRSIG:
2372 /* RRSIGs are the signatures themselves, they need no signing. */
2373 return false;
2374
2375 case DNS_TYPE_SOA:
2376 case DNS_TYPE_NS: {
2377 DnsTransaction *dt;
105e1512 2378
b63fca62 2379 /* For SOA or NS RRs we look for a matching DS transaction */
105e1512 2380
90e74a66 2381 SET_FOREACH(dt, t->dnssec_transactions) {
105e1512
LP
2382
2383 if (dt->key->class != rr->key->class)
2384 continue;
2385 if (dt->key->type != DNS_TYPE_DS)
2386 continue;
2387
1c02e7ba 2388 r = dns_name_equal(dns_resource_key_name(dt->key), dns_resource_key_name(rr->key));
105e1512
LP
2389 if (r < 0)
2390 return r;
2391 if (r == 0)
2392 continue;
2393
2394 /* We found a DS transactions for the SOA/NS
2395 * RRs we are looking at. If it discovered signed DS
2396 * RRs, then we need to be signed, too. */
2397
097a2517
TA
2398 if (!dt->answer_authenticated)
2399 return false;
105e1512 2400
097a2517 2401 return dns_answer_match_key(dt->answer, dt->key, NULL);
105e1512
LP
2402 }
2403
2404 /* We found nothing that proves this is safe to leave
2405 * this unauthenticated, hence ask inist on
2406 * authentication. */
2407 return true;
2408 }
2409
b63fca62 2410 case DNS_TYPE_DS:
105e1512
LP
2411 case DNS_TYPE_CNAME:
2412 case DNS_TYPE_DNAME: {
2413 const char *parent = NULL;
2414 DnsTransaction *dt;
105e1512 2415
b63fca62
LP
2416 /*
2417 * CNAME/DNAME RRs cannot be located at a zone apex, hence look directly for the parent SOA.
2418 *
2419 * DS RRs are signed if the parent is signed, hence also look at the parent SOA
2420 */
105e1512 2421
90e74a66 2422 SET_FOREACH(dt, t->dnssec_transactions) {
105e1512
LP
2423
2424 if (dt->key->class != rr->key->class)
2425 continue;
2426 if (dt->key->type != DNS_TYPE_SOA)
2427 continue;
2428
2429 if (!parent) {
1c02e7ba 2430 parent = dns_resource_key_name(rr->key);
105e1512
LP
2431 r = dns_name_parent(&parent);
2432 if (r < 0)
2433 return r;
2434 if (r == 0) {
b63fca62
LP
2435 if (rr->key->type == DNS_TYPE_DS)
2436 return true;
2437
105e1512 2438 /* A CNAME/DNAME without a parent? That's sooo weird. */
baaa35ad
ZJS
2439 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
2440 "Transaction %" PRIu16 " claims CNAME/DNAME at root. Refusing.", t->id);
105e1512
LP
2441 }
2442 }
2443
1c02e7ba 2444 r = dns_name_equal(dns_resource_key_name(dt->key), parent);
105e1512
LP
2445 if (r < 0)
2446 return r;
2447 if (r == 0)
2448 continue;
2449
2450 return t->answer_authenticated;
2451 }
2452
2453 return true;
2454 }
2455
2456 default: {
2457 DnsTransaction *dt;
105e1512 2458
b63fca62 2459 /* Any other kind of RR (including DNSKEY/NSEC/NSEC3). Let's see if our SOA lookup was authenticated */
105e1512 2460
90e74a66 2461 SET_FOREACH(dt, t->dnssec_transactions) {
105e1512
LP
2462
2463 if (dt->key->class != rr->key->class)
2464 continue;
2465 if (dt->key->type != DNS_TYPE_SOA)
2466 continue;
2467
1c02e7ba 2468 r = dns_name_equal(dns_resource_key_name(dt->key), dns_resource_key_name(rr->key));
105e1512
LP
2469 if (r < 0)
2470 return r;
2471 if (r == 0)
2472 continue;
2473
2474 /* We found the transaction that was supposed to find
2475 * the SOA RR for us. It was successful, but found no
2476 * RR for us. This means we are not at a zone cut. In
2477 * this case, we require authentication if the SOA
2478 * lookup was authenticated too. */
2479 return t->answer_authenticated;
2480 }
2481
2482 return true;
2483 }}
56352fe9
LP
2484}
2485
d33b6cf3
LP
2486static int dns_transaction_in_private_tld(DnsTransaction *t, const DnsResourceKey *key) {
2487 DnsTransaction *dt;
2488 const char *tld;
d33b6cf3
LP
2489 int r;
2490
2491 /* If DNSSEC downgrade mode is on, checks whether the
2492 * specified RR is one level below a TLD we have proven not to
2493 * exist. In such a case we assume that this is a private
2494 * domain, and permit it.
2495 *
2496 * This detects cases like the Fritz!Box router networks. Each
2497 * Fritz!Box router serves a private "fritz.box" zone, in the
2498 * non-existing TLD "box". Requests for the "fritz.box" domain
2499 * are served by the router itself, while requests for the
2500 * "box" domain will result in NXDOMAIN.
2501 *
2502 * Note that this logic is unable to detect cases where a
2503 * router serves a private DNS zone directly under
2504 * non-existing TLD. In such a case we cannot detect whether
2505 * the TLD is supposed to exist or not, as all requests we
2506 * make for it will be answered by the router's zone, and not
2507 * by the root zone. */
2508
2509 assert(t);
2510
2511 if (t->scope->dnssec_mode != DNSSEC_ALLOW_DOWNGRADE)
2512 return false; /* In strict DNSSEC mode what doesn't exist, doesn't exist */
2513
1c02e7ba 2514 tld = dns_resource_key_name(key);
d33b6cf3
LP
2515 r = dns_name_parent(&tld);
2516 if (r < 0)
2517 return r;
2518 if (r == 0)
2519 return false; /* Already the root domain */
2520
2521 if (!dns_name_is_single_label(tld))
2522 return false;
2523
90e74a66 2524 SET_FOREACH(dt, t->dnssec_transactions) {
d33b6cf3
LP
2525
2526 if (dt->key->class != key->class)
2527 continue;
2528
1c02e7ba 2529 r = dns_name_equal(dns_resource_key_name(dt->key), tld);
d33b6cf3
LP
2530 if (r < 0)
2531 return r;
2532 if (r == 0)
2533 continue;
2534
2535 /* We found an auxiliary lookup we did for the TLD. If
2536 * that returned with NXDOMAIN, we know the TLD didn't
2537 * exist, and hence this might be a private zone. */
2538
2539 return dt->answer_rcode == DNS_RCODE_NXDOMAIN;
2540 }
2541
2542 return false;
2543}
2544
105e1512 2545static int dns_transaction_requires_nsec(DnsTransaction *t) {
4bbc06cc 2546 char key_str[DNS_RESOURCE_KEY_STRING_MAX];
105e1512
LP
2547 DnsTransaction *dt;
2548 const char *name;
4bbc06cc 2549 uint16_t type = 0;
105e1512 2550 int r;
56352fe9
LP
2551
2552 assert(t);
2553
105e1512
LP
2554 /* Checks if we need to insist on NSEC/NSEC3 RRs for proving
2555 * this negative reply */
56352fe9 2556
b652d4a2 2557 if (t->scope->dnssec_mode == DNSSEC_NO)
105e1512 2558 return false;
56352fe9 2559
105e1512
LP
2560 if (dns_type_is_pseudo(t->key->type))
2561 return -EINVAL;
2562
1c02e7ba 2563 r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(t->key));
8e54f5d9
LP
2564 if (r < 0)
2565 return r;
2566 if (r > 0)
2567 return false;
2568
d33b6cf3
LP
2569 r = dns_transaction_in_private_tld(t, t->key);
2570 if (r < 0)
2571 return r;
2572 if (r > 0) {
2573 /* The lookup is from a TLD that is proven not to
2574 * exist, and we are in downgrade mode, hence ignore
13e785f7 2575 * that fact that we didn't get any NSEC RRs. */
d33b6cf3 2576
202b76ae
ZJS
2577 log_info("Detected a negative query %s in a private DNS zone, permitting unsigned response.",
2578 dns_resource_key_to_string(t->key, key_str, sizeof key_str));
d33b6cf3
LP
2579 return false;
2580 }
2581
1c02e7ba 2582 name = dns_resource_key_name(t->key);
105e1512 2583
4bbc06cc 2584 if (t->key->type == DNS_TYPE_DS) {
105e1512 2585
4bbc06cc
LP
2586 /* We got a negative reply for this DS lookup? DS RRs are signed when their parent zone is signed,
2587 * hence check the parent SOA in this case. */
105e1512
LP
2588
2589 r = dns_name_parent(&name);
56352fe9
LP
2590 if (r < 0)
2591 return r;
2592 if (r == 0)
105e1512 2593 return true;
4bbc06cc
LP
2594
2595 type = DNS_TYPE_SOA;
2596
2597 } else if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS))
2598 /* We got a negative reply for this SOA/NS lookup? If so, check if there's a DS RR for this */
2599 type = DNS_TYPE_DS;
2600 else
2601 /* For all other negative replies, check for the SOA lookup */
2602 type = DNS_TYPE_SOA;
105e1512
LP
2603
2604 /* For all other RRs we check the SOA on the same level to see
2605 * if it's signed. */
2606
90e74a66 2607 SET_FOREACH(dt, t->dnssec_transactions) {
105e1512
LP
2608
2609 if (dt->key->class != t->key->class)
2610 continue;
4bbc06cc 2611 if (dt->key->type != type)
56352fe9
LP
2612 continue;
2613
1c02e7ba 2614 r = dns_name_equal(dns_resource_key_name(dt->key), name);
56352fe9
LP
2615 if (r < 0)
2616 return r;
105e1512
LP
2617 if (r == 0)
2618 continue;
2619
2620 return dt->answer_authenticated;
56352fe9
LP
2621 }
2622
105e1512
LP
2623 /* If in doubt, require NSEC/NSEC3 */
2624 return true;
56352fe9
LP
2625}
2626
94aa7071
LP
2627static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRecord *rr) {
2628 DnsResourceRecord *rrsig;
2629 bool found = false;
2630 int r;
2631
2632 /* Checks whether any of the DNSKEYs used for the RRSIGs for
2633 * the specified RRset is authenticated (i.e. has a matching
2634 * DS RR). */
2635
1c02e7ba 2636 r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(rr->key));
8e54f5d9
LP
2637 if (r < 0)
2638 return r;
2639 if (r > 0)
2640 return false;
2641
94aa7071
LP
2642 DNS_ANSWER_FOREACH(rrsig, t->answer) {
2643 DnsTransaction *dt;
94aa7071
LP
2644
2645 r = dnssec_key_match_rrsig(rr->key, rrsig);
2646 if (r < 0)
2647 return r;
2648 if (r == 0)
2649 continue;
2650
90e74a66 2651 SET_FOREACH(dt, t->dnssec_transactions) {
94aa7071
LP
2652
2653 if (dt->key->class != rr->key->class)
2654 continue;
2655
2656 if (dt->key->type == DNS_TYPE_DNSKEY) {
2657
1c02e7ba 2658 r = dns_name_equal(dns_resource_key_name(dt->key), rrsig->rrsig.signer);
94aa7071
LP
2659 if (r < 0)
2660 return r;
2661 if (r == 0)
2662 continue;
2663
2664 /* OK, we found an auxiliary DNSKEY
2665 * lookup. If that lookup is
2666 * authenticated, report this. */
2667
2668 if (dt->answer_authenticated)
2669 return true;
2670
2671 found = true;
2672
2673 } else if (dt->key->type == DNS_TYPE_DS) {
2674
1c02e7ba 2675 r = dns_name_equal(dns_resource_key_name(dt->key), rrsig->rrsig.signer);
94aa7071
LP
2676 if (r < 0)
2677 return r;
2678 if (r == 0)
2679 continue;
2680
2681 /* OK, we found an auxiliary DS
2682 * lookup. If that lookup is
2683 * authenticated and non-zero, we
2684 * won! */
2685
2686 if (!dt->answer_authenticated)
2687 return false;
2688
2689 return dns_answer_match_key(dt->answer, dt->key, NULL);
2690 }
2691 }
2692 }
2693
2694 return found ? false : -ENXIO;
2695}
2696
b652d4a2
LP
2697static int dns_transaction_known_signed(DnsTransaction *t, DnsResourceRecord *rr) {
2698 assert(t);
2699 assert(rr);
2700
2701 /* We know that the root domain is signed, hence if it appears
2702 * not to be signed, there's a problem with the DNS server */
2703
2704 return rr->key->class == DNS_CLASS_IN &&
1c02e7ba 2705 dns_name_is_root(dns_resource_key_name(rr->key));
b652d4a2
LP
2706}
2707
0f87f3e8
LP
2708static int dns_transaction_check_revoked_trust_anchors(DnsTransaction *t) {
2709 DnsResourceRecord *rr;
2710 int r;
2711
2712 assert(t);
2713
2714 /* Maybe warn the user that we encountered a revoked DNSKEY
2715 * for a key from our trust anchor. Note that we don't care
2716 * whether the DNSKEY can be authenticated or not. It's
2717 * sufficient if it is self-signed. */
2718
2719 DNS_ANSWER_FOREACH(rr, t->answer) {
d424da2a 2720 r = dns_trust_anchor_check_revoked(&t->scope->manager->trust_anchor, rr, t->answer);
0f87f3e8
LP
2721 if (r < 0)
2722 return r;
2723 }
2724
2725 return 0;
2726}
2727
c9c72065
LP
2728static int dns_transaction_invalidate_revoked_keys(DnsTransaction *t) {
2729 bool changed;
2730 int r;
2731
2732 assert(t);
2733
2734 /* Removes all DNSKEY/DS objects from t->validated_keys that
2735 * our trust anchors database considers revoked. */
2736
2737 do {
2738 DnsResourceRecord *rr;
2739
2740 changed = false;
2741
2742 DNS_ANSWER_FOREACH(rr, t->validated_keys) {
2743 r = dns_trust_anchor_is_revoked(&t->scope->manager->trust_anchor, rr);
2744 if (r < 0)
2745 return r;
2746 if (r > 0) {
2747 r = dns_answer_remove_by_rr(&t->validated_keys, rr);
2748 if (r < 0)
2749 return r;
2750
2751 assert(r > 0);
2752 changed = true;
2753 break;
2754 }
2755 }
2756 } while (changed);
2757
2758 return 0;
2759}
2760
942eb2e7
LP
2761static int dns_transaction_copy_validated(DnsTransaction *t) {
2762 DnsTransaction *dt;
942eb2e7
LP
2763 int r;
2764
2765 assert(t);
2766
2767 /* Copy all validated RRs from the auxiliary DNSSEC transactions into our set of validated RRs */
2768
90e74a66 2769 SET_FOREACH(dt, t->dnssec_transactions) {
942eb2e7
LP
2770
2771 if (DNS_TRANSACTION_IS_LIVE(dt->state))
2772 continue;
2773
2774 if (!dt->answer_authenticated)
2775 continue;
2776
2777 r = dns_answer_extend(&t->validated_keys, dt->answer);
2778 if (r < 0)
2779 return r;
2780 }
2781
2782 return 0;
2783}
2784
c690b20a
ZJS
2785typedef enum {
2786 DNSSEC_PHASE_DNSKEY, /* Phase #1, only validate DNSKEYs */
2787 DNSSEC_PHASE_NSEC, /* Phase #2, only validate NSEC+NSEC3 */
2788 DNSSEC_PHASE_ALL, /* Phase #3, validate everything else */
2789} Phase;
2790
2791static int dnssec_validate_records(
2792 DnsTransaction *t,
2793 Phase phase,
2794 bool *have_nsec,
2795 DnsAnswer **validated) {
2796
547973de 2797 DnsResourceRecord *rr;
56352fe9 2798 int r;
547973de 2799
c690b20a 2800 /* Returns negative on error, 0 if validation failed, 1 to restart validation, 2 when finished. */
547973de 2801
c690b20a
ZJS
2802 DNS_ANSWER_FOREACH(rr, t->answer) {
2803 DnsResourceRecord *rrsig = NULL;
2804 DnssecResult result;
547973de 2805
c690b20a
ZJS
2806 switch (rr->key->type) {
2807 case DNS_TYPE_RRSIG:
2808 continue;
547973de 2809
c690b20a
ZJS
2810 case DNS_TYPE_DNSKEY:
2811 /* We validate DNSKEYs only in the DNSKEY and ALL phases */
2812 if (phase == DNSSEC_PHASE_NSEC)
2813 continue;
2814 break;
547973de 2815
c690b20a
ZJS
2816 case DNS_TYPE_NSEC:
2817 case DNS_TYPE_NSEC3:
2818 *have_nsec = true;
547973de 2819
c690b20a
ZJS
2820 /* We validate NSEC/NSEC3 only in the NSEC and ALL phases */
2821 if (phase == DNSSEC_PHASE_DNSKEY)
2822 continue;
2823 break;
105e1512 2824
c690b20a
ZJS
2825 default:
2826 /* We validate all other RRs only in the ALL phases */
2827 if (phase != DNSSEC_PHASE_ALL)
2828 continue;
2829 }
b652d4a2 2830
c690b20a
ZJS
2831 r = dnssec_verify_rrset_search(t->answer, rr->key, t->validated_keys, USEC_INFINITY, &result, &rrsig);
2832 if (r < 0)
2833 return r;
547973de 2834
c690b20a 2835 log_debug("Looking at %s: %s", strna(dns_resource_record_to_string(rr)), dnssec_result_to_string(result));
0f87f3e8 2836
c690b20a 2837 if (result == DNSSEC_VALIDATED) {
942eb2e7 2838
c690b20a
ZJS
2839 if (rr->key->type == DNS_TYPE_DNSKEY) {
2840 /* If we just validated a DNSKEY RRset, then let's add these keys to
2841 * the set of validated keys for this transaction. */
547973de 2842
c690b20a
ZJS
2843 r = dns_answer_copy_by_key(&t->validated_keys, t->answer, rr->key, DNS_ANSWER_AUTHENTICATED);
2844 if (r < 0)
2845 return r;
c9c72065 2846
c690b20a
ZJS
2847 /* Some of the DNSKEYs we just added might already have been revoked,
2848 * remove them again in that case. */
2849 r = dns_transaction_invalidate_revoked_keys(t);
2850 if (r < 0)
2851 return r;
2852 }
547973de 2853
c690b20a
ZJS
2854 /* Add the validated RRset to the new list of validated
2855 * RRsets, and remove it from the unvalidated RRsets.
2856 * We mark the RRset as authenticated and cacheable. */
2857 r = dns_answer_move_by_key(validated, &t->answer, rr->key, DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE);
2858 if (r < 0)
2859 return r;
547973de 2860
c690b20a 2861 manager_dnssec_verdict(t->scope->manager, DNSSEC_SECURE, rr->key);
0c7bff0a 2862
c690b20a
ZJS
2863 /* Exit the loop, we dropped something from the answer, start from the beginning */
2864 return 1;
2865 }
547973de 2866
c690b20a
ZJS
2867 /* If we haven't read all DNSKEYs yet a negative result of the validation is irrelevant, as
2868 * there might be more DNSKEYs coming. Similar, if we haven't read all NSEC/NSEC3 RRs yet,
2869 * we cannot do positive wildcard proofs yet, as those require the NSEC/NSEC3 RRs. */
2870 if (phase != DNSSEC_PHASE_ALL)
2871 continue;
0c7bff0a 2872
c690b20a
ZJS
2873 if (result == DNSSEC_VALIDATED_WILDCARD) {
2874 bool authenticated = false;
2875 const char *source;
0c7bff0a 2876
c690b20a 2877 /* This RRset validated, but as a wildcard. This means we need
13e785f7 2878 * to prove via NSEC/NSEC3 that no matching non-wildcard RR exists. */
0c7bff0a 2879
c690b20a
ZJS
2880 /* First step, determine the source of synthesis */
2881 r = dns_resource_record_source(rrsig, &source);
2882 if (r < 0)
2883 return r;
0c7bff0a 2884
c690b20a 2885 r = dnssec_test_positive_wildcard(*validated,
1c02e7ba 2886 dns_resource_key_name(rr->key),
c690b20a
ZJS
2887 source,
2888 rrsig->rrsig.signer,
2889 &authenticated);
0c7bff0a 2890
c690b20a
ZJS
2891 /* Unless the NSEC proof showed that the key really doesn't exist something is off. */
2892 if (r == 0)
2893 result = DNSSEC_INVALID;
2894 else {
2895 r = dns_answer_move_by_key(validated, &t->answer, rr->key,
2896 authenticated ? (DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE) : 0);
2897 if (r < 0)
2898 return r;
2899
2900 manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, rr->key);
2901
2902 /* Exit the loop, we dropped something from the answer, start from the beginning */
2903 return 1;
0c7bff0a 2904 }
c690b20a 2905 }
0c7bff0a 2906
c690b20a
ZJS
2907 if (result == DNSSEC_NO_SIGNATURE) {
2908 r = dns_transaction_requires_rrsig(t, rr);
547973de
LP
2909 if (r < 0)
2910 return r;
c690b20a
ZJS
2911 if (r == 0) {
2912 /* Data does not require signing. In that case, just copy it over,
13e785f7 2913 * but remember that this is by no means authenticated. */
c690b20a
ZJS
2914 r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0);
2915 if (r < 0)
2916 return r;
2917
2918 manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key);
2919 return 1;
2920 }
547973de 2921
c690b20a
ZJS
2922 r = dns_transaction_known_signed(t, rr);
2923 if (r < 0)
2924 return r;
2925 if (r > 0) {
2926 /* This is an RR we know has to be signed. If it isn't this means
2927 * the server is not attaching RRSIGs, hence complain. */
547973de 2928
c690b20a 2929 dns_server_packet_rrsig_missing(t->server, t->current_feature_level);
547973de 2930
c690b20a 2931 if (t->scope->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE) {
547973de 2932
c690b20a 2933 /* Downgrading is OK? If so, just consider the information unsigned */
c9c72065 2934
c690b20a 2935 r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0);
c9c72065
LP
2936 if (r < 0)
2937 return r;
547973de 2938
c690b20a
ZJS
2939 manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key);
2940 return 1;
2941 }
a150ff5e 2942
c690b20a
ZJS
2943 /* Otherwise, fail */
2944 t->answer_dnssec_result = DNSSEC_INCOMPATIBLE_SERVER;
2945 return 0;
f3cf586d 2946 }
547973de 2947
c690b20a
ZJS
2948 r = dns_transaction_in_private_tld(t, rr->key);
2949 if (r < 0)
2950 return r;
2951 if (r > 0) {
202b76ae 2952 char s[DNS_RESOURCE_KEY_STRING_MAX];
b652d4a2 2953
c690b20a
ZJS
2954 /* The data is from a TLD that is proven not to exist, and we are in downgrade
2955 * mode, hence ignore the fact that this was not signed. */
0c7bff0a 2956
202b76ae
ZJS
2957 log_info("Detected RRset %s is in a private DNS zone, permitting unsigned RRs.",
2958 dns_resource_key_to_string(rr->key, s, sizeof s));
0c7bff0a 2959
c690b20a 2960 r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0);
0c7bff0a
LP
2961 if (r < 0)
2962 return r;
0c7bff0a 2963
c690b20a
ZJS
2964 manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key);
2965 return 1;
2966 }
2967 }
0c7bff0a 2968
c690b20a
ZJS
2969 if (IN_SET(result,
2970 DNSSEC_MISSING_KEY,
2971 DNSSEC_SIGNATURE_EXPIRED,
2972 DNSSEC_UNSUPPORTED_ALGORITHM)) {
0c7bff0a 2973
c690b20a
ZJS
2974 r = dns_transaction_dnskey_authenticated(t, rr);
2975 if (r < 0 && r != -ENXIO)
2976 return r;
2977 if (r == 0) {
2978 /* The DNSKEY transaction was not authenticated, this means there's
2979 * no DS for this, which means it's OK if no keys are found for this signature. */
0c7bff0a 2980
c690b20a 2981 r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0);
f3cf586d
LP
2982 if (r < 0)
2983 return r;
b652d4a2 2984
c690b20a
ZJS
2985 manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key);
2986 return 1;
2987 }
2988 }
b652d4a2 2989
c690b20a
ZJS
2990 r = dns_transaction_is_primary_response(t, rr);
2991 if (r < 0)
2992 return r;
2993 if (r > 0) {
2994 /* Look for a matching DNAME for this CNAME */
2995 r = dns_answer_has_dname_for_cname(t->answer, rr);
2996 if (r < 0)
2997 return r;
2998 if (r == 0) {
2999 /* Also look among the stuff we already validated */
3000 r = dns_answer_has_dname_for_cname(*validated, rr);
f3cf586d
LP
3001 if (r < 0)
3002 return r;
c690b20a 3003 }
d33b6cf3 3004
c690b20a
ZJS
3005 if (r == 0) {
3006 if (IN_SET(result,
3007 DNSSEC_INVALID,
3008 DNSSEC_SIGNATURE_EXPIRED,
3009 DNSSEC_NO_SIGNATURE))
3010 manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, rr->key);
3011 else /* DNSSEC_MISSING_KEY or DNSSEC_UNSUPPORTED_ALGORITHM */
3012 manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, rr->key);
3013
3014 /* This is a primary response to our question, and it failed validation.
3015 * That's fatal. */
3016 t->answer_dnssec_result = result;
3017 return 0;
3018 }
d33b6cf3 3019
c690b20a
ZJS
3020 /* This is a primary response, but we do have a DNAME RR
3021 * in the RR that can replay this CNAME, hence rely on
3022 * that, and we can remove the CNAME in favour of it. */
3023 }
d33b6cf3 3024
c690b20a
ZJS
3025 /* This is just some auxiliary data. Just remove the RRset and continue. */
3026 r = dns_answer_remove_by_key(&t->answer, rr->key);
3027 if (r < 0)
3028 return r;
d33b6cf3 3029
c690b20a
ZJS
3030 /* We dropped something from the answer, start from the beginning. */
3031 return 1;
3032 }
f3cf586d 3033
c690b20a
ZJS
3034 return 2; /* Finito. */
3035}
94aa7071 3036
c690b20a
ZJS
3037int dns_transaction_validate_dnssec(DnsTransaction *t) {
3038 _cleanup_(dns_answer_unrefp) DnsAnswer *validated = NULL;
3039 Phase phase;
3040 DnsAnswerFlags flags;
3041 int r;
202b76ae 3042 char key_str[DNS_RESOURCE_KEY_STRING_MAX];
94aa7071 3043
c690b20a 3044 assert(t);
94aa7071 3045
c690b20a
ZJS
3046 /* We have now collected all DS and DNSKEY RRs in
3047 * t->validated_keys, let's see which RRs we can now
3048 * authenticate with that. */
94aa7071 3049
c690b20a
ZJS
3050 if (t->scope->dnssec_mode == DNSSEC_NO)
3051 return 0;
a150ff5e 3052
c690b20a
ZJS
3053 /* Already validated */
3054 if (t->answer_dnssec_result != _DNSSEC_RESULT_INVALID)
3055 return 0;
105e1512 3056
c690b20a
ZJS
3057 /* Our own stuff needs no validation */
3058 if (IN_SET(t->answer_source, DNS_TRANSACTION_ZONE, DNS_TRANSACTION_TRUST_ANCHOR)) {
3059 t->answer_dnssec_result = DNSSEC_VALIDATED;
3060 t->answer_authenticated = true;
3061 return 0;
3062 }
a150ff5e 3063
c690b20a
ZJS
3064 /* Cached stuff is not affected by validation. */
3065 if (t->answer_source != DNS_TRANSACTION_NETWORK)
3066 return 0;
f3cf586d 3067
c690b20a
ZJS
3068 if (!dns_transaction_dnssec_supported_full(t)) {
3069 /* The server does not support DNSSEC, or doesn't augment responses with RRSIGs. */
3070 t->answer_dnssec_result = DNSSEC_INCOMPATIBLE_SERVER;
d001e0a3 3071 log_debug("Not validating response for %" PRIu16 ", used server feature level does not support DNSSEC.", t->id);
c690b20a
ZJS
3072 return 0;
3073 }
f3cf586d 3074
202b76ae
ZJS
3075 log_debug("Validating response from transaction %" PRIu16 " (%s).",
3076 t->id,
3077 dns_resource_key_to_string(t->key, key_str, sizeof key_str));
547973de 3078
c690b20a
ZJS
3079 /* First, see if this response contains any revoked trust
3080 * anchors we care about */
3081 r = dns_transaction_check_revoked_trust_anchors(t);
3082 if (r < 0)
3083 return r;
43e6779a 3084
c690b20a
ZJS
3085 /* Third, copy all RRs we acquired successfully from auxiliary RRs over. */
3086 r = dns_transaction_copy_validated(t);
3087 if (r < 0)
3088 return r;
43e6779a 3089
c690b20a
ZJS
3090 /* Second, see if there are DNSKEYs we already know a
3091 * validated DS for. */
3092 r = dns_transaction_validate_dnskey_by_ds(t);
3093 if (r < 0)
3094 return r;
43e6779a 3095
c690b20a
ZJS
3096 /* Fourth, remove all DNSKEY and DS RRs again that our trust
3097 * anchor says are revoked. After all we might have marked
3098 * some keys revoked above, but they might still be lingering
3099 * in our validated_keys list. */
3100 r = dns_transaction_invalidate_revoked_keys(t);
3101 if (r < 0)
3102 return r;
f3cf586d 3103
c690b20a
ZJS
3104 phase = DNSSEC_PHASE_DNSKEY;
3105 for (;;) {
3106 bool have_nsec = false;
f3cf586d 3107
c690b20a
ZJS
3108 r = dnssec_validate_records(t, phase, &have_nsec, &validated);
3109 if (r <= 0)
3110 return r;
547973de 3111
c690b20a
ZJS
3112 /* Try again as long as we managed to achieve something */
3113 if (r == 1)
547973de
LP
3114 continue;
3115
c690b20a 3116 if (phase == DNSSEC_PHASE_DNSKEY && have_nsec) {
0c7bff0a 3117 /* OK, we processed all DNSKEYs, and there are NSEC/NSEC3 RRs, look at those now. */
c690b20a 3118 phase = DNSSEC_PHASE_NSEC;
0c7bff0a
LP
3119 continue;
3120 }
3121
c690b20a
ZJS
3122 if (phase != DNSSEC_PHASE_ALL) {
3123 /* OK, we processed all DNSKEYs and NSEC/NSEC3 RRs, look at all the rest now.
3124 * Note that in this third phase we start to remove RRs we couldn't validate. */
3125 phase = DNSSEC_PHASE_ALL;
56352fe9 3126 continue;
547973de
LP
3127 }
3128
56352fe9 3129 /* We're done */
547973de
LP
3130 break;
3131 }
3132
3133 dns_answer_unref(t->answer);
1cc6c93a 3134 t->answer = TAKE_PTR(validated);
547973de 3135
72667f08
LP
3136 /* At this point the answer only contains validated
3137 * RRsets. Now, let's see if it actually answers the question
3138 * we asked. If so, great! If it doesn't, then see if
3139 * NSEC/NSEC3 can prove this. */
105e1512 3140 r = dns_transaction_has_positive_answer(t, &flags);
72667f08 3141 if (r > 0) {
105e1512
LP
3142 /* Yes, it answers the question! */
3143
3144 if (flags & DNS_ANSWER_AUTHENTICATED) {
3145 /* The answer is fully authenticated, yay. */
019036a4 3146 t->answer_dnssec_result = DNSSEC_VALIDATED;
105e1512
LP
3147 t->answer_rcode = DNS_RCODE_SUCCESS;
3148 t->answer_authenticated = true;
3149 } else {
3150 /* The answer is not fully authenticated. */
019036a4 3151 t->answer_dnssec_result = DNSSEC_UNSIGNED;
105e1512
LP
3152 t->answer_authenticated = false;
3153 }
3154
72667f08
LP
3155 } else if (r == 0) {
3156 DnssecNsecResult nr;
ed29bfdc 3157 bool authenticated = false;
72667f08
LP
3158
3159 /* Bummer! Let's check NSEC/NSEC3 */
0c7bff0a 3160 r = dnssec_nsec_test(t->answer, t->key, &nr, &authenticated, &t->answer_nsec_ttl);
72667f08
LP
3161 if (r < 0)
3162 return r;
3163
3164 switch (nr) {
3165
3166 case DNSSEC_NSEC_NXDOMAIN:
3167 /* NSEC proves the domain doesn't exist. Very good. */
202b76ae 3168 log_debug("Proved NXDOMAIN via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str);
019036a4 3169 t->answer_dnssec_result = DNSSEC_VALIDATED;
72667f08 3170 t->answer_rcode = DNS_RCODE_NXDOMAIN;
ed29bfdc 3171 t->answer_authenticated = authenticated;
7aa8ce98 3172
59c5b597 3173 manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, t->key);
72667f08
LP
3174 break;
3175
3176 case DNSSEC_NSEC_NODATA:
3177 /* NSEC proves that there's no data here, very good. */
202b76ae 3178 log_debug("Proved NODATA via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str);
019036a4 3179 t->answer_dnssec_result = DNSSEC_VALIDATED;
72667f08 3180 t->answer_rcode = DNS_RCODE_SUCCESS;
ed29bfdc 3181 t->answer_authenticated = authenticated;
7aa8ce98 3182
59c5b597 3183 manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, t->key);
72667f08
LP
3184 break;
3185
105e1512
LP
3186 case DNSSEC_NSEC_OPTOUT:
3187 /* NSEC3 says the data might not be signed */
202b76ae 3188 log_debug("Data is NSEC3 opt-out via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str);
019036a4 3189 t->answer_dnssec_result = DNSSEC_UNSIGNED;
105e1512 3190 t->answer_authenticated = false;
7aa8ce98 3191
59c5b597 3192 manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, t->key);
105e1512
LP
3193 break;
3194
72667f08
LP
3195 case DNSSEC_NSEC_NO_RR:
3196 /* No NSEC data? Bummer! */
105e1512
LP
3197
3198 r = dns_transaction_requires_nsec(t);
3199 if (r < 0)
3200 return r;
7aa8ce98 3201 if (r > 0) {
019036a4 3202 t->answer_dnssec_result = DNSSEC_NO_SIGNATURE;
59c5b597 3203 manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, t->key);
7aa8ce98 3204 } else {
019036a4 3205 t->answer_dnssec_result = DNSSEC_UNSIGNED;
105e1512 3206 t->answer_authenticated = false;
59c5b597 3207 manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, t->key);
105e1512
LP
3208 }
3209
3210 break;
3211
3212 case DNSSEC_NSEC_UNSUPPORTED_ALGORITHM:
3213 /* We don't know the NSEC3 algorithm used? */
019036a4 3214 t->answer_dnssec_result = DNSSEC_UNSUPPORTED_ALGORITHM;
59c5b597 3215 manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, t->key);
72667f08
LP
3216 break;
3217
3218 case DNSSEC_NSEC_FOUND:
146035b3 3219 case DNSSEC_NSEC_CNAME:
72667f08 3220 /* NSEC says it needs to be there, but we couldn't find it? Bummer! */
019036a4 3221 t->answer_dnssec_result = DNSSEC_NSEC_MISMATCH;
59c5b597 3222 manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, t->key);
72667f08
LP
3223 break;
3224
3225 default:
3226 assert_not_reached("Unexpected NSEC result.");
3227 }
3228 }
3229
547973de
LP
3230 return 1;
3231}
3232
ec2c5e43
LP
3233static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {
3234 [DNS_TRANSACTION_NULL] = "null",
3235 [DNS_TRANSACTION_PENDING] = "pending",
547973de 3236 [DNS_TRANSACTION_VALIDATING] = "validating",
3bbdc31d 3237 [DNS_TRANSACTION_RCODE_FAILURE] = "rcode-failure",
ec2c5e43
LP
3238 [DNS_TRANSACTION_SUCCESS] = "success",
3239 [DNS_TRANSACTION_NO_SERVERS] = "no-servers",
3240 [DNS_TRANSACTION_TIMEOUT] = "timeout",
3241 [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached",
3242 [DNS_TRANSACTION_INVALID_REPLY] = "invalid-reply",
7cc6ed7b 3243 [DNS_TRANSACTION_ERRNO] = "errno",
ec2c5e43 3244 [DNS_TRANSACTION_ABORTED] = "aborted",
547973de 3245 [DNS_TRANSACTION_DNSSEC_FAILED] = "dnssec-failed",
b2b796b8 3246 [DNS_TRANSACTION_NO_TRUST_ANCHOR] = "no-trust-anchor",
91adc4db 3247 [DNS_TRANSACTION_RR_TYPE_UNSUPPORTED] = "rr-type-unsupported",
edbcc1fd 3248 [DNS_TRANSACTION_NETWORK_DOWN] = "network-down",
0791110f 3249 [DNS_TRANSACTION_NOT_FOUND] = "not-found",
ec2c5e43
LP
3250};
3251DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);
c3bc53e6
LP
3252
3253static const char* const dns_transaction_source_table[_DNS_TRANSACTION_SOURCE_MAX] = {
3254 [DNS_TRANSACTION_NETWORK] = "network",
3255 [DNS_TRANSACTION_CACHE] = "cache",
3256 [DNS_TRANSACTION_ZONE] = "zone",
0d2cd476 3257 [DNS_TRANSACTION_TRUST_ANCHOR] = "trust-anchor",
c3bc53e6
LP
3258};
3259DEFINE_STRING_TABLE_LOOKUP(dns_transaction_source, DnsTransactionSource);