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