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