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