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