]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-transaction.c
resolved: chase DNSKEY/DS RRs when doing look-ups with DNSSEC enabled
[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
LP
31
32DnsTransaction* dns_transaction_free(DnsTransaction *t) {
801ad6a6 33 DnsQueryCandidate *c;
ec2c5e43 34 DnsZoneItem *i;
547973de 35 DnsTransaction *z;
ec2c5e43
LP
36
37 if (!t)
38 return NULL;
39
40 sd_event_source_unref(t->timeout_event_source);
41
ec2c5e43
LP
42 dns_packet_unref(t->sent);
43 dns_packet_unref(t->received);
ae6a4bbf
LP
44
45 dns_answer_unref(t->answer);
ec2c5e43 46
4667e00a
LP
47 sd_event_source_unref(t->dns_udp_event_source);
48 safe_close(t->dns_udp_fd);
d20b1667 49
8300ba21 50 dns_server_unref(t->server);
ec2c5e43
LP
51 dns_stream_free(t->stream);
52
53 if (t->scope) {
f9ebb22a
LP
54 hashmap_remove_value(t->scope->transactions_by_key, t->key, t);
55 LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
ec2c5e43
LP
56
57 if (t->id != 0)
58 hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
59 }
60
da0c630e
LP
61 dns_resource_key_unref(t->key);
62
547973de 63 while ((c = set_steal_first(t->notify_query_candidates)))
801ad6a6 64 set_remove(c->transactions, t);
547973de 65 set_free(t->notify_query_candidates);
801ad6a6 66
547973de 67 while ((i = set_steal_first(t->notify_zone_items)))
ec2c5e43 68 i->probe_transaction = NULL;
547973de
LP
69 set_free(t->notify_zone_items);
70
71 while ((z = set_steal_first(t->notify_transactions)))
72 set_remove(z->dnssec_transactions, t);
73 set_free(t->notify_transactions);
74
75 while ((z = set_steal_first(t->dnssec_transactions))) {
76 set_remove(z->notify_transactions, t);
77 dns_transaction_gc(z);
78 }
79 set_free(t->dnssec_transactions);
80
81 dns_answer_unref(t->validated_keys);
ec2c5e43
LP
82
83 free(t);
84 return NULL;
85}
86
87DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
88
89void dns_transaction_gc(DnsTransaction *t) {
90 assert(t);
91
92 if (t->block_gc > 0)
93 return;
94
547973de
LP
95 if (set_isempty(t->notify_query_candidates) &&
96 set_isempty(t->notify_zone_items) &&
97 set_isempty(t->notify_transactions))
ec2c5e43
LP
98 dns_transaction_free(t);
99}
100
f52e61da 101int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key) {
ec2c5e43
LP
102 _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL;
103 int r;
104
105 assert(ret);
106 assert(s);
f52e61da 107 assert(key);
ec2c5e43 108
d5099efc 109 r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL);
ec2c5e43
LP
110 if (r < 0)
111 return r;
112
f9ebb22a 113 r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops);
da0c630e
LP
114 if (r < 0)
115 return r;
116
ec2c5e43
LP
117 t = new0(DnsTransaction, 1);
118 if (!t)
119 return -ENOMEM;
120
4667e00a 121 t->dns_udp_fd = -1;
c3bc53e6 122 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
547973de 123 t->dnssec_result = _DNSSEC_RESULT_INVALID;
f52e61da 124 t->key = dns_resource_key_ref(key);
ec2c5e43 125
da0c630e 126 /* Find a fresh, unused transaction id */
ec2c5e43
LP
127 do
128 random_bytes(&t->id, sizeof(t->id));
129 while (t->id == 0 ||
130 hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(t->id)));
131
132 r = hashmap_put(s->manager->dns_transactions, UINT_TO_PTR(t->id), t);
133 if (r < 0) {
134 t->id = 0;
135 return r;
136 }
137
f9ebb22a 138 r = hashmap_replace(s->transactions_by_key, t->key, t);
da0c630e
LP
139 if (r < 0) {
140 hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id));
141 return r;
142 }
143
f9ebb22a 144 LIST_PREPEND(transactions_by_scope, s->transactions, t);
ec2c5e43
LP
145 t->scope = s;
146
147 if (ret)
148 *ret = t;
149
150 t = NULL;
151
152 return 0;
153}
154
155static void dns_transaction_stop(DnsTransaction *t) {
156 assert(t);
157
158 t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
159 t->stream = dns_stream_free(t->stream);
ae6a4bbf
LP
160
161 /* Note that we do not drop the UDP socket here, as we want to
162 * reuse it to repeat the interaction. */
ec2c5e43
LP
163}
164
165static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
2fb3034c 166 _cleanup_free_ char *pretty = NULL;
ec2c5e43 167 DnsZoneItem *z;
ec2c5e43
LP
168
169 assert(t);
170 assert(p);
171
172 if (manager_our_packet(t->scope->manager, p) != 0)
173 return;
174
2fb3034c
LP
175 in_addr_to_string(p->family, &p->sender, &pretty);
176
177 log_debug("Transaction on scope %s on %s/%s got tentative packet from %s",
ec2c5e43
LP
178 dns_protocol_to_string(t->scope->protocol),
179 t->scope->link ? t->scope->link->name : "*",
2fb3034c
LP
180 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
181 pretty);
ec2c5e43 182
a4076574
LP
183 /* RFC 4795, Section 4.1 says that the peer with the
184 * lexicographically smaller IP address loses */
4d91eec4
LP
185 if (memcmp(&p->sender, &p->destination, FAMILY_ADDRESS_SIZE(p->family)) >= 0) {
186 log_debug("Peer has lexicographically larger IP address and thus lost in the conflict.");
a4076574
LP
187 return;
188 }
189
4d91eec4 190 log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
a4076574 191
ec2c5e43 192 t->block_gc++;
547973de 193 while ((z = set_first(t->notify_zone_items))) {
3ef64445
LP
194 /* First, make sure the zone item drops the reference
195 * to us */
196 dns_zone_item_probe_stop(z);
197
198 /* Secondly, report this as conflict, so that we might
199 * look for a different hostname */
ec2c5e43 200 dns_zone_item_conflict(z);
3ef64445 201 }
ec2c5e43
LP
202 t->block_gc--;
203
204 dns_transaction_gc(t);
205}
206
207void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
801ad6a6 208 DnsQueryCandidate *c;
ec2c5e43 209 DnsZoneItem *z;
547973de 210 DnsTransaction *d;
ec2c5e43
LP
211 Iterator i;
212
213 assert(t);
547973de 214 assert(!DNS_TRANSACTION_IS_LIVE(state));
e56187ca 215
ec2c5e43
LP
216 /* Note that this call might invalidate the query. Callers
217 * should hence not attempt to access the query or transaction
218 * after calling this function. */
219
c3bc53e6 220 log_debug("Transaction on scope %s on %s/%s now complete with <%s> from %s",
ec2c5e43
LP
221 dns_protocol_to_string(t->scope->protocol),
222 t->scope->link ? t->scope->link->name : "*",
223 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
c3bc53e6
LP
224 dns_transaction_state_to_string(state),
225 t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source));
ec2c5e43
LP
226
227 t->state = state;
228
229 dns_transaction_stop(t);
230
231 /* Notify all queries that are interested, but make sure the
232 * transaction isn't freed while we are still looking at it */
233 t->block_gc++;
547973de
LP
234 SET_FOREACH(c, t->notify_query_candidates, i)
235 dns_query_candidate_notify(c);
236 SET_FOREACH(z, t->notify_zone_items, i)
237 dns_zone_item_notify(z);
238 SET_FOREACH(d, t->notify_transactions, i)
239 dns_transaction_notify(d, t);
ec2c5e43
LP
240 t->block_gc--;
241
242 dns_transaction_gc(t);
243}
244
245static int on_stream_complete(DnsStream *s, int error) {
246 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
247 DnsTransaction *t;
248
249 assert(s);
250 assert(s->transaction);
251
252 /* Copy the data we care about out of the stream before we
253 * destroy it. */
254 t = s->transaction;
255 p = dns_packet_ref(s->read_packet);
256
257 t->stream = dns_stream_free(t->stream);
258
259 if (error != 0) {
260 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
261 return 0;
262 }
263
a4076574 264 if (dns_packet_validate_reply(p) <= 0) {
a20b9592 265 log_debug("Invalid TCP reply packet.");
a4076574
LP
266 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
267 return 0;
268 }
269
270 dns_scope_check_conflicts(t->scope, p);
271
ec2c5e43
LP
272 t->block_gc++;
273 dns_transaction_process_reply(t, p);
274 t->block_gc--;
275
276 /* If the response wasn't useful, then complete the transition now */
277 if (t->state == DNS_TRANSACTION_PENDING)
278 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
279
280 return 0;
281}
282
283static int dns_transaction_open_tcp(DnsTransaction *t) {
088480fa 284 DnsServer *server = NULL;
ec2c5e43
LP
285 _cleanup_close_ int fd = -1;
286 int r;
287
288 assert(t);
289
290 if (t->stream)
291 return 0;
292
106784eb
DM
293 switch (t->scope->protocol) {
294 case DNS_PROTOCOL_DNS:
8300ba21 295 fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53, &server);
106784eb 296 break;
ec2c5e43 297
106784eb 298 case DNS_PROTOCOL_LLMNR:
a8f6397f 299 /* When we already received a reply to this (but it was truncated), send to its sender address */
ec2c5e43 300 if (t->received)
8300ba21 301 fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port, NULL);
ec2c5e43
LP
302 else {
303 union in_addr_union address;
a7f7d1bd 304 int family = AF_UNSPEC;
ec2c5e43
LP
305
306 /* Otherwise, try to talk to the owner of a
307 * the IP address, in case this is a reverse
308 * PTR lookup */
f52e61da
LP
309
310 r = dns_name_address(DNS_RESOURCE_KEY_NAME(t->key), &family, &address);
ec2c5e43
LP
311 if (r < 0)
312 return r;
313 if (r == 0)
314 return -EINVAL;
9e08a6e0 315 if (family != t->scope->family)
9318cdd3 316 return -ESRCH;
ec2c5e43 317
8300ba21 318 fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT, NULL);
ec2c5e43 319 }
106784eb
DM
320
321 break;
322
323 default:
ec2c5e43 324 return -EAFNOSUPPORT;
106784eb 325 }
ec2c5e43
LP
326
327 if (fd < 0)
328 return fd;
329
330 r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd);
331 if (r < 0)
332 return r;
333
334 fd = -1;
335
336 r = dns_stream_write_packet(t->stream, t->sent);
337 if (r < 0) {
338 t->stream = dns_stream_free(t->stream);
339 return r;
340 }
341
8300ba21
TG
342 dns_server_unref(t->server);
343 t->server = dns_server_ref(server);
ec2c5e43 344 t->received = dns_packet_unref(t->received);
ae6a4bbf
LP
345 t->answer = dns_answer_unref(t->answer);
346 t->answer_rcode = 0;
ec2c5e43
LP
347 t->stream->complete = on_stream_complete;
348 t->stream->transaction = t;
349
350 /* The interface index is difficult to determine if we are
351 * connecting to the local host, hence fill this in right away
352 * instead of determining it from the socket */
353 if (t->scope->link)
354 t->stream->ifindex = t->scope->link->ifindex;
355
356 return 0;
357}
358
647f6aa8
TG
359static void dns_transaction_next_dns_server(DnsTransaction *t) {
360 assert(t);
361
362 t->server = dns_server_unref(t->server);
4667e00a
LP
363 t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source);
364 t->dns_udp_fd = safe_close(t->dns_udp_fd);
647f6aa8
TG
365
366 dns_scope_next_dns_server(t->scope);
367}
368
547973de
LP
369static void dns_transaction_cache_answer(DnsTransaction *t) {
370 unsigned n_cache;
371
372 assert(t);
373
374 /* For mDNS we cache whenever we get the packet, rather than
375 * in each transaction. */
376 if (!IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR))
377 return;
378
379 /* We never cache if this packet is from the local host, under
380 * the assumption that a locally running DNS server would
381 * cache this anyway, and probably knows better when to flush
382 * the cache then we could. */
383 if (!DNS_PACKET_SHALL_CACHE(t->received))
384 return;
385
386 /* According to RFC 4795, section 2.9. only the RRs from the
387 * answer section shall be cached. However, if we know the
388 * message is authenticated, we might as well cache
389 * everything. */
390 if (t->answer_authenticated)
391 n_cache = dns_answer_size(t->answer);
392 else
393 n_cache = DNS_PACKET_ANCOUNT(t->received);
394
395 dns_cache_put(&t->scope->cache,
396 t->key,
397 t->answer_rcode,
398 t->answer,
399 n_cache,
400 t->answer_authenticated,
401 0,
402 t->received->family,
403 &t->received->sender);
404}
405
406static void dns_transaction_process_dnssec(DnsTransaction *t) {
407 int r;
408
409 assert(t);
410
411 /* Are there ongoing DNSSEC transactions? If so, let's wait for them. */
412 if (!set_isempty(t->dnssec_transactions))
413 return;
414
415 /* All our auxiliary DNSSEC transactions are complete now. Try
416 * to validate our RRset now. */
417 r = dns_transaction_validate_dnssec(t);
418 if (r < 0) {
419 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
420 return;
421 }
422
423 if (!IN_SET(t->dnssec_result, _DNSSEC_RESULT_INVALID, DNSSEC_VALIDATED, DNSSEC_NO_SIGNATURE /* FOR NOW! */)) {
424 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
425 return;
426 }
427
428 dns_transaction_cache_answer(t);
429
430 if (t->answer_rcode == DNS_RCODE_SUCCESS)
431 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
432 else
433 dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
434}
435
ec2c5e43 436void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
9df3ba6c 437 usec_t ts;
ec2c5e43
LP
438 int r;
439
440 assert(t);
441 assert(p);
442 assert(t->state == DNS_TRANSACTION_PENDING);
9df3ba6c
TG
443 assert(t->scope);
444 assert(t->scope->manager);
ec2c5e43
LP
445
446 /* Note that this call might invalidate the query. Callers
447 * should hence not attempt to access the query or transaction
448 * after calling this function. */
449
b5efcf29
LP
450 log_debug("Processing incoming packet on transaction %" PRIu16".", t->id);
451
106784eb 452 switch (t->scope->protocol) {
b5efcf29 453
106784eb 454 case DNS_PROTOCOL_LLMNR:
ec2c5e43
LP
455 assert(t->scope->link);
456
457 /* For LLMNR we will not accept any packets from other
458 * interfaces */
459
460 if (p->ifindex != t->scope->link->ifindex)
461 return;
462
463 if (p->family != t->scope->family)
464 return;
465
466 /* Tentative packets are not full responses but still
467 * useful for identifying uniqueness conflicts during
468 * probing. */
8b757a38 469 if (DNS_PACKET_LLMNR_T(p)) {
ec2c5e43
LP
470 dns_transaction_tentative(t, p);
471 return;
472 }
106784eb
DM
473
474 break;
475
4e5bf5e1
DM
476 case DNS_PROTOCOL_MDNS:
477 assert(t->scope->link);
478
479 /* For mDNS we will not accept any packets from other interfaces */
480 if (p->ifindex != t->scope->link->ifindex)
481 return;
482
483 if (p->family != t->scope->family)
484 return;
485
486 break;
487
106784eb
DM
488 case DNS_PROTOCOL_DNS:
489 break;
490
491 default:
9c56a6f3 492 assert_not_reached("Invalid DNS protocol.");
ec2c5e43
LP
493 }
494
ec2c5e43
LP
495 if (t->received != p) {
496 dns_packet_unref(t->received);
497 t->received = dns_packet_ref(p);
498 }
499
c3bc53e6
LP
500 t->answer_source = DNS_TRANSACTION_NETWORK;
501
ec2c5e43
LP
502 if (p->ipproto == IPPROTO_TCP) {
503 if (DNS_PACKET_TC(p)) {
504 /* Truncated via TCP? Somebody must be fucking with us */
505 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
506 return;
507 }
508
509 if (DNS_PACKET_ID(p) != t->id) {
510 /* Not the reply to our query? Somebody must be fucking with us */
511 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
512 return;
513 }
514 }
515
38a03f06 516 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
9df3ba6c
TG
517
518 switch (t->scope->protocol) {
8af5b883 519
9df3ba6c
TG
520 case DNS_PROTOCOL_DNS:
521 assert(t->server);
522
4e0b8b17
TG
523 if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
524
8af5b883 525 /* Request failed, immediately try again with reduced features */
4e0b8b17
TG
526 log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p)));
527
528 dns_server_packet_failed(t->server, t->current_features);
529
530 r = dns_transaction_go(t);
531 if (r < 0) {
532 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
533 return;
534 }
535
536 return;
537 } else
d74fb368 538 dns_server_packet_received(t->server, t->current_features, ts - t->start_usec, p->size);
9df3ba6c
TG
539
540 break;
8af5b883 541
9df3ba6c
TG
542 case DNS_PROTOCOL_LLMNR:
543 case DNS_PROTOCOL_MDNS:
544 dns_scope_packet_received(t->scope, ts - t->start_usec);
9df3ba6c 545 break;
8af5b883 546
9df3ba6c 547 default:
8af5b883 548 assert_not_reached("Invalid DNS protocol.");
9df3ba6c
TG
549 }
550
ec2c5e43 551 if (DNS_PACKET_TC(p)) {
547493c5
DM
552
553 /* Truncated packets for mDNS are not allowed. Give up immediately. */
554 if (t->scope->protocol == DNS_PROTOCOL_MDNS) {
555 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
556 return;
557 }
558
ec2c5e43
LP
559 /* Response was truncated, let's try again with good old TCP */
560 r = dns_transaction_open_tcp(t);
561 if (r == -ESRCH) {
562 /* No servers found? Damn! */
563 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
564 return;
565 }
566 if (r < 0) {
8af5b883 567 /* On LLMNR, if we cannot connect to the host,
ec2c5e43
LP
568 * we immediately give up */
569 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
570 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
571 return;
572 }
573
574 /* On DNS, couldn't send? Try immediately again, with a new server */
647f6aa8 575 dns_transaction_next_dns_server(t);
ec2c5e43
LP
576
577 r = dns_transaction_go(t);
578 if (r < 0) {
579 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
580 return;
581 }
582
583 return;
584 }
585 }
586
8af5b883 587 /* Parse message, if it isn't parsed yet. */
ec2c5e43
LP
588 r = dns_packet_extract(p);
589 if (r < 0) {
590 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
591 return;
592 }
593
b5efcf29
LP
594 if (IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR)) {
595
547493c5 596 /* Only consider responses with equivalent query section to the request */
8af5b883
LP
597 r = dns_packet_is_reply_for(p, t->key);
598 if (r < 0) {
599 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
600 return;
601 }
602 if (r == 0) {
547493c5
DM
603 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
604 return;
605 }
29815b6c 606
547493c5
DM
607 /* Install the answer as answer to the transaction */
608 dns_answer_unref(t->answer);
609 t->answer = dns_answer_ref(p->answer);
610 t->answer_rcode = DNS_PACKET_RCODE(p);
611 t->answer_authenticated = t->scope->dnssec_mode == DNSSEC_TRUST && DNS_PACKET_AD(p);
612
547973de
LP
613 r = dns_transaction_request_dnssec_keys(t);
614 if (r < 0) {
615 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
616 return;
617 }
618 if (r > 0) {
619 /* There are DNSSEC transactions pending now. Update the state accordingly. */
620 t->state = DNS_TRANSACTION_VALIDATING;
621 return;
622 }
547493c5 623 }
ec2c5e43 624
547973de 625 dns_transaction_process_dnssec(t);
ec2c5e43
LP
626}
627
c19ffd9f
TG
628static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
629 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
630 DnsTransaction *t = userdata;
631 int r;
632
633 assert(t);
634 assert(t->scope);
635
636 r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p);
637 if (r <= 0)
638 return r;
639
640 if (dns_packet_validate_reply(p) > 0 &&
9df3ba6c 641 DNS_PACKET_ID(p) == t->id)
c19ffd9f 642 dns_transaction_process_reply(t, p);
9df3ba6c 643 else
8af5b883 644 log_debug("Invalid DNS packet, ignoring.");
c19ffd9f
TG
645
646 return 0;
647}
648
471d40d9 649static int dns_transaction_emit(DnsTransaction *t) {
c19ffd9f
TG
650 int r;
651
652 assert(t);
c19ffd9f 653
471d40d9
TG
654 if (t->scope->protocol == DNS_PROTOCOL_DNS && !t->server) {
655 DnsServer *server = NULL;
656 _cleanup_close_ int fd = -1;
c19ffd9f 657
471d40d9
TG
658 fd = dns_scope_udp_dns_socket(t->scope, &server);
659 if (fd < 0)
660 return fd;
c19ffd9f 661
4667e00a 662 r = sd_event_add_io(t->scope->manager->event, &t->dns_udp_event_source, fd, EPOLLIN, on_dns_packet, t);
471d40d9
TG
663 if (r < 0)
664 return r;
c19ffd9f 665
4667e00a 666 t->dns_udp_fd = fd;
471d40d9
TG
667 fd = -1;
668 t->server = dns_server_ref(server);
669 }
c19ffd9f 670
9c5e12a4 671 r = dns_scope_emit(t->scope, t->dns_udp_fd, t->server, t->sent);
471d40d9
TG
672 if (r < 0)
673 return r;
c19ffd9f 674
be808ea0
TG
675 if (t->server)
676 t->current_features = t->server->possible_features;
677
471d40d9 678 return 0;
c19ffd9f
TG
679}
680
ec2c5e43
LP
681static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
682 DnsTransaction *t = userdata;
683 int r;
684
685 assert(s);
686 assert(t);
687
ef7ce6df
DM
688 if (!t->initial_jitter_scheduled || t->initial_jitter_elapsed) {
689 /* Timeout reached? Increase the timeout for the server used */
690 switch (t->scope->protocol) {
691 case DNS_PROTOCOL_DNS:
692 assert(t->server);
ec2c5e43 693
ef7ce6df 694 dns_server_packet_lost(t->server, t->current_features, usec - t->start_usec);
be808ea0 695
ef7ce6df
DM
696 break;
697 case DNS_PROTOCOL_LLMNR:
698 case DNS_PROTOCOL_MDNS:
699 dns_scope_packet_lost(t->scope, usec - t->start_usec);
9df3ba6c 700
ef7ce6df
DM
701 break;
702 default:
703 assert_not_reached("Invalid DNS protocol.");
704 }
705
706 if (t->initial_jitter_scheduled)
707 t->initial_jitter_elapsed = true;
be808ea0
TG
708 }
709
710 /* ...and try again with a new server */
711 dns_transaction_next_dns_server(t);
712
ec2c5e43
LP
713 r = dns_transaction_go(t);
714 if (r < 0)
715 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
716
717 return 0;
718}
719
9df3ba6c
TG
720static usec_t transaction_get_resend_timeout(DnsTransaction *t) {
721 assert(t);
722 assert(t->scope);
723
724 switch (t->scope->protocol) {
725 case DNS_PROTOCOL_DNS:
726 assert(t->server);
727
728 return t->server->resend_timeout;
9df3ba6c 729 case DNS_PROTOCOL_MDNS:
11a27c2e
DM
730 assert(t->n_attempts > 0);
731 return (1 << (t->n_attempts - 1)) * USEC_PER_SEC;
732 case DNS_PROTOCOL_LLMNR:
9df3ba6c
TG
733 return t->scope->resend_timeout;
734 default:
735 assert_not_reached("Invalid DNS protocol.");
736 }
737}
738
1effe965 739static int dns_transaction_prepare_next_attempt(DnsTransaction *t, usec_t ts) {
ec2c5e43
LP
740 bool had_stream;
741 int r;
742
743 assert(t);
744
745 had_stream = !!t->stream;
746
747 dns_transaction_stop(t);
748
ec2c5e43
LP
749 if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
750 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
751 return 0;
752 }
753
754 if (t->scope->protocol == DNS_PROTOCOL_LLMNR && had_stream) {
755 /* If we already tried via a stream, then we don't
756 * retry on LLMNR. See RFC 4795, Section 2.7. */
757 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
758 return 0;
759 }
760
761 t->n_attempts++;
9df3ba6c 762 t->start_usec = ts;
ec2c5e43 763 t->received = dns_packet_unref(t->received);
ae6a4bbf
LP
764 t->answer = dns_answer_unref(t->answer);
765 t->answer_rcode = 0;
c3bc53e6 766 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
ec2c5e43 767
0d2cd476
LP
768 /* Check the trust anchor. Do so only on classic DNS, since DNSSEC does not apply otherwise. */
769 if (t->scope->protocol == DNS_PROTOCOL_DNS) {
770 r = dns_trust_anchor_lookup(&t->scope->manager->trust_anchor, t->key, &t->answer);
771 if (r < 0)
772 return r;
773 if (r > 0) {
774 t->answer_rcode = DNS_RCODE_SUCCESS;
775 t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
931851e8 776 t->answer_authenticated = true;
0d2cd476
LP
777 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
778 return 0;
779 }
780 }
781
782 /* Check the zone, but only if this transaction is not used
d746bb3e 783 * for probing or verifying a zone item. */
547973de 784 if (set_isempty(t->notify_zone_items)) {
d746bb3e 785
ae6a4bbf 786 r = dns_zone_lookup(&t->scope->zone, t->key, &t->answer, NULL, NULL);
d746bb3e
LP
787 if (r < 0)
788 return r;
789 if (r > 0) {
ae6a4bbf 790 t->answer_rcode = DNS_RCODE_SUCCESS;
c3bc53e6 791 t->answer_source = DNS_TRANSACTION_ZONE;
931851e8 792 t->answer_authenticated = true;
d746bb3e
LP
793 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
794 return 0;
795 }
796 }
797
4d926a69
LP
798 /* Check the cache, but only if this transaction is not used
799 * for probing or verifying a zone item. */
547973de 800 if (set_isempty(t->notify_zone_items)) {
2c27fbca 801
4d926a69
LP
802 /* Before trying the cache, let's make sure we figured out a
803 * server to use. Should this cause a change of server this
804 * might flush the cache. */
805 dns_scope_get_dns_server(t->scope);
2c27fbca 806
4d926a69
LP
807 /* Let's then prune all outdated entries */
808 dns_cache_prune(&t->scope->cache);
809
931851e8 810 r = dns_cache_lookup(&t->scope->cache, t->key, &t->answer_rcode, &t->answer, &t->answer_authenticated);
4d926a69
LP
811 if (r < 0)
812 return r;
813 if (r > 0) {
c3bc53e6 814 t->answer_source = DNS_TRANSACTION_CACHE;
ae6a4bbf 815 if (t->answer_rcode == DNS_RCODE_SUCCESS)
4d926a69
LP
816 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
817 else
818 dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
819 return 0;
820 }
ec2c5e43
LP
821 }
822
1effe965
DM
823 return 1;
824}
825
0afa57e2
DM
826static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
827
828 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
7778dfff 829 bool add_known_answers = false;
0afa57e2
DM
830 DnsTransaction *other;
831 unsigned qdcount;
832 usec_t ts;
833 int r;
834
835 assert(t);
836 assert(t->scope->protocol == DNS_PROTOCOL_MDNS);
837
838 /* Discard any previously prepared packet, so we can start over and coaleasce again */
839 t->sent = dns_packet_unref(t->sent);
840
841 r = dns_packet_new_query(&p, t->scope->protocol, 0, false);
842 if (r < 0)
843 return r;
844
845 r = dns_packet_append_key(p, t->key, NULL);
846 if (r < 0)
847 return r;
848
849 qdcount = 1;
850
7778dfff
DM
851 if (dns_key_is_shared(t->key))
852 add_known_answers = true;
853
0afa57e2
DM
854 /*
855 * For mDNS, we want to coalesce as many open queries in pending transactions into one single
856 * query packet on the wire as possible. To achieve that, we iterate through all pending transactions
857 * in our current scope, and see whether their timing contraints allow them to be sent.
858 */
859
860 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
861
862 LIST_FOREACH(transactions_by_scope, other, t->scope->transactions) {
863
864 /* Skip ourselves */
865 if (other == t)
866 continue;
867
868 if (other->state != DNS_TRANSACTION_PENDING)
869 continue;
870
871 if (other->next_attempt_after > ts)
872 continue;
873
874 if (qdcount >= UINT16_MAX)
875 break;
876
877 r = dns_packet_append_key(p, other->key, NULL);
878
879 /*
880 * If we can't stuff more questions into the packet, just give up.
881 * One of the 'other' transactions will fire later and take care of the rest.
882 */
883 if (r == -EMSGSIZE)
884 break;
885
886 if (r < 0)
887 return r;
888
889 r = dns_transaction_prepare_next_attempt(other, ts);
890 if (r <= 0)
891 continue;
892
893 ts += transaction_get_resend_timeout(other);
894
895 r = sd_event_add_time(
896 other->scope->manager->event,
897 &other->timeout_event_source,
898 clock_boottime_or_monotonic(),
899 ts, 0,
900 on_transaction_timeout, other);
901 if (r < 0)
902 return r;
903
904 other->state = DNS_TRANSACTION_PENDING;
905 other->next_attempt_after = ts;
906
907 qdcount ++;
7778dfff
DM
908
909 if (dns_key_is_shared(other->key))
910 add_known_answers = true;
0afa57e2
DM
911 }
912
913 DNS_PACKET_HEADER(p)->qdcount = htobe16(qdcount);
914 DNS_PACKET_HEADER(p)->id = t->id;
915
7778dfff
DM
916 /* Append known answer section if we're asking for any shared record */
917 if (add_known_answers) {
918 r = dns_cache_export_shared_to_packet(&t->scope->cache, p);
919 if (r < 0)
920 return r;
921 }
922
0afa57e2
DM
923 t->sent = p;
924 p = NULL;
925
926 return 0;
927}
928
929static int dns_transaction_make_packet(DnsTransaction *t) {
930 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
931 int r;
932
933 assert(t);
934
935 if (t->scope->protocol == DNS_PROTOCOL_MDNS)
936 return dns_transaction_make_packet_mdns(t);
937
938 if (t->sent)
939 return 0;
940
941 r = dns_packet_new_query(&p, t->scope->protocol, 0, t->scope->dnssec_mode == DNSSEC_YES);
942 if (r < 0)
943 return r;
944
945 r = dns_scope_good_key(t->scope, t->key);
946 if (r < 0)
947 return r;
948 if (r == 0)
949 return -EDOM;
950
951 r = dns_packet_append_key(p, t->key, NULL);
952 if (r < 0)
953 return r;
954
955 DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
956 DNS_PACKET_HEADER(p)->id = t->id;
957
958 t->sent = p;
959 p = NULL;
960
961 return 0;
962}
963
1effe965
DM
964int dns_transaction_go(DnsTransaction *t) {
965 usec_t ts;
966 int r;
967
968 assert(t);
969
970 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
547973de 971
1effe965
DM
972 r = dns_transaction_prepare_next_attempt(t, ts);
973 if (r <= 0)
974 return r;
975
547973de
LP
976 if (log_get_max_level() >= LOG_DEBUG) {
977 _cleanup_free_ char *ks = NULL;
978
979 (void) dns_resource_key_to_string(t->key, &ks);
980
981 log_debug("Excercising transaction for <%s> on scope %s on %s/%s",
982 ks ? strstrip(ks) : "???",
983 dns_protocol_to_string(t->scope->protocol),
984 t->scope->link ? t->scope->link->name : "*",
985 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family));
986 }
1effe965 987
ef7ce6df 988 if (!t->initial_jitter_scheduled &&
ea12bcc7
DM
989 (t->scope->protocol == DNS_PROTOCOL_LLMNR ||
990 t->scope->protocol == DNS_PROTOCOL_MDNS)) {
991 usec_t jitter, accuracy;
6e068472
LP
992
993 /* RFC 4795 Section 2.7 suggests all queries should be
994 * delayed by a random time from 0 to JITTER_INTERVAL. */
995
ef7ce6df 996 t->initial_jitter_scheduled = true;
6e068472
LP
997
998 random_bytes(&jitter, sizeof(jitter));
ea12bcc7
DM
999
1000 switch (t->scope->protocol) {
1001 case DNS_PROTOCOL_LLMNR:
1002 jitter %= LLMNR_JITTER_INTERVAL_USEC;
1003 accuracy = LLMNR_JITTER_INTERVAL_USEC;
1004 break;
1005 case DNS_PROTOCOL_MDNS:
1006 jitter %= MDNS_JITTER_RANGE_USEC;
1007 jitter += MDNS_JITTER_MIN_USEC;
1008 accuracy = MDNS_JITTER_RANGE_USEC;
1009 break;
1010 default:
1011 assert_not_reached("bad protocol");
1012 }
6e068472
LP
1013
1014 r = sd_event_add_time(
1015 t->scope->manager->event,
1016 &t->timeout_event_source,
1017 clock_boottime_or_monotonic(),
ea12bcc7 1018 ts + jitter, accuracy,
6e068472
LP
1019 on_transaction_timeout, t);
1020 if (r < 0)
1021 return r;
1022
1023 t->n_attempts = 0;
a9da14e1 1024 t->next_attempt_after = ts;
6e068472
LP
1025 t->state = DNS_TRANSACTION_PENDING;
1026
ea12bcc7 1027 log_debug("Delaying %s transaction for " USEC_FMT "us.", dns_protocol_to_string(t->scope->protocol), jitter);
6e068472
LP
1028 return 0;
1029 }
1030
ec2c5e43
LP
1031 /* Otherwise, we need to ask the network */
1032 r = dns_transaction_make_packet(t);
1033 if (r == -EDOM) {
1034 /* Not the right request to make on this network?
1035 * (i.e. an A request made on IPv6 or an AAAA request
1036 * made on IPv4, on LLMNR or mDNS.) */
1037 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
1038 return 0;
1039 }
1040 if (r < 0)
1041 return r;
1042
1043 if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
f52e61da
LP
1044 (dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), "in-addr.arpa") > 0 ||
1045 dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), "ip6.arpa") > 0)) {
ec2c5e43
LP
1046
1047 /* RFC 4795, Section 2.4. says reverse lookups shall
1048 * always be made via TCP on LLMNR */
1049 r = dns_transaction_open_tcp(t);
1050 } else {
be808ea0
TG
1051 /* Try via UDP, and if that fails due to large size or lack of
1052 * support try via TCP */
471d40d9 1053 r = dns_transaction_emit(t);
be808ea0 1054 if (r == -EMSGSIZE || r == -EAGAIN)
ec2c5e43
LP
1055 r = dns_transaction_open_tcp(t);
1056 }
be808ea0 1057
ec2c5e43
LP
1058 if (r == -ESRCH) {
1059 /* No servers to send this to? */
1060 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
1061 return 0;
8300ba21 1062 } else if (r < 0) {
13b551ac
LP
1063 if (t->scope->protocol != DNS_PROTOCOL_DNS) {
1064 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
1065 return 0;
1066 }
1067
ec2c5e43 1068 /* Couldn't send? Try immediately again, with a new server */
647f6aa8 1069 dns_transaction_next_dns_server(t);
ec2c5e43
LP
1070
1071 return dns_transaction_go(t);
1072 }
1073
a9da14e1
DM
1074 ts += transaction_get_resend_timeout(t);
1075
9a015429
LP
1076 r = sd_event_add_time(
1077 t->scope->manager->event,
1078 &t->timeout_event_source,
1079 clock_boottime_or_monotonic(),
a9da14e1 1080 ts, 0,
9a015429 1081 on_transaction_timeout, t);
ec2c5e43
LP
1082 if (r < 0)
1083 return r;
1084
1085 t->state = DNS_TRANSACTION_PENDING;
a9da14e1
DM
1086 t->next_attempt_after = ts;
1087
ec2c5e43
LP
1088 return 1;
1089}
1090
547973de
LP
1091static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResourceKey *key, DnsTransaction **ret) {
1092 DnsTransaction *aux;
1093 int r;
1094
1095 assert(t);
1096 assert(ret);
1097 assert(key);
1098
1099 aux = dns_scope_find_transaction(t->scope, key, true);
1100 if (!aux) {
1101 r = dns_transaction_new(&aux, t->scope, key);
1102 if (r < 0)
1103 return r;
1104 } else {
1105 if (set_contains(t->dnssec_transactions, aux)) {
1106 *ret = aux;
1107 return 0;
1108 }
1109 }
1110
1111 r = set_ensure_allocated(&t->dnssec_transactions, NULL);
1112 if (r < 0)
1113 goto gc;
1114
1115 r = set_ensure_allocated(&aux->notify_transactions, NULL);
1116 if (r < 0)
1117 goto gc;
1118
1119 r = set_put(t->dnssec_transactions, aux);
1120 if (r < 0)
1121 goto gc;
1122
1123 r = set_put(aux->notify_transactions, t);
1124 if (r < 0) {
1125 (void) set_remove(t->dnssec_transactions, aux);
1126 goto gc;
1127 }
1128
1129 *ret = aux;
1130 return 1;
1131
1132gc:
1133 dns_transaction_gc(aux);
1134 return r;
1135}
1136
1137static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *key) {
1138 _cleanup_(dns_answer_unrefp) DnsAnswer *a = NULL;
1139 DnsTransaction *aux;
1140 int r;
1141
1142 assert(t);
1143 assert(key);
1144
1145 /* Try to get the data from the trust anchor */
1146 r = dns_trust_anchor_lookup(&t->scope->manager->trust_anchor, key, &a);
1147 if (r < 0)
1148 return r;
1149 if (r > 0) {
1150 r = dns_answer_extend(&t->validated_keys, a);
1151 if (r < 0)
1152 return r;
1153
1154 return 0;
1155 }
1156
1157 /* This didn't work, ask for it via the network/cache then. */
1158 r = dns_transaction_add_dnssec_transaction(t, key, &aux);
1159 if (r < 0)
1160 return r;
1161
1162 if (aux->state == DNS_TRANSACTION_NULL) {
1163 r = dns_transaction_go(aux);
1164 if (r < 0)
1165 return r;
1166 }
1167
1168 return 0;
1169}
1170
1171int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
1172 DnsResourceRecord *rr;
1173 int r;
1174
1175 assert(t);
1176
1177 if (t->scope->dnssec_mode != DNSSEC_YES)
1178 return 0;
1179
1180 DNS_ANSWER_FOREACH(rr, t->answer) {
1181
1182 switch (rr->key->type) {
1183
1184 case DNS_TYPE_RRSIG: {
1185 /* For each RRSIG we request the matching DNSKEY */
1186 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *dnskey = NULL;
1187
1188 /* If this RRSIG is about a DNSKEY RR and the
1189 * signer is the same as the owner, then we
1190 * already have the DNSKEY, and we don't have
1191 * to look for more. */
1192 if (rr->rrsig.type_covered == DNS_TYPE_DNSKEY) {
1193 r = dns_name_equal(rr->rrsig.signer, DNS_RESOURCE_KEY_NAME(rr->key));
1194 if (r < 0)
1195 return r;
1196 if (r > 0)
1197 continue;
1198 }
1199
1200 /* If the signer is not a parent of the owner,
1201 * then the signature is bogus, let's ignore
1202 * it. */
1203 r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(rr->key), rr->rrsig.signer);
1204 if (r < 0)
1205 return r;
1206 if (r == 0)
1207 continue;
1208
1209 dnskey = dns_resource_key_new(rr->key->class, DNS_TYPE_DNSKEY, rr->rrsig.signer);
1210 if (!dnskey)
1211 return -ENOMEM;
1212
1213 log_debug("Requesting DNSKEY to validate transaction %" PRIu16" (key tag: %" PRIu16 ").", t->id, rr->rrsig.key_tag);
1214
1215 r = dns_transaction_request_dnssec_rr(t, dnskey);
1216 if (r < 0)
1217 return r;
1218 break;
1219 }
1220
1221 case DNS_TYPE_DNSKEY: {
1222 /* For each DNSKEY we request the matching DS */
1223 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
1224
1225 ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, DNS_RESOURCE_KEY_NAME(rr->key));
1226 if (!ds)
1227 return -ENOMEM;
1228
1229 log_debug("Requesting DS to validate transaction %" PRIu16" (key tag: %" PRIu16 ").", t->id, dnssec_keytag(rr));
1230
1231 r = dns_transaction_request_dnssec_rr(t, ds);
1232 if (r < 0)
1233 return r;
1234
1235 break;
1236 }}
1237 }
1238
1239 return !set_isempty(t->dnssec_transactions);
1240}
1241
1242void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source) {
1243 int r;
1244
1245 assert(t);
1246 assert(IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING));
1247 assert(source);
1248
1249 /* Invoked whenever any of our auxiliary DNSSEC transactions
1250 completed its work. We simply copy the answer from that
1251 transaction over. */
1252
1253 if (source->state != DNS_TRANSACTION_SUCCESS) {
1254 log_debug("Auxiliary DNSSEC RR query failed.");
1255 t->dnssec_result = DNSSEC_FAILED_AUXILIARY;
1256 } else {
1257 r = dns_answer_extend(&t->validated_keys, source->answer);
1258 if (r < 0) {
1259 log_error_errno(r, "Failed to merge validated DNSSEC key data: %m");
1260 t->dnssec_result = DNSSEC_FAILED_AUXILIARY;
1261 }
1262 }
1263
1264 /* Detach us from the DNSSEC transaction. */
1265 (void) set_remove(t->dnssec_transactions, source);
1266 (void) set_remove(source->notify_transactions, t);
1267
1268 /* If the state is still PENDING, we are still in the loop
1269 * that adds further DNSSEC transactions, hence don't check if
1270 * we are ready yet. If the state is VALIDATING however, we
1271 * should check if we are complete now. */
1272 if (t->state == DNS_TRANSACTION_VALIDATING)
1273 dns_transaction_process_dnssec(t);
1274}
1275
1276int dns_transaction_validate_dnssec(DnsTransaction *t) {
1277 _cleanup_(dns_answer_unrefp) DnsAnswer *validated = NULL;
1278 DnsResourceRecord *rr;
1279 int ifindex, r;
1280
1281 assert(t);
1282
1283 /* We have now collected all DS and DNSKEY RRs in
1284 * t->validated_keys, let's see which RRs we can now
1285 * authenticate with that. */
1286
1287 if (t->scope->dnssec_mode != DNSSEC_YES)
1288 return 0;
1289
1290 /* Already validated */
1291 if (t->dnssec_result != _DNSSEC_RESULT_INVALID)
1292 return 0;
1293
1294 if (IN_SET(t->answer_source, DNS_TRANSACTION_ZONE, DNS_TRANSACTION_TRUST_ANCHOR)) {
1295 t->dnssec_result = DNSSEC_VALIDATED;
1296 t->answer_authenticated = true;
1297 return 0;
1298 }
1299
1300 if (log_get_max_level() >= LOG_DEBUG) {
1301 _cleanup_free_ char *ks = NULL;
1302
1303 (void) dns_resource_key_to_string(t->key, &ks);
1304 log_debug("Validating response from transaction %" PRIu16 " (%s).", t->id, ks ? strstrip(ks) : "???");
1305 }
1306
1307 /* First see if there are DNSKEYs we already known a validated DS for. */
1308 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, t->answer) {
1309
1310 r = dnssec_verify_dnskey_search(rr, t->validated_keys);
1311 if (r < 0)
1312 return r;
1313 if (r == 0)
1314 continue;
1315
1316 /* If so, the DNSKEY is validated too. */
1317 r = dns_answer_add_extend(&t->validated_keys, rr, ifindex);
1318 if (r < 0)
1319 return r;
1320 }
1321
1322 for (;;) {
1323 bool changed = false, missing_key_for_transaction = false;
1324
1325 DNS_ANSWER_FOREACH(rr, t->answer) {
1326 DnssecResult result;
1327
1328 if (rr->key->type == DNS_TYPE_RRSIG)
1329 continue;
1330
1331 r = dnssec_verify_rrset_search(t->answer, rr->key, t->validated_keys, USEC_INFINITY, &result);
1332 if (r < 0)
1333 return r;
1334
1335 if (log_get_max_level() >= LOG_DEBUG) {
1336 _cleanup_free_ char *rrs = NULL;
1337
1338 (void) dns_resource_record_to_string(rr, &rrs);
1339 log_debug("Looking at %s: %s", rrs ? strstrip(rrs) : "???", dnssec_result_to_string(result));
1340 }
1341
1342 switch (result) {
1343
1344 case DNSSEC_VALIDATED:
1345
1346 /* Add the validated RRset to the new list of validated RRsets */
1347 r = dns_answer_copy_by_key(&validated, t->answer, rr->key);
1348 if (r < 0)
1349 return r;
1350
1351 if (rr->key->type == DNS_TYPE_DNSKEY) {
1352 /* If we just validated a
1353 * DNSKEY RRset, then let's
1354 * add these keys to the set
1355 * of validated keys for this
1356 * transaction. */
1357
1358 r = dns_answer_copy_by_key(&t->validated_keys, t->answer, rr->key);
1359 if (r < 0)
1360 return r;
1361 }
1362
1363 /* Now, remove this RRset from the RRs still to process */
1364 r = dns_answer_remove_by_key(&t->answer, rr->key);
1365 if (r < 0)
1366 return r;
1367
1368 changed = true;
1369 break;
1370
1371 case DNSSEC_INVALID:
1372 case DNSSEC_NO_SIGNATURE:
1373 case DNSSEC_SIGNATURE_EXPIRED:
1374
1375 /* Is this the RRset that we were looking for? If so, this is fatal for the whole transaction */
1376 r = dns_resource_key_match_rr(t->key, rr, NULL);
1377 if (r < 0)
1378 return r;
1379 if (r > 0) {
1380 t->dnssec_result = result;
1381 return 0;
1382 }
1383
1384 /* Is this a CNAME for a record we were looking for? If so, it's also fatal for the whole transaction */
1385 r = dns_resource_key_match_cname(t->key, rr, NULL);
1386 if (r < 0)
1387 return r;
1388 if (r > 0) {
1389 t->dnssec_result = result;
1390 return 0;
1391 }
1392
1393 /* This is just something auxiliary. Just remove the RRset and continue. */
1394 r = dns_answer_remove_by_key(&t->answer, rr->key);
1395 if (r < 0)
1396 return r;
1397
1398 changed = true;
1399 break;
1400
1401 case DNSSEC_MISSING_KEY:
1402 /* They key is missing? Let's continue
1403 * with the next iteration, maybe
1404 * we'll find it in an DNSKEY RRset
1405 * later on. */
1406
1407 r = dns_resource_key_equal(rr->key, t->key);
1408 if (r < 0)
1409 return r;
1410 if (r > 0)
1411 missing_key_for_transaction = true;
1412
1413 break;
1414
1415 default:
1416 assert_not_reached("Unexpected DNSSEC result");
1417 }
1418
1419 if (changed)
1420 break;
1421 }
1422
1423 if (changed)
1424 continue;
1425
1426 /* This didn't work either, there's no point in
1427 * continuing. */
1428 if (missing_key_for_transaction) {
1429 t->dnssec_result = DNSSEC_MISSING_KEY;
1430 return 0;
1431 }
1432
1433 break;
1434 }
1435
1436 dns_answer_unref(t->answer);
1437 t->answer = validated;
1438 validated = NULL;
1439
1440 t->answer_authenticated = true;
1441 t->dnssec_result = DNSSEC_VALIDATED;
1442 return 1;
1443}
1444
ec2c5e43
LP
1445static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {
1446 [DNS_TRANSACTION_NULL] = "null",
1447 [DNS_TRANSACTION_PENDING] = "pending",
547973de 1448 [DNS_TRANSACTION_VALIDATING] = "validating",
ec2c5e43
LP
1449 [DNS_TRANSACTION_FAILURE] = "failure",
1450 [DNS_TRANSACTION_SUCCESS] = "success",
1451 [DNS_TRANSACTION_NO_SERVERS] = "no-servers",
1452 [DNS_TRANSACTION_TIMEOUT] = "timeout",
1453 [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached",
1454 [DNS_TRANSACTION_INVALID_REPLY] = "invalid-reply",
1455 [DNS_TRANSACTION_RESOURCES] = "resources",
1456 [DNS_TRANSACTION_ABORTED] = "aborted",
547973de 1457 [DNS_TRANSACTION_DNSSEC_FAILED] = "dnssec-failed",
ec2c5e43
LP
1458};
1459DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);
c3bc53e6
LP
1460
1461static const char* const dns_transaction_source_table[_DNS_TRANSACTION_SOURCE_MAX] = {
1462 [DNS_TRANSACTION_NETWORK] = "network",
1463 [DNS_TRANSACTION_CACHE] = "cache",
1464 [DNS_TRANSACTION_ZONE] = "zone",
0d2cd476 1465 [DNS_TRANSACTION_TRUST_ANCHOR] = "trust-anchor",
c3bc53e6
LP
1466};
1467DEFINE_STRING_TABLE_LOOKUP(dns_transaction_source, DnsTransactionSource);