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