]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-transaction.c
resolved: improve some log messages a bit
[thirdparty/systemd.git] / src / resolve / resolved-dns-transaction.c
CommitLineData
ec2c5e43
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include "af-list.h"
b5efdb8a 23#include "alloc-util.h"
f52e61da 24#include "dns-domain.h"
3ffd4af2
LP
25#include "fd-util.h"
26#include "random-util.h"
7778dfff 27#include "resolved-dns-cache.h"
3ffd4af2
LP
28#include "resolved-dns-transaction.h"
29#include "resolved-llmnr.h"
8b43440b 30#include "string-table.h"
ec2c5e43 31
c61d2b44
LP
32static void dns_transaction_reset_answer(DnsTransaction *t) {
33 assert(t);
34
35 t->received = dns_packet_unref(t->received);
36 t->answer = dns_answer_unref(t->answer);
37 t->answer_rcode = 0;
38 t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
39 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
40 t->answer_authenticated = false;
41}
42
ec2c5e43 43DnsTransaction* dns_transaction_free(DnsTransaction *t) {
801ad6a6 44 DnsQueryCandidate *c;
ec2c5e43 45 DnsZoneItem *i;
547973de 46 DnsTransaction *z;
ec2c5e43
LP
47
48 if (!t)
49 return NULL;
50
51 sd_event_source_unref(t->timeout_event_source);
52
ec2c5e43 53 dns_packet_unref(t->sent);
c61d2b44 54 dns_transaction_reset_answer(t);
ec2c5e43 55
4667e00a
LP
56 sd_event_source_unref(t->dns_udp_event_source);
57 safe_close(t->dns_udp_fd);
d20b1667 58
8300ba21 59 dns_server_unref(t->server);
ec2c5e43
LP
60 dns_stream_free(t->stream);
61
62 if (t->scope) {
f9ebb22a
LP
63 hashmap_remove_value(t->scope->transactions_by_key, t->key, t);
64 LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
ec2c5e43
LP
65
66 if (t->id != 0)
67 hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
68 }
69
da0c630e
LP
70 dns_resource_key_unref(t->key);
71
547973de 72 while ((c = set_steal_first(t->notify_query_candidates)))
801ad6a6 73 set_remove(c->transactions, t);
547973de 74 set_free(t->notify_query_candidates);
801ad6a6 75
547973de 76 while ((i = set_steal_first(t->notify_zone_items)))
ec2c5e43 77 i->probe_transaction = NULL;
547973de
LP
78 set_free(t->notify_zone_items);
79
80 while ((z = set_steal_first(t->notify_transactions)))
81 set_remove(z->dnssec_transactions, t);
82 set_free(t->notify_transactions);
83
84 while ((z = set_steal_first(t->dnssec_transactions))) {
85 set_remove(z->notify_transactions, t);
86 dns_transaction_gc(z);
87 }
88 set_free(t->dnssec_transactions);
89
90 dns_answer_unref(t->validated_keys);
ec2c5e43 91
a5784c49 92 free(t->key_string);
ec2c5e43
LP
93 free(t);
94 return NULL;
95}
96
97DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
98
99void dns_transaction_gc(DnsTransaction *t) {
100 assert(t);
101
102 if (t->block_gc > 0)
103 return;
104
547973de
LP
105 if (set_isempty(t->notify_query_candidates) &&
106 set_isempty(t->notify_zone_items) &&
107 set_isempty(t->notify_transactions))
ec2c5e43
LP
108 dns_transaction_free(t);
109}
110
f52e61da 111int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key) {
ec2c5e43
LP
112 _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL;
113 int r;
114
115 assert(ret);
116 assert(s);
f52e61da 117 assert(key);
ec2c5e43 118
9eae2bf3 119 /* Don't allow looking up invalid or pseudo RRs */
c463eb78 120 if (!dns_type_is_valid_query(key->type))
9eae2bf3
LP
121 return -EINVAL;
122
123 /* We only support the IN class */
c463eb78 124 if (key->class != DNS_CLASS_IN && key->class != DNS_CLASS_ANY)
9eae2bf3
LP
125 return -EOPNOTSUPP;
126
d5099efc 127 r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL);
ec2c5e43
LP
128 if (r < 0)
129 return r;
130
f9ebb22a 131 r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops);
da0c630e
LP
132 if (r < 0)
133 return r;
134
ec2c5e43
LP
135 t = new0(DnsTransaction, 1);
136 if (!t)
137 return -ENOMEM;
138
4667e00a 139 t->dns_udp_fd = -1;
c3bc53e6 140 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
019036a4 141 t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
f52e61da 142 t->key = dns_resource_key_ref(key);
ec2c5e43 143
da0c630e 144 /* Find a fresh, unused transaction id */
ec2c5e43
LP
145 do
146 random_bytes(&t->id, sizeof(t->id));
147 while (t->id == 0 ||
148 hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(t->id)));
149
150 r = hashmap_put(s->manager->dns_transactions, UINT_TO_PTR(t->id), t);
151 if (r < 0) {
152 t->id = 0;
153 return r;
154 }
155
f9ebb22a 156 r = hashmap_replace(s->transactions_by_key, t->key, t);
da0c630e
LP
157 if (r < 0) {
158 hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id));
159 return r;
160 }
161
f9ebb22a 162 LIST_PREPEND(transactions_by_scope, s->transactions, t);
ec2c5e43
LP
163 t->scope = s;
164
a150ff5e
LP
165 s->manager->n_transactions_total ++;
166
ec2c5e43
LP
167 if (ret)
168 *ret = t;
169
170 t = NULL;
171
172 return 0;
173}
174
175static void dns_transaction_stop(DnsTransaction *t) {
176 assert(t);
177
178 t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
179 t->stream = dns_stream_free(t->stream);
ae6a4bbf
LP
180
181 /* Note that we do not drop the UDP socket here, as we want to
182 * reuse it to repeat the interaction. */
ec2c5e43
LP
183}
184
185static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
2fb3034c 186 _cleanup_free_ char *pretty = NULL;
ec2c5e43 187 DnsZoneItem *z;
ec2c5e43
LP
188
189 assert(t);
190 assert(p);
191
192 if (manager_our_packet(t->scope->manager, p) != 0)
193 return;
194
2fb3034c
LP
195 in_addr_to_string(p->family, &p->sender, &pretty);
196
a5784c49
LP
197 log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s got tentative packet from %s.",
198 t->id,
199 dns_transaction_key_string(t),
ec2c5e43
LP
200 dns_protocol_to_string(t->scope->protocol),
201 t->scope->link ? t->scope->link->name : "*",
2fb3034c
LP
202 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
203 pretty);
ec2c5e43 204
a4076574
LP
205 /* RFC 4795, Section 4.1 says that the peer with the
206 * lexicographically smaller IP address loses */
4d91eec4
LP
207 if (memcmp(&p->sender, &p->destination, FAMILY_ADDRESS_SIZE(p->family)) >= 0) {
208 log_debug("Peer has lexicographically larger IP address and thus lost in the conflict.");
a4076574
LP
209 return;
210 }
211
4d91eec4 212 log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
a4076574 213
ec2c5e43 214 t->block_gc++;
547973de 215 while ((z = set_first(t->notify_zone_items))) {
3ef64445
LP
216 /* First, make sure the zone item drops the reference
217 * to us */
218 dns_zone_item_probe_stop(z);
219
220 /* Secondly, report this as conflict, so that we might
221 * look for a different hostname */
ec2c5e43 222 dns_zone_item_conflict(z);
3ef64445 223 }
ec2c5e43
LP
224 t->block_gc--;
225
226 dns_transaction_gc(t);
227}
228
229void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
801ad6a6 230 DnsQueryCandidate *c;
ec2c5e43 231 DnsZoneItem *z;
547973de 232 DnsTransaction *d;
ec2c5e43
LP
233 Iterator i;
234
235 assert(t);
547973de 236 assert(!DNS_TRANSACTION_IS_LIVE(state));
e56187ca 237
f61dfddb
LP
238 if (state == DNS_TRANSACTION_DNSSEC_FAILED)
239 log_struct(LOG_NOTICE,
240 LOG_MESSAGE("DNSSEC validation failed for question %s: %s", dns_transaction_key_string(t), dnssec_result_to_string(t->answer_dnssec_result)),
241 "DNS_TRANSACTION=%" PRIu16, t->id,
242 "DNS_QUESTION=%s", dns_transaction_key_string(t),
243 "DNSSEC_RESULT=%s", dnssec_result_to_string(t->answer_dnssec_result),
244 NULL);
245
ec2c5e43
LP
246 /* Note that this call might invalidate the query. Callers
247 * should hence not attempt to access the query or transaction
248 * after calling this function. */
249
a5784c49
LP
250 log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s now complete with <%s> from %s (%s).",
251 t->id,
252 dns_transaction_key_string(t),
ec2c5e43
LP
253 dns_protocol_to_string(t->scope->protocol),
254 t->scope->link ? t->scope->link->name : "*",
255 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
c3bc53e6 256 dns_transaction_state_to_string(state),
a5784c49
LP
257 t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source),
258 t->answer_authenticated ? "authenticated" : "unsigned");
ec2c5e43
LP
259
260 t->state = state;
261
262 dns_transaction_stop(t);
263
264 /* Notify all queries that are interested, but make sure the
265 * transaction isn't freed while we are still looking at it */
266 t->block_gc++;
f7014757 267
547973de
LP
268 SET_FOREACH(c, t->notify_query_candidates, i)
269 dns_query_candidate_notify(c);
270 SET_FOREACH(z, t->notify_zone_items, i)
271 dns_zone_item_notify(z);
ec2c5e43 272
f7014757
LP
273 if (!set_isempty(t->notify_transactions)) {
274 DnsTransaction **nt;
275 unsigned j, n = 0;
276
277 /* We need to be careful when notifying other
278 * transactions, as that might destroy other
279 * transactions in our list. Hence, in order to be
280 * able to safely iterate through the list of
281 * transactions, take a GC lock on all of them
282 * first. Then, in a second loop, notify them, but
283 * first unlock that specific transaction. */
284
285 nt = newa(DnsTransaction*, set_size(t->notify_transactions));
286 SET_FOREACH(d, t->notify_transactions, i) {
287 nt[n++] = d;
288 d->block_gc++;
289 }
290
291 assert(n == set_size(t->notify_transactions));
292
293 for (j = 0; j < n; j++) {
294 if (set_contains(t->notify_transactions, nt[j]))
295 dns_transaction_notify(nt[j], t);
296
297 nt[j]->block_gc--;
298 dns_transaction_gc(nt[j]);
299 }
300 }
301
302 t->block_gc--;
ec2c5e43
LP
303 dns_transaction_gc(t);
304}
305
306static int on_stream_complete(DnsStream *s, int error) {
307 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
308 DnsTransaction *t;
309
310 assert(s);
311 assert(s->transaction);
312
313 /* Copy the data we care about out of the stream before we
314 * destroy it. */
315 t = s->transaction;
316 p = dns_packet_ref(s->read_packet);
317
318 t->stream = dns_stream_free(t->stream);
319
ac720200
LP
320 if (IN_SET(error, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE)) {
321 dns_transaction_complete(t, DNS_TRANSACTION_CONNECTION_FAILURE);
322 return 0;
323 }
324
ec2c5e43
LP
325 if (error != 0) {
326 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
327 return 0;
328 }
329
a4076574 330 if (dns_packet_validate_reply(p) <= 0) {
a20b9592 331 log_debug("Invalid TCP reply packet.");
a4076574
LP
332 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
333 return 0;
334 }
335
336 dns_scope_check_conflicts(t->scope, p);
337
ec2c5e43
LP
338 t->block_gc++;
339 dns_transaction_process_reply(t, p);
340 t->block_gc--;
341
342 /* If the response wasn't useful, then complete the transition now */
343 if (t->state == DNS_TRANSACTION_PENDING)
344 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
598f44bd
LP
345 else
346 dns_transaction_gc(t);
ec2c5e43
LP
347
348 return 0;
349}
350
351static int dns_transaction_open_tcp(DnsTransaction *t) {
088480fa 352 DnsServer *server = NULL;
ec2c5e43
LP
353 _cleanup_close_ int fd = -1;
354 int r;
355
356 assert(t);
357
358 if (t->stream)
359 return 0;
360
106784eb
DM
361 switch (t->scope->protocol) {
362 case DNS_PROTOCOL_DNS:
49cce12d 363 fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, 53, &server);
106784eb 364 break;
ec2c5e43 365
106784eb 366 case DNS_PROTOCOL_LLMNR:
a8f6397f 367 /* When we already received a reply to this (but it was truncated), send to its sender address */
ec2c5e43 368 if (t->received)
49cce12d 369 fd = dns_scope_socket_tcp(t->scope, t->received->family, &t->received->sender, t->received->sender_port, NULL);
ec2c5e43
LP
370 else {
371 union in_addr_union address;
a7f7d1bd 372 int family = AF_UNSPEC;
ec2c5e43
LP
373
374 /* Otherwise, try to talk to the owner of a
375 * the IP address, in case this is a reverse
376 * PTR lookup */
f52e61da
LP
377
378 r = dns_name_address(DNS_RESOURCE_KEY_NAME(t->key), &family, &address);
ec2c5e43
LP
379 if (r < 0)
380 return r;
381 if (r == 0)
382 return -EINVAL;
9e08a6e0 383 if (family != t->scope->family)
9318cdd3 384 return -ESRCH;
ec2c5e43 385
49cce12d 386 fd = dns_scope_socket_tcp(t->scope, family, &address, LLMNR_PORT, NULL);
ec2c5e43 387 }
106784eb
DM
388
389 break;
390
391 default:
ec2c5e43 392 return -EAFNOSUPPORT;
106784eb 393 }
ec2c5e43
LP
394
395 if (fd < 0)
396 return fd;
397
398 r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd);
399 if (r < 0)
400 return r;
401
402 fd = -1;
403
404 r = dns_stream_write_packet(t->stream, t->sent);
405 if (r < 0) {
406 t->stream = dns_stream_free(t->stream);
407 return r;
408 }
409
8300ba21
TG
410 dns_server_unref(t->server);
411 t->server = dns_server_ref(server);
c61d2b44
LP
412
413 dns_transaction_reset_answer(t);
414
ec2c5e43
LP
415 t->stream->complete = on_stream_complete;
416 t->stream->transaction = t;
417
418 /* The interface index is difficult to determine if we are
419 * connecting to the local host, hence fill this in right away
420 * instead of determining it from the socket */
421 if (t->scope->link)
422 t->stream->ifindex = t->scope->link->ifindex;
423
cbe4216d
LP
424 t->tried_stream = true;
425
ec2c5e43
LP
426 return 0;
427}
428
647f6aa8
TG
429static void dns_transaction_next_dns_server(DnsTransaction *t) {
430 assert(t);
431
432 t->server = dns_server_unref(t->server);
4667e00a
LP
433 t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source);
434 t->dns_udp_fd = safe_close(t->dns_udp_fd);
647f6aa8
TG
435
436 dns_scope_next_dns_server(t->scope);
437}
438
547973de 439static void dns_transaction_cache_answer(DnsTransaction *t) {
547973de
LP
440 assert(t);
441
442 /* For mDNS we cache whenever we get the packet, rather than
443 * in each transaction. */
444 if (!IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR))
445 return;
446
447 /* We never cache if this packet is from the local host, under
448 * the assumption that a locally running DNS server would
449 * cache this anyway, and probably knows better when to flush
450 * the cache then we could. */
451 if (!DNS_PACKET_SHALL_CACHE(t->received))
452 return;
453
547973de
LP
454 dns_cache_put(&t->scope->cache,
455 t->key,
456 t->answer_rcode,
457 t->answer,
547973de
LP
458 t->answer_authenticated,
459 0,
460 t->received->family,
461 &t->received->sender);
462}
463
105e1512
LP
464static bool dns_transaction_dnssec_is_live(DnsTransaction *t) {
465 DnsTransaction *dt;
466 Iterator i;
467
468 assert(t);
469
470 SET_FOREACH(dt, t->dnssec_transactions, i)
471 if (DNS_TRANSACTION_IS_LIVE(dt->state))
472 return true;
473
474 return false;
475}
476
547973de
LP
477static void dns_transaction_process_dnssec(DnsTransaction *t) {
478 int r;
479
480 assert(t);
481
482 /* Are there ongoing DNSSEC transactions? If so, let's wait for them. */
105e1512 483 if (dns_transaction_dnssec_is_live(t))
547973de
LP
484 return;
485
486 /* All our auxiliary DNSSEC transactions are complete now. Try
487 * to validate our RRset now. */
488 r = dns_transaction_validate_dnssec(t);
489 if (r < 0) {
490 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
491 return;
492 }
493
b652d4a2
LP
494 if (t->answer_dnssec_result == DNSSEC_INCOMPATIBLE_SERVER &&
495 t->scope->dnssec_mode == DNSSEC_YES) {
496 /* We are not in automatic downgrade mode, and the
497 * server is bad, refuse operation. */
498 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
499 return;
500 }
501
019036a4 502 if (!IN_SET(t->answer_dnssec_result,
b652d4a2
LP
503 _DNSSEC_RESULT_INVALID, /* No DNSSEC validation enabled */
504 DNSSEC_VALIDATED, /* Answer is signed and validated successfully */
505 DNSSEC_UNSIGNED, /* Answer is right-fully unsigned */
506 DNSSEC_INCOMPATIBLE_SERVER)) { /* Server does not do DNSSEC (Yay, we are downgrade attack vulnerable!) */
547973de
LP
507 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
508 return;
509 }
510
511 dns_transaction_cache_answer(t);
512
513 if (t->answer_rcode == DNS_RCODE_SUCCESS)
514 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
515 else
3bbdc31d 516 dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE);
547973de
LP
517}
518
ec2c5e43 519void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
9df3ba6c 520 usec_t ts;
ec2c5e43
LP
521 int r;
522
523 assert(t);
524 assert(p);
9df3ba6c
TG
525 assert(t->scope);
526 assert(t->scope->manager);
ec2c5e43 527
5a7e41a3
LP
528 if (t->state != DNS_TRANSACTION_PENDING)
529 return;
530
ec2c5e43
LP
531 /* Note that this call might invalidate the query. Callers
532 * should hence not attempt to access the query or transaction
533 * after calling this function. */
534
b5efcf29
LP
535 log_debug("Processing incoming packet on transaction %" PRIu16".", t->id);
536
106784eb 537 switch (t->scope->protocol) {
b5efcf29 538
106784eb 539 case DNS_PROTOCOL_LLMNR:
ec2c5e43
LP
540 assert(t->scope->link);
541
542 /* For LLMNR we will not accept any packets from other
543 * interfaces */
544
545 if (p->ifindex != t->scope->link->ifindex)
546 return;
547
548 if (p->family != t->scope->family)
549 return;
550
551 /* Tentative packets are not full responses but still
552 * useful for identifying uniqueness conflicts during
553 * probing. */
8b757a38 554 if (DNS_PACKET_LLMNR_T(p)) {
ec2c5e43
LP
555 dns_transaction_tentative(t, p);
556 return;
557 }
106784eb
DM
558
559 break;
560
4e5bf5e1
DM
561 case DNS_PROTOCOL_MDNS:
562 assert(t->scope->link);
563
564 /* For mDNS we will not accept any packets from other interfaces */
565 if (p->ifindex != t->scope->link->ifindex)
566 return;
567
568 if (p->family != t->scope->family)
569 return;
570
571 break;
572
106784eb
DM
573 case DNS_PROTOCOL_DNS:
574 break;
575
576 default:
9c56a6f3 577 assert_not_reached("Invalid DNS protocol.");
ec2c5e43
LP
578 }
579
ec2c5e43
LP
580 if (t->received != p) {
581 dns_packet_unref(t->received);
582 t->received = dns_packet_ref(p);
583 }
584
c3bc53e6
LP
585 t->answer_source = DNS_TRANSACTION_NETWORK;
586
ec2c5e43
LP
587 if (p->ipproto == IPPROTO_TCP) {
588 if (DNS_PACKET_TC(p)) {
589 /* Truncated via TCP? Somebody must be fucking with us */
590 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
591 return;
592 }
593
594 if (DNS_PACKET_ID(p) != t->id) {
595 /* Not the reply to our query? Somebody must be fucking with us */
596 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
597 return;
598 }
599 }
600
38a03f06 601 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
9df3ba6c
TG
602
603 switch (t->scope->protocol) {
8af5b883 604
9df3ba6c
TG
605 case DNS_PROTOCOL_DNS:
606 assert(t->server);
607
4e0b8b17
TG
608 if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
609
8af5b883 610 /* Request failed, immediately try again with reduced features */
4e0b8b17
TG
611 log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p)));
612
613 dns_server_packet_failed(t->server, t->current_features);
614
615 r = dns_transaction_go(t);
616 if (r < 0) {
617 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
618 return;
619 }
620
621 return;
622 } else
d74fb368 623 dns_server_packet_received(t->server, t->current_features, ts - t->start_usec, p->size);
9df3ba6c
TG
624
625 break;
8af5b883 626
9df3ba6c
TG
627 case DNS_PROTOCOL_LLMNR:
628 case DNS_PROTOCOL_MDNS:
629 dns_scope_packet_received(t->scope, ts - t->start_usec);
9df3ba6c 630 break;
8af5b883 631
9df3ba6c 632 default:
8af5b883 633 assert_not_reached("Invalid DNS protocol.");
9df3ba6c
TG
634 }
635
ec2c5e43 636 if (DNS_PACKET_TC(p)) {
547493c5
DM
637
638 /* Truncated packets for mDNS are not allowed. Give up immediately. */
639 if (t->scope->protocol == DNS_PROTOCOL_MDNS) {
640 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
641 return;
642 }
643
ec2c5e43
LP
644 /* Response was truncated, let's try again with good old TCP */
645 r = dns_transaction_open_tcp(t);
646 if (r == -ESRCH) {
647 /* No servers found? Damn! */
648 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
649 return;
650 }
651 if (r < 0) {
8af5b883 652 /* On LLMNR, if we cannot connect to the host,
ec2c5e43
LP
653 * we immediately give up */
654 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
655 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
656 return;
657 }
658
659 /* On DNS, couldn't send? Try immediately again, with a new server */
647f6aa8 660 dns_transaction_next_dns_server(t);
ec2c5e43
LP
661
662 r = dns_transaction_go(t);
663 if (r < 0) {
664 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
665 return;
666 }
ec2c5e43 667 }
2a6658ef
LP
668
669 return;
ec2c5e43
LP
670 }
671
8af5b883 672 /* Parse message, if it isn't parsed yet. */
ec2c5e43
LP
673 r = dns_packet_extract(p);
674 if (r < 0) {
675 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
676 return;
677 }
678
b5efcf29
LP
679 if (IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR)) {
680
547493c5 681 /* Only consider responses with equivalent query section to the request */
8af5b883
LP
682 r = dns_packet_is_reply_for(p, t->key);
683 if (r < 0) {
684 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
685 return;
686 }
687 if (r == 0) {
547493c5
DM
688 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
689 return;
690 }
29815b6c 691
547493c5
DM
692 /* Install the answer as answer to the transaction */
693 dns_answer_unref(t->answer);
694 t->answer = dns_answer_ref(p->answer);
695 t->answer_rcode = DNS_PACKET_RCODE(p);
105e1512 696 t->answer_authenticated = false;
79e24931 697
547973de
LP
698 r = dns_transaction_request_dnssec_keys(t);
699 if (r < 0) {
700 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
701 return;
702 }
703 if (r > 0) {
704 /* There are DNSSEC transactions pending now. Update the state accordingly. */
705 t->state = DNS_TRANSACTION_VALIDATING;
423659ab 706 dns_transaction_stop(t);
547973de
LP
707 return;
708 }
547493c5 709 }
ec2c5e43 710
547973de 711 dns_transaction_process_dnssec(t);
ec2c5e43
LP
712}
713
c19ffd9f
TG
714static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
715 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
716 DnsTransaction *t = userdata;
717 int r;
718
719 assert(t);
720 assert(t->scope);
721
722 r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p);
723 if (r <= 0)
724 return r;
725
726 if (dns_packet_validate_reply(p) > 0 &&
9df3ba6c 727 DNS_PACKET_ID(p) == t->id)
c19ffd9f 728 dns_transaction_process_reply(t, p);
9df3ba6c 729 else
2c6bf498 730 log_debug("Invalid DNS UDP packet, ignoring.");
c19ffd9f
TG
731
732 return 0;
733}
734
49cce12d 735static int dns_transaction_emit_udp(DnsTransaction *t) {
c19ffd9f
TG
736 int r;
737
738 assert(t);
c19ffd9f 739
471d40d9
TG
740 if (t->scope->protocol == DNS_PROTOCOL_DNS && !t->server) {
741 DnsServer *server = NULL;
742 _cleanup_close_ int fd = -1;
c19ffd9f 743
49cce12d 744 fd = dns_scope_socket_udp(t->scope, &server);
471d40d9
TG
745 if (fd < 0)
746 return fd;
c19ffd9f 747
4667e00a 748 r = sd_event_add_io(t->scope->manager->event, &t->dns_udp_event_source, fd, EPOLLIN, on_dns_packet, t);
471d40d9
TG
749 if (r < 0)
750 return r;
c19ffd9f 751
4667e00a 752 t->dns_udp_fd = fd;
471d40d9
TG
753 fd = -1;
754 t->server = dns_server_ref(server);
755 }
c19ffd9f 756
49cce12d 757 r = dns_scope_emit_udp(t->scope, t->dns_udp_fd, t->server, t->sent);
471d40d9
TG
758 if (r < 0)
759 return r;
c19ffd9f 760
be808ea0
TG
761 if (t->server)
762 t->current_features = t->server->possible_features;
763
471d40d9 764 return 0;
c19ffd9f
TG
765}
766
ec2c5e43
LP
767static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
768 DnsTransaction *t = userdata;
769 int r;
770
771 assert(s);
772 assert(t);
773
ef7ce6df
DM
774 if (!t->initial_jitter_scheduled || t->initial_jitter_elapsed) {
775 /* Timeout reached? Increase the timeout for the server used */
776 switch (t->scope->protocol) {
49cce12d 777
ef7ce6df
DM
778 case DNS_PROTOCOL_DNS:
779 assert(t->server);
ef7ce6df 780 dns_server_packet_lost(t->server, t->current_features, usec - t->start_usec);
ef7ce6df 781 break;
49cce12d 782
ef7ce6df
DM
783 case DNS_PROTOCOL_LLMNR:
784 case DNS_PROTOCOL_MDNS:
785 dns_scope_packet_lost(t->scope, usec - t->start_usec);
ef7ce6df 786 break;
49cce12d 787
ef7ce6df
DM
788 default:
789 assert_not_reached("Invalid DNS protocol.");
790 }
791
792 if (t->initial_jitter_scheduled)
793 t->initial_jitter_elapsed = true;
be808ea0
TG
794 }
795
423659ab
LP
796 log_debug("Timeout reached on transaction %" PRIu16 ".", t->id);
797
be808ea0
TG
798 /* ...and try again with a new server */
799 dns_transaction_next_dns_server(t);
800
ec2c5e43
LP
801 r = dns_transaction_go(t);
802 if (r < 0)
803 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
804
805 return 0;
806}
807
9df3ba6c
TG
808static usec_t transaction_get_resend_timeout(DnsTransaction *t) {
809 assert(t);
810 assert(t->scope);
811
812 switch (t->scope->protocol) {
49cce12d 813
9df3ba6c
TG
814 case DNS_PROTOCOL_DNS:
815 assert(t->server);
9df3ba6c 816 return t->server->resend_timeout;
49cce12d 817
9df3ba6c 818 case DNS_PROTOCOL_MDNS:
11a27c2e
DM
819 assert(t->n_attempts > 0);
820 return (1 << (t->n_attempts - 1)) * USEC_PER_SEC;
49cce12d 821
11a27c2e 822 case DNS_PROTOCOL_LLMNR:
9df3ba6c 823 return t->scope->resend_timeout;
49cce12d 824
9df3ba6c
TG
825 default:
826 assert_not_reached("Invalid DNS protocol.");
827 }
828}
829
c842ff24 830static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
ec2c5e43
LP
831 int r;
832
833 assert(t);
834
ec2c5e43
LP
835 dns_transaction_stop(t);
836
ec2c5e43
LP
837 if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
838 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
839 return 0;
840 }
841
cbe4216d 842 if (t->scope->protocol == DNS_PROTOCOL_LLMNR && t->tried_stream) {
ec2c5e43
LP
843 /* If we already tried via a stream, then we don't
844 * retry on LLMNR. See RFC 4795, Section 2.7. */
845 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
846 return 0;
847 }
848
849 t->n_attempts++;
9df3ba6c 850 t->start_usec = ts;
c61d2b44
LP
851
852 dns_transaction_reset_answer(t);
ec2c5e43 853
0d2cd476
LP
854 /* Check the trust anchor. Do so only on classic DNS, since DNSSEC does not apply otherwise. */
855 if (t->scope->protocol == DNS_PROTOCOL_DNS) {
856 r = dns_trust_anchor_lookup(&t->scope->manager->trust_anchor, t->key, &t->answer);
857 if (r < 0)
858 return r;
859 if (r > 0) {
860 t->answer_rcode = DNS_RCODE_SUCCESS;
861 t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
931851e8 862 t->answer_authenticated = true;
0d2cd476
LP
863 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
864 return 0;
865 }
866 }
867
868 /* Check the zone, but only if this transaction is not used
d746bb3e 869 * for probing or verifying a zone item. */
547973de 870 if (set_isempty(t->notify_zone_items)) {
d746bb3e 871
ae6a4bbf 872 r = dns_zone_lookup(&t->scope->zone, t->key, &t->answer, NULL, NULL);
d746bb3e
LP
873 if (r < 0)
874 return r;
875 if (r > 0) {
ae6a4bbf 876 t->answer_rcode = DNS_RCODE_SUCCESS;
c3bc53e6 877 t->answer_source = DNS_TRANSACTION_ZONE;
931851e8 878 t->answer_authenticated = true;
d746bb3e
LP
879 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
880 return 0;
881 }
882 }
883
4d926a69
LP
884 /* Check the cache, but only if this transaction is not used
885 * for probing or verifying a zone item. */
547973de 886 if (set_isempty(t->notify_zone_items)) {
2c27fbca 887
4d926a69
LP
888 /* Before trying the cache, let's make sure we figured out a
889 * server to use. Should this cause a change of server this
890 * might flush the cache. */
891 dns_scope_get_dns_server(t->scope);
2c27fbca 892
4d926a69
LP
893 /* Let's then prune all outdated entries */
894 dns_cache_prune(&t->scope->cache);
895
931851e8 896 r = dns_cache_lookup(&t->scope->cache, t->key, &t->answer_rcode, &t->answer, &t->answer_authenticated);
4d926a69
LP
897 if (r < 0)
898 return r;
899 if (r > 0) {
c3bc53e6 900 t->answer_source = DNS_TRANSACTION_CACHE;
ae6a4bbf 901 if (t->answer_rcode == DNS_RCODE_SUCCESS)
4d926a69
LP
902 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
903 else
3bbdc31d 904 dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE);
4d926a69
LP
905 return 0;
906 }
ec2c5e43
LP
907 }
908
1effe965
DM
909 return 1;
910}
911
0afa57e2
DM
912static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
913
914 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
7778dfff 915 bool add_known_answers = false;
0afa57e2
DM
916 DnsTransaction *other;
917 unsigned qdcount;
918 usec_t ts;
919 int r;
920
921 assert(t);
922 assert(t->scope->protocol == DNS_PROTOCOL_MDNS);
923
e5abebab 924 /* Discard any previously prepared packet, so we can start over and coalesce again */
0afa57e2
DM
925 t->sent = dns_packet_unref(t->sent);
926
927 r = dns_packet_new_query(&p, t->scope->protocol, 0, false);
928 if (r < 0)
929 return r;
930
931 r = dns_packet_append_key(p, t->key, NULL);
932 if (r < 0)
933 return r;
934
935 qdcount = 1;
936
7778dfff
DM
937 if (dns_key_is_shared(t->key))
938 add_known_answers = true;
939
0afa57e2
DM
940 /*
941 * For mDNS, we want to coalesce as many open queries in pending transactions into one single
942 * query packet on the wire as possible. To achieve that, we iterate through all pending transactions
943 * in our current scope, and see whether their timing contraints allow them to be sent.
944 */
945
946 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
947
948 LIST_FOREACH(transactions_by_scope, other, t->scope->transactions) {
949
950 /* Skip ourselves */
951 if (other == t)
952 continue;
953
954 if (other->state != DNS_TRANSACTION_PENDING)
955 continue;
956
957 if (other->next_attempt_after > ts)
958 continue;
959
960 if (qdcount >= UINT16_MAX)
961 break;
962
963 r = dns_packet_append_key(p, other->key, NULL);
964
965 /*
966 * If we can't stuff more questions into the packet, just give up.
967 * One of the 'other' transactions will fire later and take care of the rest.
968 */
969 if (r == -EMSGSIZE)
970 break;
971
972 if (r < 0)
973 return r;
974
c842ff24 975 r = dns_transaction_prepare(other, ts);
0afa57e2
DM
976 if (r <= 0)
977 continue;
978
979 ts += transaction_get_resend_timeout(other);
980
981 r = sd_event_add_time(
982 other->scope->manager->event,
983 &other->timeout_event_source,
984 clock_boottime_or_monotonic(),
985 ts, 0,
986 on_transaction_timeout, other);
987 if (r < 0)
988 return r;
989
990 other->state = DNS_TRANSACTION_PENDING;
991 other->next_attempt_after = ts;
992
993 qdcount ++;
7778dfff
DM
994
995 if (dns_key_is_shared(other->key))
996 add_known_answers = true;
0afa57e2
DM
997 }
998
999 DNS_PACKET_HEADER(p)->qdcount = htobe16(qdcount);
0afa57e2 1000
7778dfff
DM
1001 /* Append known answer section if we're asking for any shared record */
1002 if (add_known_answers) {
1003 r = dns_cache_export_shared_to_packet(&t->scope->cache, p);
1004 if (r < 0)
1005 return r;
1006 }
1007
0afa57e2
DM
1008 t->sent = p;
1009 p = NULL;
1010
1011 return 0;
1012}
1013
1014static int dns_transaction_make_packet(DnsTransaction *t) {
1015 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1016 int r;
1017
1018 assert(t);
1019
1020 if (t->scope->protocol == DNS_PROTOCOL_MDNS)
1021 return dns_transaction_make_packet_mdns(t);
1022
1023 if (t->sent)
1024 return 0;
1025
b652d4a2 1026 r = dns_packet_new_query(&p, t->scope->protocol, 0, t->scope->dnssec_mode != DNSSEC_NO);
0afa57e2
DM
1027 if (r < 0)
1028 return r;
1029
1030 r = dns_scope_good_key(t->scope, t->key);
1031 if (r < 0)
1032 return r;
1033 if (r == 0)
1034 return -EDOM;
1035
1036 r = dns_packet_append_key(p, t->key, NULL);
1037 if (r < 0)
1038 return r;
1039
1040 DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
1041 DNS_PACKET_HEADER(p)->id = t->id;
1042
1043 t->sent = p;
1044 p = NULL;
1045
1046 return 0;
1047}
1048
1effe965
DM
1049int dns_transaction_go(DnsTransaction *t) {
1050 usec_t ts;
1051 int r;
1052
1053 assert(t);
1054
1055 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
547973de 1056
c842ff24 1057 r = dns_transaction_prepare(t, ts);
1effe965
DM
1058 if (r <= 0)
1059 return r;
1060
a5784c49
LP
1061 log_debug("Excercising transaction %" PRIu16 " for <%s> on scope %s on %s/%s.",
1062 t->id,
1063 dns_transaction_key_string(t),
1064 dns_protocol_to_string(t->scope->protocol),
1065 t->scope->link ? t->scope->link->name : "*",
1066 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family));
1effe965 1067
ef7ce6df 1068 if (!t->initial_jitter_scheduled &&
ea12bcc7
DM
1069 (t->scope->protocol == DNS_PROTOCOL_LLMNR ||
1070 t->scope->protocol == DNS_PROTOCOL_MDNS)) {
1071 usec_t jitter, accuracy;
6e068472
LP
1072
1073 /* RFC 4795 Section 2.7 suggests all queries should be
1074 * delayed by a random time from 0 to JITTER_INTERVAL. */
1075
ef7ce6df 1076 t->initial_jitter_scheduled = true;
6e068472
LP
1077
1078 random_bytes(&jitter, sizeof(jitter));
ea12bcc7
DM
1079
1080 switch (t->scope->protocol) {
1081 case DNS_PROTOCOL_LLMNR:
1082 jitter %= LLMNR_JITTER_INTERVAL_USEC;
1083 accuracy = LLMNR_JITTER_INTERVAL_USEC;
1084 break;
1085 case DNS_PROTOCOL_MDNS:
1086 jitter %= MDNS_JITTER_RANGE_USEC;
1087 jitter += MDNS_JITTER_MIN_USEC;
1088 accuracy = MDNS_JITTER_RANGE_USEC;
1089 break;
1090 default:
1091 assert_not_reached("bad protocol");
1092 }
6e068472
LP
1093
1094 r = sd_event_add_time(
1095 t->scope->manager->event,
1096 &t->timeout_event_source,
1097 clock_boottime_or_monotonic(),
ea12bcc7 1098 ts + jitter, accuracy,
6e068472
LP
1099 on_transaction_timeout, t);
1100 if (r < 0)
1101 return r;
1102
1103 t->n_attempts = 0;
a9da14e1 1104 t->next_attempt_after = ts;
6e068472
LP
1105 t->state = DNS_TRANSACTION_PENDING;
1106
ea12bcc7 1107 log_debug("Delaying %s transaction for " USEC_FMT "us.", dns_protocol_to_string(t->scope->protocol), jitter);
6e068472
LP
1108 return 0;
1109 }
1110
ec2c5e43
LP
1111 /* Otherwise, we need to ask the network */
1112 r = dns_transaction_make_packet(t);
1113 if (r == -EDOM) {
1114 /* Not the right request to make on this network?
1115 * (i.e. an A request made on IPv6 or an AAAA request
1116 * made on IPv4, on LLMNR or mDNS.) */
1117 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
1118 return 0;
1119 }
1120 if (r < 0)
1121 return r;
1122
1123 if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
f52e61da
LP
1124 (dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), "in-addr.arpa") > 0 ||
1125 dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), "ip6.arpa") > 0)) {
ec2c5e43
LP
1126
1127 /* RFC 4795, Section 2.4. says reverse lookups shall
1128 * always be made via TCP on LLMNR */
1129 r = dns_transaction_open_tcp(t);
1130 } else {
be808ea0
TG
1131 /* Try via UDP, and if that fails due to large size or lack of
1132 * support try via TCP */
49cce12d 1133 r = dns_transaction_emit_udp(t);
be808ea0 1134 if (r == -EMSGSIZE || r == -EAGAIN)
ec2c5e43
LP
1135 r = dns_transaction_open_tcp(t);
1136 }
be808ea0 1137
ec2c5e43
LP
1138 if (r == -ESRCH) {
1139 /* No servers to send this to? */
1140 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
1141 return 0;
8300ba21 1142 } else if (r < 0) {
13b551ac
LP
1143 if (t->scope->protocol != DNS_PROTOCOL_DNS) {
1144 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
1145 return 0;
1146 }
1147
ec2c5e43 1148 /* Couldn't send? Try immediately again, with a new server */
647f6aa8 1149 dns_transaction_next_dns_server(t);
ec2c5e43
LP
1150
1151 return dns_transaction_go(t);
1152 }
1153
a9da14e1
DM
1154 ts += transaction_get_resend_timeout(t);
1155
9a015429
LP
1156 r = sd_event_add_time(
1157 t->scope->manager->event,
1158 &t->timeout_event_source,
1159 clock_boottime_or_monotonic(),
a9da14e1 1160 ts, 0,
9a015429 1161 on_transaction_timeout, t);
ec2c5e43
LP
1162 if (r < 0)
1163 return r;
1164
1165 t->state = DNS_TRANSACTION_PENDING;
a9da14e1
DM
1166 t->next_attempt_after = ts;
1167
ec2c5e43
LP
1168 return 1;
1169}
1170
547973de
LP
1171static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResourceKey *key, DnsTransaction **ret) {
1172 DnsTransaction *aux;
1173 int r;
1174
1175 assert(t);
1176 assert(ret);
1177 assert(key);
1178
1179 aux = dns_scope_find_transaction(t->scope, key, true);
1180 if (!aux) {
1181 r = dns_transaction_new(&aux, t->scope, key);
1182 if (r < 0)
1183 return r;
1184 } else {
1185 if (set_contains(t->dnssec_transactions, aux)) {
1186 *ret = aux;
1187 return 0;
1188 }
1189 }
1190
1191 r = set_ensure_allocated(&t->dnssec_transactions, NULL);
1192 if (r < 0)
1193 goto gc;
1194
1195 r = set_ensure_allocated(&aux->notify_transactions, NULL);
1196 if (r < 0)
1197 goto gc;
1198
1199 r = set_put(t->dnssec_transactions, aux);
1200 if (r < 0)
1201 goto gc;
1202
1203 r = set_put(aux->notify_transactions, t);
1204 if (r < 0) {
1205 (void) set_remove(t->dnssec_transactions, aux);
1206 goto gc;
1207 }
1208
1209 *ret = aux;
1210 return 1;
1211
1212gc:
1213 dns_transaction_gc(aux);
1214 return r;
1215}
1216
1217static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *key) {
1218 _cleanup_(dns_answer_unrefp) DnsAnswer *a = NULL;
1219 DnsTransaction *aux;
1220 int r;
1221
1222 assert(t);
1223 assert(key);
1224
aae6a86e
LP
1225 r = dns_resource_key_equal(t->key, key);
1226 if (r < 0)
1227 return r;
1228 if (r > 0) /* Don't go in circles */
1229 return 0;
1230
547973de
LP
1231 /* Try to get the data from the trust anchor */
1232 r = dns_trust_anchor_lookup(&t->scope->manager->trust_anchor, key, &a);
1233 if (r < 0)
1234 return r;
1235 if (r > 0) {
1236 r = dns_answer_extend(&t->validated_keys, a);
1237 if (r < 0)
1238 return r;
1239
1240 return 0;
1241 }
1242
1243 /* This didn't work, ask for it via the network/cache then. */
1244 r = dns_transaction_add_dnssec_transaction(t, key, &aux);
1245 if (r < 0)
1246 return r;
1247
1248 if (aux->state == DNS_TRANSACTION_NULL) {
1249 r = dns_transaction_go(aux);
1250 if (r < 0)
1251 return r;
1252 }
1253
1254 return 0;
1255}
1256
105e1512
LP
1257static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) {
1258 int r;
1259
1260 assert(t);
1261
1262 /* Checks whether the answer is positive, i.e. either a direct
1263 * answer to the question, or a CNAME/DNAME for it */
1264
1265 r = dns_answer_match_key(t->answer, t->key, flags);
1266 if (r != 0)
1267 return r;
1268
1269 r = dns_answer_find_cname_or_dname(t->answer, t->key, NULL, flags);
1270 if (r != 0)
1271 return r;
1272
1273 return false;
1274}
1275
1276static int dns_transaction_has_unsigned_negative_answer(DnsTransaction *t) {
1277 int r;
1278
1279 assert(t);
1280
1281 /* Checks whether the answer is negative, and lacks NSEC/NSEC3
1282 * RRs to prove it */
1283
1284 r = dns_transaction_has_positive_answer(t, NULL);
1285 if (r < 0)
1286 return r;
1287 if (r > 0)
1288 return false;
1289
1290 /* The answer does not contain any RRs that match to the
1291 * question. If so, let's see if there are any NSEC/NSEC3 RRs
1292 * included. If not, the answer is unsigned. */
1293
1294 r = dns_answer_contains_nsec_or_nsec3(t->answer);
1295 if (r < 0)
1296 return r;
1297 if (r > 0)
1298 return false;
1299
1300 return true;
1301}
1302
1303static int dns_transaction_is_primary_response(DnsTransaction *t, DnsResourceRecord *rr) {
1304 int r;
1305
1306 assert(t);
1307 assert(rr);
1308
1309 /* Check if the specified RR is the "primary" response,
1310 * i.e. either matches the question precisely or is a
1311 * CNAME/DNAME for it, or is any kind of NSEC/NSEC3 RR */
1312
1313 r = dns_resource_key_match_rr(t->key, rr, NULL);
1314 if (r != 0)
1315 return r;
1316
1317 r = dns_resource_key_match_cname_or_dname(t->key, rr->key, NULL);
1318 if (r != 0)
1319 return r;
1320
1321 if (rr->key->type == DNS_TYPE_NSEC3) {
1322 const char *p;
1323
1324 p = DNS_RESOURCE_KEY_NAME(rr->key);
1325 r = dns_name_parent(&p);
1326 if (r < 0)
1327 return r;
1328 if (r > 0) {
1329 r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), p);
1330 if (r < 0)
1331 return r;
1332 if (r > 0)
1333 return true;
1334 }
1335 }
1336
1337 return rr->key->type == DNS_TYPE_NSEC;
1338}
1339
547973de
LP
1340int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
1341 DnsResourceRecord *rr;
105e1512 1342
547973de
LP
1343 int r;
1344
1345 assert(t);
1346
105e1512
LP
1347 /*
1348 * Retrieve all auxiliary RRs for the answer we got, so that
1349 * we can verify signatures or prove that RRs are rightfully
1350 * unsigned. Specifically:
1351 *
1352 * - For RRSIG we get the matching DNSKEY
1353 * - For DNSKEY we get the matching DS
1354 * - For unsigned SOA/NS we get the matching DS
b63fca62 1355 * - For unsigned CNAME/DNAME/DS we get the parent SOA RR
105e1512
LP
1356 * - For other unsigned RRs we get the matching SOA RR
1357 * - For SOA/NS/DS queries with no matching response RRs, and no NSEC/NSEC3, the parent's SOA RR
1358 * - For other queries with no matching response RRs, and no NSEC/NSEC3, the SOA RR
1359 */
1360
b652d4a2 1361 if (t->scope->dnssec_mode == DNSSEC_NO)
547973de
LP
1362 return 0;
1363
b652d4a2
LP
1364 if (t->current_features < DNS_SERVER_FEATURE_LEVEL_DO)
1365 return 0; /* Server doesn't do DNSSEC, there's no point in requesting any RRs then. */
1366 if (t->server && t->server->rrsig_missing)
1367 return 0; /* Server handles DNSSEC requests, but isn't augmenting responses with RRSIGs. No point in trying DNSSEC then. */
1368
547973de
LP
1369 DNS_ANSWER_FOREACH(rr, t->answer) {
1370
105e1512
LP
1371 if (dns_type_is_pseudo(rr->key->type))
1372 continue;
1373
547973de
LP
1374 switch (rr->key->type) {
1375
1376 case DNS_TYPE_RRSIG: {
1377 /* For each RRSIG we request the matching DNSKEY */
1378 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *dnskey = NULL;
1379
1380 /* If this RRSIG is about a DNSKEY RR and the
1381 * signer is the same as the owner, then we
1382 * already have the DNSKEY, and we don't have
1383 * to look for more. */
1384 if (rr->rrsig.type_covered == DNS_TYPE_DNSKEY) {
1385 r = dns_name_equal(rr->rrsig.signer, DNS_RESOURCE_KEY_NAME(rr->key));
1386 if (r < 0)
1387 return r;
1388 if (r > 0)
1389 continue;
1390 }
1391
105e1512
LP
1392 /* If the signer is not a parent of our
1393 * original query, then this is about an
1394 * auxiliary RRset, but not anything we asked
1395 * for. In this case we aren't interested,
1396 * because we don't want to request additional
1397 * RRs for stuff we didn't really ask for, and
1398 * also to avoid request loops, where
1399 * additional RRs from one transaction result
1400 * in another transaction whose additonal RRs
1401 * point back to the original transaction, and
1402 * we deadlock. */
1403 r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), rr->rrsig.signer);
547973de
LP
1404 if (r < 0)
1405 return r;
1406 if (r == 0)
1407 continue;
1408
1409 dnskey = dns_resource_key_new(rr->key->class, DNS_TYPE_DNSKEY, rr->rrsig.signer);
1410 if (!dnskey)
1411 return -ENOMEM;
1412
105e1512 1413 log_debug("Requesting DNSKEY to validate transaction %" PRIu16" (%s, RRSIG with key tag: %" PRIu16 ").", t->id, DNS_RESOURCE_KEY_NAME(rr->key), rr->rrsig.key_tag);
547973de
LP
1414 r = dns_transaction_request_dnssec_rr(t, dnskey);
1415 if (r < 0)
1416 return r;
1417 break;
1418 }
1419
1420 case DNS_TYPE_DNSKEY: {
1421 /* For each DNSKEY we request the matching DS */
1422 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
1423
105e1512
LP
1424 /* If the DNSKEY we are looking at is not for
1425 * zone we are interested in, nor any of its
1426 * parents, we aren't interested, and don't
1427 * request it. After all, we don't want to end
1428 * up in request loops, and want to keep
1429 * additional traffic down. */
1430
1431 r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), DNS_RESOURCE_KEY_NAME(rr->key));
1432 if (r < 0)
1433 return r;
1434 if (r == 0)
1435 continue;
1436
547973de
LP
1437 ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, DNS_RESOURCE_KEY_NAME(rr->key));
1438 if (!ds)
1439 return -ENOMEM;
1440
105e1512
LP
1441 log_debug("Requesting DS to validate transaction %" PRIu16" (%s, DNSKEY with key tag: %" PRIu16 ").", t->id, DNS_RESOURCE_KEY_NAME(rr->key), dnssec_keytag(rr));
1442 r = dns_transaction_request_dnssec_rr(t, ds);
1443 if (r < 0)
1444 return r;
547973de 1445
105e1512
LP
1446 break;
1447 }
1448
105e1512
LP
1449 case DNS_TYPE_SOA:
1450 case DNS_TYPE_NS: {
1451 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
1452
1453 /* For an unsigned SOA or NS, try to acquire
1454 * the matching DS RR, as we are at a zone cut
1455 * then, and whether a DS exists tells us
1456 * whether the zone is signed. Do so only if
1457 * this RR matches our original question,
1458 * however. */
1459
1460 r = dns_resource_key_match_rr(t->key, rr, NULL);
1461 if (r < 0)
1462 return r;
1463 if (r == 0)
1464 continue;
1465
1466 r = dnssec_has_rrsig(t->answer, rr->key);
1467 if (r < 0)
1468 return r;
1469 if (r > 0)
1470 continue;
1471
1472 ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, DNS_RESOURCE_KEY_NAME(rr->key));
1473 if (!ds)
1474 return -ENOMEM;
1475
1476 log_debug("Requesting DS to validate transaction %" PRIu16 " (%s, unsigned SOA/NS RRset).", t->id, DNS_RESOURCE_KEY_NAME(rr->key));
547973de
LP
1477 r = dns_transaction_request_dnssec_rr(t, ds);
1478 if (r < 0)
1479 return r;
1480
1481 break;
105e1512
LP
1482 }
1483
b63fca62 1484 case DNS_TYPE_DS:
105e1512
LP
1485 case DNS_TYPE_CNAME:
1486 case DNS_TYPE_DNAME: {
1487 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
1488 const char *name;
1489
1490 /* CNAMEs and DNAMEs cannot be located at a
1491 * zone apex, hence ask for the parent SOA for
1492 * unsigned CNAME/DNAME RRs, maybe that's the
1493 * apex. But do all that only if this is
1494 * actually a response to our original
b63fca62
LP
1495 * question.
1496 *
1497 * Similar for DS RRs, which are signed when
1498 * the parent SOA is signed. */
105e1512
LP
1499
1500 r = dns_transaction_is_primary_response(t, rr);
1501 if (r < 0)
1502 return r;
1503 if (r == 0)
1504 continue;
1505
1506 r = dnssec_has_rrsig(t->answer, rr->key);
1507 if (r < 0)
1508 return r;
1509 if (r > 0)
1510 continue;
1511
1512 name = DNS_RESOURCE_KEY_NAME(rr->key);
1513 r = dns_name_parent(&name);
1514 if (r < 0)
1515 return r;
1516 if (r == 0)
1517 continue;
1518
1519 soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, name);
1520 if (!soa)
1521 return -ENOMEM;
1522
b63fca62 1523 log_debug("Requesting parent SOA to validate transaction %" PRIu16 " (%s, unsigned CNAME/DNAME/DS RRset).", t->id, DNS_RESOURCE_KEY_NAME(rr->key));
105e1512
LP
1524 r = dns_transaction_request_dnssec_rr(t, soa);
1525 if (r < 0)
1526 return r;
1527
1528 break;
1529 }
1530
1531 default: {
1532 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
1533
b63fca62
LP
1534 /* For other unsigned RRsets (including
1535 * NSEC/NSEC3!), look for proof the zone is
1536 * unsigned, by requesting the SOA RR of the
1537 * zone. However, do so only if they are
1538 * directly relevant to our original
105e1512
LP
1539 * question. */
1540
1541 r = dns_transaction_is_primary_response(t, rr);
1542 if (r < 0)
1543 return r;
1544 if (r == 0)
1545 continue;
1546
1547 r = dnssec_has_rrsig(t->answer, rr->key);
1548 if (r < 0)
1549 return r;
1550 if (r > 0)
1551 continue;
1552
1553 soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, DNS_RESOURCE_KEY_NAME(rr->key));
1554 if (!soa)
1555 return -ENOMEM;
1556
db5b0e92 1557 log_debug("Requesting SOA to validate transaction %" PRIu16 " (%s, unsigned non-SOA/NS RRset <%s>).", t->id, DNS_RESOURCE_KEY_NAME(rr->key), dns_resource_record_to_string(rr));
105e1512
LP
1558 r = dns_transaction_request_dnssec_rr(t, soa);
1559 if (r < 0)
1560 return r;
1561 break;
547973de
LP
1562 }}
1563 }
1564
105e1512
LP
1565 /* Above, we requested everything necessary to validate what
1566 * we got. Now, let's request what we need to validate what we
1567 * didn't get... */
1568
1569 r = dns_transaction_has_unsigned_negative_answer(t);
1570 if (r < 0)
1571 return r;
1572 if (r > 0) {
1573 const char *name;
1574
1575 name = DNS_RESOURCE_KEY_NAME(t->key);
1576
1577 /* If this was a SOA or NS request, then this
1578 * indicates that we are not at a zone apex, hence ask
1579 * the parent name instead. If this was a DS request,
1580 * then it's signed when the parent zone is signed,
1581 * hence ask the parent in that case, too. */
1582
1583 if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS, DNS_TYPE_DS)) {
1584 r = dns_name_parent(&name);
1585 if (r < 0)
1586 return r;
1587 if (r > 0)
1588 log_debug("Requesting parent SOA to validate transaction %" PRIu16 " (%s, unsigned empty SOA/NS/DS response).", t->id, DNS_RESOURCE_KEY_NAME(t->key));
1589 else
1590 name = NULL;
1591 } else
1592 log_debug("Requesting SOA to validate transaction %" PRIu16 " (%s, unsigned empty non-SOA/NS/DS response).", t->id, DNS_RESOURCE_KEY_NAME(t->key));
1593
1594 if (name) {
1595 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
1596
1597 soa = dns_resource_key_new(t->key->class, DNS_TYPE_SOA, name);
1598 if (!soa)
1599 return -ENOMEM;
1600
1601 r = dns_transaction_request_dnssec_rr(t, soa);
1602 if (r < 0)
1603 return r;
1604 }
1605 }
1606
1607 return dns_transaction_dnssec_is_live(t);
547973de
LP
1608}
1609
1610void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source) {
1611 int r;
1612
1613 assert(t);
547973de
LP
1614 assert(source);
1615
105e1512
LP
1616 if (!IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING))
1617 return;
1618
547973de 1619 /* Invoked whenever any of our auxiliary DNSSEC transactions
105e1512
LP
1620 completed its work. We copy any RRs from that transaction
1621 over into our list of validated keys -- but only if the
1622 answer is authenticated.
1623
1624 Note that we fail our transaction if the auxiliary
1625 transaction failed, except on NXDOMAIN. This is because
1626 some broken DNS servers (Akamai...) will return NXDOMAIN
1627 for empty non-terminals. */
1628
6773896e 1629 switch (source->state) {
547973de 1630
6773896e
LP
1631 case DNS_TRANSACTION_DNSSEC_FAILED:
1632
1633 log_debug("Auxiliary DNSSEC RR query failed validation: %s", dnssec_result_to_string(source->answer_dnssec_result));
1634 t->answer_dnssec_result = source->answer_dnssec_result; /* Copy error code over */
1635 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
1636 break;
1637
1638 case DNS_TRANSACTION_RCODE_FAILURE:
1639
1640 if (source->answer_rcode != DNS_RCODE_NXDOMAIN) {
1641 log_debug("Auxiliary DNSSEC RR query failed with rcode=%i.", source->answer_rcode);
105e1512 1642 goto fail;
547973de 1643 }
547973de 1644
6773896e
LP
1645 /* fall-through: NXDOMAIN is good enough for us */
1646
1647 case DNS_TRANSACTION_SUCCESS:
1648 if (source->answer_authenticated) {
1649 r = dns_answer_extend(&t->validated_keys, source->answer);
1650 if (r < 0) {
1651 log_error_errno(r, "Failed to merge validated DNSSEC key data: %m");
1652 goto fail;
1653 }
1654 }
1655
1656 /* If the state is still PENDING, we are still in the loop
1657 * that adds further DNSSEC transactions, hence don't check if
1658 * we are ready yet. If the state is VALIDATING however, we
1659 * should check if we are complete now. */
1660 if (t->state == DNS_TRANSACTION_VALIDATING)
1661 dns_transaction_process_dnssec(t);
1662 break;
1663
1664 default:
1665 log_debug("Auxiliary DNSSEC RR query failed with %s", dns_transaction_state_to_string(source->state));
1666 goto fail;
1667 }
105e1512
LP
1668
1669 return;
1670
1671fail:
019036a4 1672 t->answer_dnssec_result = DNSSEC_FAILED_AUXILIARY;
105e1512 1673 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
547973de
LP
1674}
1675
105e1512
LP
1676static int dns_transaction_validate_dnskey_by_ds(DnsTransaction *t) {
1677 DnsResourceRecord *rr;
1678 int ifindex, r;
1679
1680 assert(t);
1681
1682 /* Add all DNSKEY RRs from the answer that are validated by DS
1683 * RRs from the list of validated keys to the list of
1684 * validated keys. */
1685
1686 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, t->answer) {
1687
1688 r = dnssec_verify_dnskey_search(rr, t->validated_keys);
1689 if (r < 0)
1690 return r;
1691 if (r == 0)
1692 continue;
1693
1694 /* If so, the DNSKEY is validated too. */
1695 r = dns_answer_add_extend(&t->validated_keys, rr, ifindex, DNS_ANSWER_AUTHENTICATED);
1696 if (r < 0)
1697 return r;
1698 }
1699
1700 return 0;
1701}
1702
1703static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *rr) {
56352fe9
LP
1704 int r;
1705
1706 assert(t);
1707 assert(rr);
1708
105e1512
LP
1709 /* Checks if the RR we are looking for must be signed with an
1710 * RRSIG. This is used for positive responses. */
24a5b982 1711
b652d4a2 1712 if (t->scope->dnssec_mode == DNSSEC_NO)
105e1512 1713 return false;
56352fe9 1714
105e1512
LP
1715 if (dns_type_is_pseudo(rr->key->type))
1716 return -EINVAL;
56352fe9 1717
105e1512 1718 switch (rr->key->type) {
56352fe9 1719
105e1512
LP
1720 case DNS_TYPE_RRSIG:
1721 /* RRSIGs are the signatures themselves, they need no signing. */
1722 return false;
1723
1724 case DNS_TYPE_SOA:
1725 case DNS_TYPE_NS: {
1726 DnsTransaction *dt;
1727 Iterator i;
1728
b63fca62 1729 /* For SOA or NS RRs we look for a matching DS transaction */
105e1512
LP
1730
1731 SET_FOREACH(dt, t->dnssec_transactions, i) {
1732
1733 if (dt->key->class != rr->key->class)
1734 continue;
1735 if (dt->key->type != DNS_TYPE_DS)
1736 continue;
1737
1738 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), DNS_RESOURCE_KEY_NAME(rr->key));
1739 if (r < 0)
1740 return r;
1741 if (r == 0)
1742 continue;
1743
1744 /* We found a DS transactions for the SOA/NS
1745 * RRs we are looking at. If it discovered signed DS
1746 * RRs, then we need to be signed, too. */
1747
097a2517
TA
1748 if (!dt->answer_authenticated)
1749 return false;
105e1512 1750
097a2517 1751 return dns_answer_match_key(dt->answer, dt->key, NULL);
105e1512
LP
1752 }
1753
1754 /* We found nothing that proves this is safe to leave
1755 * this unauthenticated, hence ask inist on
1756 * authentication. */
1757 return true;
1758 }
1759
b63fca62 1760 case DNS_TYPE_DS:
105e1512
LP
1761 case DNS_TYPE_CNAME:
1762 case DNS_TYPE_DNAME: {
1763 const char *parent = NULL;
1764 DnsTransaction *dt;
1765 Iterator i;
1766
b63fca62
LP
1767 /*
1768 * CNAME/DNAME RRs cannot be located at a zone apex, hence look directly for the parent SOA.
1769 *
1770 * DS RRs are signed if the parent is signed, hence also look at the parent SOA
1771 */
105e1512
LP
1772
1773 SET_FOREACH(dt, t->dnssec_transactions, i) {
1774
1775 if (dt->key->class != rr->key->class)
1776 continue;
1777 if (dt->key->type != DNS_TYPE_SOA)
1778 continue;
1779
1780 if (!parent) {
1781 parent = DNS_RESOURCE_KEY_NAME(rr->key);
1782 r = dns_name_parent(&parent);
1783 if (r < 0)
1784 return r;
1785 if (r == 0) {
b63fca62
LP
1786 if (rr->key->type == DNS_TYPE_DS)
1787 return true;
1788
105e1512
LP
1789 /* A CNAME/DNAME without a parent? That's sooo weird. */
1790 log_debug("Transaction %" PRIu16 " claims CNAME/DNAME at root. Refusing.", t->id);
1791 return -EBADMSG;
1792 }
1793 }
1794
1795 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), parent);
1796 if (r < 0)
1797 return r;
1798 if (r == 0)
1799 continue;
1800
1801 return t->answer_authenticated;
1802 }
1803
1804 return true;
1805 }
1806
1807 default: {
1808 DnsTransaction *dt;
1809 Iterator i;
1810
b63fca62 1811 /* Any other kind of RR (including DNSKEY/NSEC/NSEC3). Let's see if our SOA lookup was authenticated */
105e1512
LP
1812
1813 SET_FOREACH(dt, t->dnssec_transactions, i) {
1814
1815 if (dt->key->class != rr->key->class)
1816 continue;
1817 if (dt->key->type != DNS_TYPE_SOA)
1818 continue;
1819
1820 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), DNS_RESOURCE_KEY_NAME(rr->key));
1821 if (r < 0)
1822 return r;
1823 if (r == 0)
1824 continue;
1825
1826 /* We found the transaction that was supposed to find
1827 * the SOA RR for us. It was successful, but found no
1828 * RR for us. This means we are not at a zone cut. In
1829 * this case, we require authentication if the SOA
1830 * lookup was authenticated too. */
1831 return t->answer_authenticated;
1832 }
1833
1834 return true;
1835 }}
56352fe9
LP
1836}
1837
105e1512
LP
1838static int dns_transaction_requires_nsec(DnsTransaction *t) {
1839 DnsTransaction *dt;
1840 const char *name;
1841 Iterator i;
1842 int r;
56352fe9
LP
1843
1844 assert(t);
1845
105e1512
LP
1846 /* Checks if we need to insist on NSEC/NSEC3 RRs for proving
1847 * this negative reply */
56352fe9 1848
b652d4a2 1849 if (t->scope->dnssec_mode == DNSSEC_NO)
105e1512 1850 return false;
56352fe9 1851
105e1512
LP
1852 if (dns_type_is_pseudo(t->key->type))
1853 return -EINVAL;
1854
1855 name = DNS_RESOURCE_KEY_NAME(t->key);
1856
1857 if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS, DNS_TYPE_DS)) {
1858
1859 /* We got a negative reply for this SOA/NS lookup? If
1860 * so, then we are not at a zone apex, and thus should
1861 * look at the result of the parent SOA lookup.
1862 *
1863 * We got a negative reply for this DS lookup? DS RRs
1864 * are signed when their parent zone is signed, hence
1865 * also check the parent SOA in this case. */
1866
1867 r = dns_name_parent(&name);
56352fe9
LP
1868 if (r < 0)
1869 return r;
1870 if (r == 0)
105e1512
LP
1871 return true;
1872 }
1873
1874 /* For all other RRs we check the SOA on the same level to see
1875 * if it's signed. */
1876
1877 SET_FOREACH(dt, t->dnssec_transactions, i) {
1878
1879 if (dt->key->class != t->key->class)
1880 continue;
1881 if (dt->key->type != DNS_TYPE_SOA)
56352fe9
LP
1882 continue;
1883
105e1512 1884 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), name);
56352fe9
LP
1885 if (r < 0)
1886 return r;
105e1512
LP
1887 if (r == 0)
1888 continue;
1889
1890 return dt->answer_authenticated;
56352fe9
LP
1891 }
1892
105e1512
LP
1893 /* If in doubt, require NSEC/NSEC3 */
1894 return true;
56352fe9
LP
1895}
1896
94aa7071
LP
1897static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRecord *rr) {
1898 DnsResourceRecord *rrsig;
1899 bool found = false;
1900 int r;
1901
1902 /* Checks whether any of the DNSKEYs used for the RRSIGs for
1903 * the specified RRset is authenticated (i.e. has a matching
1904 * DS RR). */
1905
1906 DNS_ANSWER_FOREACH(rrsig, t->answer) {
1907 DnsTransaction *dt;
1908 Iterator i;
1909
1910 r = dnssec_key_match_rrsig(rr->key, rrsig);
1911 if (r < 0)
1912 return r;
1913 if (r == 0)
1914 continue;
1915
1916 SET_FOREACH(dt, t->dnssec_transactions, i) {
1917
1918 if (dt->key->class != rr->key->class)
1919 continue;
1920
1921 if (dt->key->type == DNS_TYPE_DNSKEY) {
1922
1923 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), rrsig->rrsig.signer);
1924 if (r < 0)
1925 return r;
1926 if (r == 0)
1927 continue;
1928
1929 /* OK, we found an auxiliary DNSKEY
1930 * lookup. If that lookup is
1931 * authenticated, report this. */
1932
1933 if (dt->answer_authenticated)
1934 return true;
1935
1936 found = true;
1937
1938 } else if (dt->key->type == DNS_TYPE_DS) {
1939
1940 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), rrsig->rrsig.signer);
1941 if (r < 0)
1942 return r;
1943 if (r == 0)
1944 continue;
1945
1946 /* OK, we found an auxiliary DS
1947 * lookup. If that lookup is
1948 * authenticated and non-zero, we
1949 * won! */
1950
1951 if (!dt->answer_authenticated)
1952 return false;
1953
1954 return dns_answer_match_key(dt->answer, dt->key, NULL);
1955 }
1956 }
1957 }
1958
1959 return found ? false : -ENXIO;
1960}
1961
b652d4a2
LP
1962static int dns_transaction_known_signed(DnsTransaction *t, DnsResourceRecord *rr) {
1963 assert(t);
1964 assert(rr);
1965
1966 /* We know that the root domain is signed, hence if it appears
1967 * not to be signed, there's a problem with the DNS server */
1968
1969 return rr->key->class == DNS_CLASS_IN &&
1970 dns_name_is_root(DNS_RESOURCE_KEY_NAME(rr->key));
1971}
1972
547973de
LP
1973int dns_transaction_validate_dnssec(DnsTransaction *t) {
1974 _cleanup_(dns_answer_unrefp) DnsAnswer *validated = NULL;
56352fe9 1975 bool dnskeys_finalized = false;
547973de 1976 DnsResourceRecord *rr;
105e1512 1977 DnsAnswerFlags flags;
56352fe9 1978 int r;
547973de
LP
1979
1980 assert(t);
1981
1982 /* We have now collected all DS and DNSKEY RRs in
1983 * t->validated_keys, let's see which RRs we can now
1984 * authenticate with that. */
1985
b652d4a2 1986 if (t->scope->dnssec_mode == DNSSEC_NO)
547973de
LP
1987 return 0;
1988
1989 /* Already validated */
019036a4 1990 if (t->answer_dnssec_result != _DNSSEC_RESULT_INVALID)
547973de
LP
1991 return 0;
1992
105e1512 1993 /* Our own stuff needs no validation */
547973de 1994 if (IN_SET(t->answer_source, DNS_TRANSACTION_ZONE, DNS_TRANSACTION_TRUST_ANCHOR)) {
019036a4 1995 t->answer_dnssec_result = DNSSEC_VALIDATED;
547973de
LP
1996 t->answer_authenticated = true;
1997 return 0;
1998 }
1999
105e1512
LP
2000 /* Cached stuff is not affected by validation. */
2001 if (t->answer_source != DNS_TRANSACTION_NETWORK)
2002 return 0;
2003
b652d4a2
LP
2004 if (t->current_features < DNS_SERVER_FEATURE_LEVEL_DO ||
2005 (t->server && t->server->rrsig_missing)) {
2006 /* The server does not support DNSSEC, or doesn't augment responses with RRSIGs. */
2007 t->answer_dnssec_result = DNSSEC_INCOMPATIBLE_SERVER;
2008 return 0;
2009 }
2010
a5784c49 2011 log_debug("Validating response from transaction %" PRIu16 " (%s).", t->id, dns_transaction_key_string(t));
547973de
LP
2012
2013 /* First see if there are DNSKEYs we already known a validated DS for. */
56352fe9
LP
2014 r = dns_transaction_validate_dnskey_by_ds(t);
2015 if (r < 0)
2016 return r;
547973de
LP
2017
2018 for (;;) {
56352fe9 2019 bool changed = false;
547973de
LP
2020
2021 DNS_ANSWER_FOREACH(rr, t->answer) {
2022 DnssecResult result;
2023
2024 if (rr->key->type == DNS_TYPE_RRSIG)
2025 continue;
2026
2027 r = dnssec_verify_rrset_search(t->answer, rr->key, t->validated_keys, USEC_INFINITY, &result);
2028 if (r < 0)
2029 return r;
2030
7b50eb2e 2031 log_debug("Looking at %s: %s", strna(dns_resource_record_to_string(rr)), dnssec_result_to_string(result));
547973de 2032
56352fe9 2033 if (result == DNSSEC_VALIDATED) {
547973de 2034
547973de
LP
2035 if (rr->key->type == DNS_TYPE_DNSKEY) {
2036 /* If we just validated a
2037 * DNSKEY RRset, then let's
2038 * add these keys to the set
2039 * of validated keys for this
2040 * transaction. */
2041
105e1512 2042 r = dns_answer_copy_by_key(&t->validated_keys, t->answer, rr->key, DNS_ANSWER_AUTHENTICATED);
547973de
LP
2043 if (r < 0)
2044 return r;
2045 }
2046
105e1512
LP
2047 /* Add the validated RRset to the new
2048 * list of validated RRsets, and
2049 * remove it from the unvalidated
2050 * RRsets. We mark the RRset as
2051 * authenticated and cacheable. */
2052 r = dns_answer_move_by_key(&validated, &t->answer, rr->key, DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE);
547973de
LP
2053 if (r < 0)
2054 return r;
2055
a150ff5e
LP
2056 t->scope->manager->n_dnssec_secure++;
2057
56352fe9 2058 /* Exit the loop, we dropped something from the answer, start from the beginning */
547973de
LP
2059 changed = true;
2060 break;
2061
56352fe9 2062 } else if (dnskeys_finalized) {
94aa7071 2063
56352fe9
LP
2064 /* If we haven't read all DNSKEYs yet
2065 * a negative result of the validation
2066 * is irrelevant, as there might be
2067 * more DNSKEYs coming. */
547973de 2068
105e1512
LP
2069 if (result == DNSSEC_NO_SIGNATURE) {
2070 r = dns_transaction_requires_rrsig(t, rr);
2071 if (r < 0)
2072 return r;
2073 if (r == 0) {
2074 /* Data does not require signing. In that case, just copy it over,
2075 * but remember that this is by no means authenticated.*/
2076 r = dns_answer_move_by_key(&validated, &t->answer, rr->key, 0);
2077 if (r < 0)
2078 return r;
2079
a150ff5e
LP
2080 t->scope->manager->n_dnssec_insecure++;
2081
105e1512
LP
2082 changed = true;
2083 break;
2084 }
b652d4a2
LP
2085
2086 r = dns_transaction_known_signed(t, rr);
2087 if (r < 0)
2088 return r;
2089 if (r > 0) {
2090 /* This is an RR we know has to be signed. If it isn't this means
2091 * the server is not attaching RRSIGs, hence complain. */
2092
2093 dns_server_packet_rrsig_missing(t->server);
2094
2095 if (t->scope->dnssec_mode == DNSSEC_DOWNGRADE_OK) {
2096
2097 /* Downgrading is OK? If so, just consider the information unsigned */
2098
2099 r = dns_answer_move_by_key(&validated, &t->answer, rr->key, 0);
2100 if (r < 0)
2101 return r;
2102
2103 t->scope->manager->n_dnssec_insecure++;
2104 changed = true;
2105 break;
2106 }
2107
2108 /* Otherwise, fail */
2109 t->answer_dnssec_result = DNSSEC_INCOMPATIBLE_SERVER;
2110 return 0;
2111 }
94aa7071
LP
2112 }
2113
2114 if (IN_SET(result,
2115 DNSSEC_MISSING_KEY,
2116 DNSSEC_SIGNATURE_EXPIRED,
2117 DNSSEC_UNSUPPORTED_ALGORITHM)) {
2118
2119 r = dns_transaction_dnskey_authenticated(t, rr);
2120 if (r < 0 && r != -ENXIO)
2121 return r;
2122 if (r == 0) {
2123 /* The DNSKEY transaction was not authenticated, this means there's
2124 * no DS for this, which means it's OK if no keys are found for this signature. */
2125
2126 r = dns_answer_move_by_key(&validated, &t->answer, rr->key, 0);
2127 if (r < 0)
2128 return r;
2129
a150ff5e
LP
2130 t->scope->manager->n_dnssec_insecure++;
2131
94aa7071
LP
2132 changed = true;
2133 break;
2134 }
105e1512
LP
2135 }
2136
a150ff5e
LP
2137 if (IN_SET(result,
2138 DNSSEC_INVALID,
2139 DNSSEC_SIGNATURE_EXPIRED,
2140 DNSSEC_NO_SIGNATURE,
2141 DNSSEC_UNSUPPORTED_ALGORITHM))
2142 t->scope->manager->n_dnssec_bogus++;
2143 else
2144 t->scope->manager->n_dnssec_indeterminate++;
2145
56352fe9 2146 r = dns_transaction_is_primary_response(t, rr);
547973de
LP
2147 if (r < 0)
2148 return r;
2149 if (r > 0) {
56352fe9
LP
2150 /* This is a primary response
2151 * to our question, and it
2152 * failed validation. That's
2153 * fatal. */
019036a4 2154 t->answer_dnssec_result = result;
547973de
LP
2155 return 0;
2156 }
2157
56352fe9
LP
2158 /* This is just some auxiliary
2159 * data. Just remove the RRset and
2160 * continue. */
547973de
LP
2161 r = dns_answer_remove_by_key(&t->answer, rr->key);
2162 if (r < 0)
2163 return r;
2164
56352fe9 2165 /* Exit the loop, we dropped something from the answer, start from the beginning */
547973de
LP
2166 changed = true;
2167 break;
547973de 2168 }
547973de
LP
2169 }
2170
2171 if (changed)
2172 continue;
2173
56352fe9
LP
2174 if (!dnskeys_finalized) {
2175 /* OK, now we know we have added all DNSKEYs
2176 * we possibly could to our validated
2177 * list. Now run the whole thing once more,
2178 * and strip everything we still cannot
2179 * validate.
2180 */
2181 dnskeys_finalized = true;
2182 continue;
547973de
LP
2183 }
2184
56352fe9 2185 /* We're done */
547973de
LP
2186 break;
2187 }
2188
2189 dns_answer_unref(t->answer);
2190 t->answer = validated;
2191 validated = NULL;
2192
72667f08
LP
2193 /* At this point the answer only contains validated
2194 * RRsets. Now, let's see if it actually answers the question
2195 * we asked. If so, great! If it doesn't, then see if
2196 * NSEC/NSEC3 can prove this. */
105e1512 2197 r = dns_transaction_has_positive_answer(t, &flags);
72667f08 2198 if (r > 0) {
105e1512
LP
2199 /* Yes, it answers the question! */
2200
2201 if (flags & DNS_ANSWER_AUTHENTICATED) {
2202 /* The answer is fully authenticated, yay. */
019036a4 2203 t->answer_dnssec_result = DNSSEC_VALIDATED;
105e1512
LP
2204 t->answer_rcode = DNS_RCODE_SUCCESS;
2205 t->answer_authenticated = true;
2206 } else {
2207 /* The answer is not fully authenticated. */
019036a4 2208 t->answer_dnssec_result = DNSSEC_UNSIGNED;
105e1512
LP
2209 t->answer_authenticated = false;
2210 }
2211
72667f08
LP
2212 } else if (r == 0) {
2213 DnssecNsecResult nr;
ed29bfdc 2214 bool authenticated = false;
72667f08
LP
2215
2216 /* Bummer! Let's check NSEC/NSEC3 */
ed29bfdc 2217 r = dnssec_test_nsec(t->answer, t->key, &nr, &authenticated);
72667f08
LP
2218 if (r < 0)
2219 return r;
2220
2221 switch (nr) {
2222
2223 case DNSSEC_NSEC_NXDOMAIN:
2224 /* NSEC proves the domain doesn't exist. Very good. */
105e1512 2225 log_debug("Proved NXDOMAIN via NSEC/NSEC3 for transaction %u (%s)", t->id, dns_transaction_key_string(t));
019036a4 2226 t->answer_dnssec_result = DNSSEC_VALIDATED;
72667f08 2227 t->answer_rcode = DNS_RCODE_NXDOMAIN;
ed29bfdc 2228 t->answer_authenticated = authenticated;
72667f08
LP
2229 break;
2230
2231 case DNSSEC_NSEC_NODATA:
2232 /* NSEC proves that there's no data here, very good. */
105e1512 2233 log_debug("Proved NODATA via NSEC/NSEC3 for transaction %u (%s)", t->id, dns_transaction_key_string(t));
019036a4 2234 t->answer_dnssec_result = DNSSEC_VALIDATED;
72667f08 2235 t->answer_rcode = DNS_RCODE_SUCCESS;
ed29bfdc 2236 t->answer_authenticated = authenticated;
72667f08
LP
2237 break;
2238
105e1512
LP
2239 case DNSSEC_NSEC_OPTOUT:
2240 /* NSEC3 says the data might not be signed */
2241 log_debug("Data is NSEC3 opt-out via NSEC/NSEC3 for transaction %u (%s)", t->id, dns_transaction_key_string(t));
019036a4 2242 t->answer_dnssec_result = DNSSEC_UNSIGNED;
105e1512
LP
2243 t->answer_authenticated = false;
2244 break;
2245
72667f08
LP
2246 case DNSSEC_NSEC_NO_RR:
2247 /* No NSEC data? Bummer! */
105e1512
LP
2248
2249 r = dns_transaction_requires_nsec(t);
2250 if (r < 0)
2251 return r;
2252 if (r > 0)
019036a4 2253 t->answer_dnssec_result = DNSSEC_NO_SIGNATURE;
105e1512 2254 else {
019036a4 2255 t->answer_dnssec_result = DNSSEC_UNSIGNED;
105e1512
LP
2256 t->answer_authenticated = false;
2257 }
2258
2259 break;
2260
2261 case DNSSEC_NSEC_UNSUPPORTED_ALGORITHM:
2262 /* We don't know the NSEC3 algorithm used? */
019036a4 2263 t->answer_dnssec_result = DNSSEC_UNSUPPORTED_ALGORITHM;
72667f08
LP
2264 break;
2265
2266 case DNSSEC_NSEC_FOUND:
2267 /* NSEC says it needs to be there, but we couldn't find it? Bummer! */
019036a4 2268 t->answer_dnssec_result = DNSSEC_NSEC_MISMATCH;
72667f08
LP
2269 break;
2270
2271 default:
2272 assert_not_reached("Unexpected NSEC result.");
2273 }
2274 }
2275
547973de
LP
2276 return 1;
2277}
2278
a5784c49
LP
2279const char *dns_transaction_key_string(DnsTransaction *t) {
2280 assert(t);
2281
2282 if (!t->key_string) {
2283 if (dns_resource_key_to_string(t->key, &t->key_string) < 0)
2284 return "n/a";
2285 }
2286
2287 return strstrip(t->key_string);
2288}
2289
ec2c5e43
LP
2290static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {
2291 [DNS_TRANSACTION_NULL] = "null",
2292 [DNS_TRANSACTION_PENDING] = "pending",
547973de 2293 [DNS_TRANSACTION_VALIDATING] = "validating",
3bbdc31d 2294 [DNS_TRANSACTION_RCODE_FAILURE] = "rcode-failure",
ec2c5e43
LP
2295 [DNS_TRANSACTION_SUCCESS] = "success",
2296 [DNS_TRANSACTION_NO_SERVERS] = "no-servers",
2297 [DNS_TRANSACTION_TIMEOUT] = "timeout",
2298 [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached",
2299 [DNS_TRANSACTION_INVALID_REPLY] = "invalid-reply",
2300 [DNS_TRANSACTION_RESOURCES] = "resources",
ac720200 2301 [DNS_TRANSACTION_CONNECTION_FAILURE] = "connection-failure",
ec2c5e43 2302 [DNS_TRANSACTION_ABORTED] = "aborted",
547973de 2303 [DNS_TRANSACTION_DNSSEC_FAILED] = "dnssec-failed",
ec2c5e43
LP
2304};
2305DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);
c3bc53e6
LP
2306
2307static const char* const dns_transaction_source_table[_DNS_TRANSACTION_SOURCE_MAX] = {
2308 [DNS_TRANSACTION_NETWORK] = "network",
2309 [DNS_TRANSACTION_CACHE] = "cache",
2310 [DNS_TRANSACTION_ZONE] = "zone",
0d2cd476 2311 [DNS_TRANSACTION_TRUST_ANCHOR] = "trust-anchor",
c3bc53e6
LP
2312};
2313DEFINE_STRING_TABLE_LOOKUP(dns_transaction_source, DnsTransactionSource);