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