query.c revision 1.25 1 /* $NetBSD: query.c,v 1.25 2025/07/17 19:01:47 christos Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16 /*! \file */
17
18 #include <ctype.h>
19 #include <inttypes.h>
20 #include <stdbool.h>
21 #include <stdint.h>
22 #include <string.h>
23
24 #include <isc/async.h>
25 #include <isc/counter.h>
26 #include <isc/hex.h>
27 #include <isc/mem.h>
28 #include <isc/once.h>
29 #include <isc/random.h>
30 #include <isc/result.h>
31 #include <isc/rwlock.h>
32 #include <isc/serial.h>
33 #include <isc/stats.h>
34 #include <isc/string.h>
35 #include <isc/thread.h>
36 #include <isc/util.h>
37
38 #include <dns/adb.h>
39 #include <dns/badcache.h>
40 #include <dns/byaddr.h>
41 #include <dns/cache.h>
42 #include <dns/db.h>
43 #include <dns/dlz.h>
44 #include <dns/dns64.h>
45 #include <dns/dnsrps.h>
46 #include <dns/dnssec.h>
47 #include <dns/ede.h>
48 #include <dns/keytable.h>
49 #include <dns/message.h>
50 #include <dns/ncache.h>
51 #include <dns/nsec.h>
52 #include <dns/nsec3.h>
53 #include <dns/order.h>
54 #include <dns/rbt.h>
55 #include <dns/rcode.h>
56 #include <dns/rdata.h>
57 #include <dns/rdataclass.h>
58 #include <dns/rdatalist.h>
59 #include <dns/rdataset.h>
60 #include <dns/rdatasetiter.h>
61 #include <dns/rdatastruct.h>
62 #include <dns/rdatatype.h>
63 #include <dns/resolver.h>
64 #include <dns/result.h>
65 #include <dns/stats.h>
66 #include <dns/tkey.h>
67 #include <dns/types.h>
68 #include <dns/view.h>
69 #include <dns/zone.h>
70 #include <dns/zt.h>
71
72 #include <ns/client.h>
73 #include <ns/hooks.h>
74 #include <ns/interfacemgr.h>
75 #include <ns/log.h>
76 #include <ns/server.h>
77 #include <ns/sortlist.h>
78 #include <ns/stats.h>
79 #include <ns/xfrout.h>
80
81 #include "probes.h"
82
83 #if 0
84 /*
85 * It has been recommended that DNS64 be changed to return excluded
86 * AAAA addresses if DNS64 synthesis does not occur. This minimises
87 * the impact on the lookup results. While most DNS AAAA lookups are
88 * done to send IP packets to a host, not all of them are and filtering
89 * excluded addresses has a negative impact on those uses.
90 */
91 #define dns64_bis_return_excluded_addresses 1
92 #endif /* if 0 */
93
94 #define QUERY_ERROR(qctx, r) \
95 do { \
96 (qctx)->result = r; \
97 (qctx)->want_restart = false; \
98 (qctx)->line = __LINE__; \
99 } while (0)
100
101 /*% Partial answer? */
102 #define PARTIALANSWER(c) \
103 (((c)->query.attributes & NS_QUERYATTR_PARTIALANSWER) != 0)
104 /*% Use Cache? */
105 #define USECACHE(c) (((c)->query.attributes & NS_QUERYATTR_CACHEOK) != 0)
106 /*% Recursion OK? */
107 #define RECURSIONOK(c) (((c)->query.attributes & NS_QUERYATTR_RECURSIONOK) != 0)
108 /*% Recursing? */
109 #define RECURSING(c) (((c)->query.attributes & NS_QUERYATTR_RECURSING) != 0)
110 /*% Want Recursion? */
111 #define WANTRECURSION(c) \
112 (((c)->query.attributes & NS_QUERYATTR_WANTRECURSION) != 0)
113 /*% Is TCP? */
114 #define TCP(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
115
116 /*% Want DNSSEC? */
117 #define WANTDNSSEC(c) (((c)->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
118 /*% Want WANTAD? */
119 #define WANTAD(c) (((c)->attributes & NS_CLIENTATTR_WANTAD) != 0)
120 /*% Client presented a bad COOKIE. */
121 #define BADCOOKIE(c) (((c)->attributes & NS_CLIENTATTR_BADCOOKIE) != 0)
122 /*% Client presented a valid COOKIE. */
123 #define HAVECOOKIE(c) (((c)->attributes & NS_CLIENTATTR_HAVECOOKIE) != 0)
124 /*% Client presented a COOKIE. */
125 #define WANTCOOKIE(c) (((c)->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0)
126 /*% Client presented a CLIENT-SUBNET option. */
127 #define HAVEECS(c) (((c)->attributes & NS_CLIENTATTR_HAVEECS) != 0)
128 /*% No authority? */
129 #define NOAUTHORITY(c) (((c)->query.attributes & NS_QUERYATTR_NOAUTHORITY) != 0)
130 /*% No additional? */
131 #define NOADDITIONAL(c) \
132 (((c)->query.attributes & NS_QUERYATTR_NOADDITIONAL) != 0)
133 /*% Secure? */
134 #define SECURE(c) (((c)->query.attributes & NS_QUERYATTR_SECURE) != 0)
135 /*% DNS64 A lookup? */
136 #define DNS64(c) (((c)->query.attributes & NS_QUERYATTR_DNS64) != 0)
137
138 #define DNS64EXCLUDE(c) \
139 (((c)->query.attributes & NS_QUERYATTR_DNS64EXCLUDE) != 0)
140
141 #define REDIRECT(c) (((c)->query.attributes & NS_QUERYATTR_REDIRECT) != 0)
142
143 /*% Was the client already sent a response? */
144 #define QUERY_ANSWERED(q) (((q)->attributes & NS_QUERYATTR_ANSWERED) != 0)
145
146 /*% Does the query allow stale data in the response? */
147 #define QUERY_STALEOK(q) (((q)->attributes & NS_QUERYATTR_STALEOK) != 0)
148
149 /*% Does the query wants to check for stale RRset due to a timeout? */
150 #define QUERY_STALETIMEOUT(q) (((q)->dboptions & DNS_DBFIND_STALETIMEOUT) != 0)
151
152 /*% Does the rdataset 'r' have an attached 'No QNAME Proof'? */
153 #define NOQNAME(r) (((r)->attributes & DNS_RDATASETATTR_NOQNAME) != 0)
154
155 /*% Does the rdataset 'r' contain a stale answer? */
156 #define STALE(r) (((r)->attributes & DNS_RDATASETATTR_STALE) != 0)
157
158 /*% Does the rdataset 'r' is stale and within stale-refresh-time? */
159 #define STALE_WINDOW(r) (((r)->attributes & DNS_RDATASETATTR_STALE_WINDOW) != 0)
160
161 #ifdef WANT_QUERYTRACE
162 static void
163 client_trace(ns_client_t *client, int level, const char *message) {
164 if (client != NULL && client->query.qname != NULL) {
165 if (isc_log_wouldlog(ns_lctx, level)) {
166 char qbuf[DNS_NAME_FORMATSIZE];
167 char tbuf[DNS_RDATATYPE_FORMATSIZE];
168 dns_name_format(client->query.qname, qbuf,
169 sizeof(qbuf));
170 dns_rdatatype_format(client->query.qtype, tbuf,
171 sizeof(tbuf));
172 isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT,
173 NS_LOGMODULE_QUERY, level,
174 "query client=%p thread=0x%" PRIxPTR
175 "(%s/%s): %s",
176 client, isc_thread_self(), qbuf, tbuf,
177 message);
178 }
179 } else {
180 isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT,
181 NS_LOGMODULE_QUERY, level,
182 "query client=%p thread=0x%" PRIxPTR
183 "(<unknown-query>): %s",
184 client, isc_thread_self(), message);
185 }
186 }
187 #define CTRACE(l, m) client_trace(client, l, m)
188 #define CCTRACE(l, m) client_trace(qctx->client, l, m)
189 #else /* ifdef WANT_QUERYTRACE */
190 #define CTRACE(l, m) ((void)m)
191 #define CCTRACE(l, m) ((void)m)
192 #endif /* WANT_QUERYTRACE */
193
194 #define PENDINGOK(x) (((x) & DNS_DBFIND_PENDINGOK) != 0)
195
196 #define SFCACHE_CDFLAG 0x1
197
198 /*
199 * SAVE and RESTORE have the same semantics as:
200 *
201 * foo_attach(b, &a);
202 * foo_detach(&b);
203 *
204 * without the locking and magic testing.
205 *
206 * We use the names SAVE and RESTORE to show the operation being performed,
207 * even though the two macros are identical.
208 */
209 #define SAVE(a, b) \
210 do { \
211 INSIST(a == NULL); \
212 a = b; \
213 b = NULL; \
214 } while (0)
215 #define RESTORE(a, b) SAVE(a, b)
216
217 static bool
218 validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
219 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
220
221 static void
222 query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
223 dns_dbversion_t *version, ns_client_t *client,
224 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
225 dns_name_t *fname, bool exact, dns_name_t *found);
226
227 static void
228 log_queryerror(ns_client_t *client, isc_result_t result, int line, int level);
229
230 static void
231 rpz_st_clear(ns_client_t *client);
232
233 static bool
234 rpz_ck_dnssec(ns_client_t *client, isc_result_t qresult,
235 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
236
237 static void
238 log_noexistnodata(void *val, int level, const char *fmt, ...)
239 ISC_FORMAT_PRINTF(3, 4);
240
241 static isc_result_t
242 query_addanswer(query_ctx_t *qctx);
243
244 static isc_result_t
245 query_prepare_delegation_response(query_ctx_t *qctx);
246
247 static isc_result_t
248 acquire_recursionquota(ns_client_t *client);
249
250 static void
251 release_recursionquota(ns_client_t *client);
252
253 /*
254 * Return the hooktable in use with 'qctx', or if there isn't one
255 * set, return the default hooktable.
256 */
257 static ns_hooktable_t *
258 get_hooktab(query_ctx_t *qctx) {
259 if (qctx == NULL || qctx->view == NULL || qctx->view->hooktable == NULL)
260 {
261 return ns__hook_table;
262 }
263
264 return qctx->view->hooktable;
265 }
266
267 /*
268 * Call the specified hook function in every configured module that implements
269 * that function. If any hook function returns NS_HOOK_RETURN, we
270 * set 'result' and terminate processing by jumping to the 'cleanup' tag.
271 *
272 * (Note that a hook function may set the 'result' to ISC_R_SUCCESS but
273 * still terminate processing within the calling function. That's why this
274 * is a macro instead of a static function; it needs to be able to use
275 * 'goto cleanup' regardless of the return value.)
276 */
277 #define CALL_HOOK(_id, _qctx) \
278 do { \
279 isc_result_t _res = result; \
280 ns_hooktable_t *_tab = get_hooktab(_qctx); \
281 ns_hook_t *_hook; \
282 _hook = ISC_LIST_HEAD((*_tab)[_id]); \
283 while (_hook != NULL) { \
284 ns_hook_action_t _func = _hook->action; \
285 void *_data = _hook->action_data; \
286 INSIST(_func != NULL); \
287 switch (_func(_qctx, _data, &_res)) { \
288 case NS_HOOK_CONTINUE: \
289 _hook = ISC_LIST_NEXT(_hook, link); \
290 break; \
291 case NS_HOOK_RETURN: \
292 result = _res; \
293 goto cleanup; \
294 default: \
295 UNREACHABLE(); \
296 } \
297 } \
298 } while (false)
299
300 /*
301 * Call the specified hook function in every configured module that
302 * implements that function. All modules are called; hook function return
303 * codes are ignored. This is intended for use with initialization and
304 * destruction calls which *must* run in every configured module.
305 *
306 * (This could be implemented as a static void function, but is left as a
307 * macro for symmetry with CALL_HOOK above.)
308 */
309 #define CALL_HOOK_NORETURN(_id, _qctx) \
310 do { \
311 isc_result_t _res; \
312 ns_hooktable_t *_tab = get_hooktab(_qctx); \
313 ns_hook_t *_hook; \
314 _hook = ISC_LIST_HEAD((*_tab)[_id]); \
315 while (_hook != NULL) { \
316 ns_hook_action_t _func = _hook->action; \
317 void *_data = _hook->action_data; \
318 INSIST(_func != NULL); \
319 _func(_qctx, _data, &_res); \
320 _hook = ISC_LIST_NEXT(_hook, link); \
321 } \
322 } while (false)
323
324 /*
325 * The functions defined below implement the query logic that previously lived
326 * in the single very complex function query_find(). The query_ctx_t structure
327 * defined in <ns/query.h> maintains state from function to function. The call
328 * flow for the general query processing algorithm is described below:
329 *
330 * 1. Set up query context and other resources for a client
331 * query (query_setup())
332 *
333 * 2. Start the search (ns__query_start())
334 *
335 * 3. Identify authoritative data sources which may have an answer;
336 * search them (query_lookup()). If an answer is found, go to 7.
337 *
338 * 4. If recursion or cache access are allowed, search the cache
339 * (query_lookup() again, using the cache database) to find a better
340 * answer. If an answer is found, go to 7.
341 *
342 * 5. If recursion is allowed, begin recursion (ns_query_recurse()).
343 * Go to 15 to clean up this phase of the query. When recursion
344 * is complete, processing will resume at 6.
345 *
346 * 6. Resume from recursion; set up query context for resumed processing.
347 *
348 * 7. Determine what sort of answer we've found (query_gotanswer())
349 * and call other functions accordingly:
350 * - not found (auth or cache), go to 8
351 * - delegation, go to 9
352 * - no such domain (auth), go to 10
353 * - empty answer (auth), go to 11
354 * - negative response (cache), go to 12
355 * - answer found, go to 13
356 *
357 * 8. The answer was not found in the database (query_notfound().
358 * Set up a referral and go to 9.
359 *
360 * 9. Handle a delegation response (query_delegation()). If we need
361 * to and are allowed to recurse (query_delegation_recurse()), go to 5,
362 * otherwise go to 15 to clean up and return the delegation to the client.
363 *
364 * 10. No such domain (query_nxdomain()). Attempt redirection; if
365 * unsuccessful, add authority section records (query_addsoa(),
366 * query_addauth()), then go to 15 to return NXDOMAIN to client.
367 *
368 * 11. Empty answer (query_nodata()). Add authority section records
369 * (query_addsoa(), query_addauth()) and signatures if authoritative
370 * (query_sign_nodata()) then go to 15 and return
371 * NOERROR/ANCOUNT=0 to client.
372 *
373 * 12. No such domain or empty answer returned from cache (query_ncache()).
374 * Set response code appropriately, go to 11.
375 *
376 * 13. Prepare a response (query_prepresponse()) and then fill it
377 * appropriately (query_respond(), or for type ANY,
378 * query_respond_any()).
379 *
380 * 14. If a restart is needed due to CNAME/DNAME chaining, go to 2.
381 *
382 * 15. Clean up resources. If recursing, stop and wait for the event
383 * handler to be called back (step 6). If an answer is ready,
384 * return it to the client.
385 *
386 * (XXX: This description omits several special cases including
387 * DNS64, RPZ, RRL, and the SERVFAIL cache. It also doesn't discuss
388 * plugins.)
389 */
390
391 static void
392 query_trace(query_ctx_t *qctx);
393
394 static void
395 qctx_init(ns_client_t *client, dns_fetchresponse_t **respp,
396 dns_rdatatype_t qtype, query_ctx_t *qctx);
397
398 static isc_result_t
399 qctx_prepare_buffers(query_ctx_t *qctx, isc_buffer_t *buffer);
400
401 static void
402 qctx_freedata(query_ctx_t *qctx);
403
404 static void
405 qctx_destroy(query_ctx_t *qctx);
406
407 static void
408 query_setup(ns_client_t *client, dns_rdatatype_t qtype);
409
410 static isc_result_t
411 query_lookup(query_ctx_t *qctx);
412
413 static void
414 fetch_callback(void *arg);
415
416 static void
417 recparam_update(ns_query_recparam_t *param, dns_rdatatype_t qtype,
418 const dns_name_t *qname, const dns_name_t *qdomain);
419
420 static isc_result_t
421 query_resume(query_ctx_t *qctx);
422
423 static isc_result_t
424 query_checkrrl(query_ctx_t *qctx, isc_result_t result);
425
426 static isc_result_t
427 query_checkrpz(query_ctx_t *qctx, isc_result_t result);
428
429 static isc_result_t
430 query_rpzcname(query_ctx_t *qctx, dns_name_t *cname);
431
432 static isc_result_t
433 query_gotanswer(query_ctx_t *qctx, isc_result_t result);
434
435 static void
436 query_addnoqnameproof(query_ctx_t *qctx);
437
438 static isc_result_t
439 query_respond_any(query_ctx_t *qctx);
440
441 static isc_result_t
442 query_respond(query_ctx_t *qctx);
443
444 static isc_result_t
445 query_dns64(query_ctx_t *qctx);
446
447 static void
448 query_filter64(query_ctx_t *qctx);
449
450 static isc_result_t
451 query_notfound(query_ctx_t *qctx);
452
453 static isc_result_t
454 query_zone_delegation(query_ctx_t *qctx);
455
456 static isc_result_t
457 query_delegation(query_ctx_t *qctx);
458
459 static isc_result_t
460 query_delegation_recurse(query_ctx_t *qctx);
461
462 static void
463 query_addds(query_ctx_t *qctx);
464
465 static isc_result_t
466 query_nodata(query_ctx_t *qctx, isc_result_t result);
467
468 static isc_result_t
469 query_sign_nodata(query_ctx_t *qctx);
470
471 static void
472 query_addnxrrsetnsec(query_ctx_t *qctx);
473
474 static isc_result_t
475 query_nxdomain(query_ctx_t *qctx, isc_result_t result);
476
477 static isc_result_t
478 query_redirect(query_ctx_t *qctx, isc_result_t result);
479
480 static isc_result_t
481 query_ncache(query_ctx_t *qctx, isc_result_t result);
482
483 static isc_result_t
484 query_coveringnsec(query_ctx_t *qctx);
485
486 static isc_result_t
487 query_zerottl_refetch(query_ctx_t *qctx);
488
489 static isc_result_t
490 query_cname(query_ctx_t *qctx);
491
492 static isc_result_t
493 query_dname(query_ctx_t *qctx);
494
495 static void
496 query_addcname(query_ctx_t *qctx, dns_trust_t trust, dns_ttl_t ttl);
497
498 static isc_result_t
499 query_prepresponse(query_ctx_t *qctx);
500
501 static isc_result_t
502 query_addsoa(query_ctx_t *qctx, unsigned int override_ttl,
503 dns_section_t section);
504
505 static isc_result_t
506 query_addns(query_ctx_t *qctx);
507
508 static void
509 query_addbestns(query_ctx_t *qctx);
510
511 static void
512 query_addwildcardproof(query_ctx_t *qctx, bool ispositive, bool nodata);
513
514 static void
515 query_addauth(query_ctx_t *qctx);
516
517 static void
518 query_clear_stale(ns_client_t *client);
519
520 /*
521 * Increment query statistics counters.
522 */
523 static void
524 inc_stats(ns_client_t *client, isc_statscounter_t counter) {
525 dns_zone_t *zone = client->query.authzone;
526 dns_rdatatype_t qtype;
527 dns_rdataset_t *rdataset;
528 isc_stats_t *zonestats;
529 dns_stats_t *querystats = NULL;
530
531 ns_stats_increment(client->manager->sctx->nsstats, counter);
532
533 if (zone == NULL) {
534 return;
535 }
536
537 /* Do regular response type stats */
538 zonestats = dns_zone_getrequeststats(zone);
539
540 if (zonestats != NULL) {
541 isc_stats_increment(zonestats, counter);
542 }
543
544 /* Do query type statistics
545 *
546 * We only increment per-type if we're using the authoritative
547 * answer counter, preventing double-counting.
548 */
549 if (counter == ns_statscounter_authans) {
550 querystats = dns_zone_getrcvquerystats(zone);
551 if (querystats != NULL) {
552 rdataset = ISC_LIST_HEAD(client->query.qname->list);
553 if (rdataset != NULL) {
554 qtype = rdataset->type;
555 dns_rdatatypestats_increment(querystats, qtype);
556 }
557 }
558 }
559 }
560
561 #define NS_CLIENT_FLAGS_FORMATSIZE sizeof("+E(255)STDCV")
562
563 static inline void
564 ns_client_log_flags(ns_client_t *client, unsigned int flags,
565 unsigned int extflags, char *buf, size_t len) {
566 isc_buffer_t b;
567
568 isc_buffer_init(&b, buf, len);
569 isc_buffer_putuint8(&b, WANTRECURSION(client) ? '+' : '-');
570 if (client->ednsversion >= 0) {
571 char ednsbuf[sizeof("E(255)")] = { 0 };
572
573 snprintf(ednsbuf, sizeof(ednsbuf), "E(%hhu)",
574 (unsigned char)client->ednsversion);
575 isc_buffer_putstr(&b, ednsbuf);
576 }
577 if (client->signer != NULL) {
578 isc_buffer_putuint8(&b, 'S');
579 }
580 if (TCP(client)) {
581 isc_buffer_putuint8(&b, 'T');
582 }
583 if ((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) {
584 isc_buffer_putuint8(&b, 'D');
585 }
586 if ((flags & DNS_MESSAGEFLAG_CD) != 0) {
587 isc_buffer_putuint8(&b, 'C');
588 }
589 if (HAVECOOKIE(client)) {
590 isc_buffer_putuint8(&b, 'V');
591 } else if (WANTCOOKIE(client)) {
592 isc_buffer_putuint8(&b, 'K');
593 }
594 isc_buffer_putuint8(&b, 0);
595 }
596
597 #define NS_CLIENT_ECS_FORMATSIZE (DNS_ECS_FORMATSIZE + sizeof(" [ECS ]") - 1)
598
599 static inline void
600 ns_client_log_ecs(ns_client_t *client, char *ecsbuf, size_t len) {
601 strlcpy(ecsbuf, " [ECS ", len);
602 dns_ecs_format(&client->ecs, ecsbuf + 6, len - 6);
603 strlcat(ecsbuf, "]", len);
604 }
605
606 static inline void
607 log_response(ns_client_t *client, dns_rcode_t rcode) {
608 char namebuf[DNS_NAME_FORMATSIZE];
609 char typebuf[DNS_RDATATYPE_FORMATSIZE];
610 char classbuf[DNS_RDATACLASS_FORMATSIZE];
611 char rcodebuf[20];
612 char onbuf[ISC_NETADDR_FORMATSIZE];
613 char ecsbuf[NS_CLIENT_ECS_FORMATSIZE] = { 0 };
614 char flagsbuf[NS_CLIENT_FLAGS_FORMATSIZE] = { 0 };
615 isc_buffer_t b;
616 int level = ISC_LOG_INFO;
617
618 if (!isc_log_wouldlog(ns_lctx, level)) {
619 return;
620 }
621
622 dns_name_format(client->query.origqname, namebuf, sizeof(namebuf));
623 dns_rdataclass_format(client->message->rdclass, classbuf,
624 sizeof(classbuf));
625 dns_rdatatype_format(client->query.qtype, typebuf, sizeof(typebuf));
626 isc_buffer_init(&b, rcodebuf, sizeof(rcodebuf));
627 dns_rcode_totext(rcode, &b);
628 isc_buffer_putuint8(&b, 0);
629 isc_netaddr_format(&client->destaddr, onbuf, sizeof(onbuf));
630
631 if (HAVEECS(client)) {
632 ns_client_log_ecs(client, ecsbuf, sizeof(ecsbuf));
633 }
634
635 ns_client_log_flags(client, client->message->flags, client->extflags,
636 flagsbuf, sizeof(flagsbuf));
637 ns_client_log(client, NS_LOGCATEGORY_RESPONSES, NS_LOGMODULE_QUERY,
638 level, "response: %s %s %s %s %u %u %u %s (%s)%s",
639 namebuf, classbuf, typebuf, rcodebuf,
640 client->message->counts[DNS_SECTION_ANSWER],
641 client->message->counts[DNS_SECTION_AUTHORITY],
642 client->message->counts[DNS_SECTION_ADDITIONAL], flagsbuf,
643 onbuf, ecsbuf);
644 }
645
646 static void
647 query_send(ns_client_t *client) {
648 isc_statscounter_t counter;
649
650 if ((client->message->flags & DNS_MESSAGEFLAG_AA) == 0) {
651 inc_stats(client, ns_statscounter_nonauthans);
652 } else {
653 inc_stats(client, ns_statscounter_authans);
654 }
655
656 if (client->message->rcode == dns_rcode_noerror) {
657 dns_section_t answer = DNS_SECTION_ANSWER;
658 if (ISC_LIST_EMPTY(client->message->sections[answer])) {
659 if (client->query.isreferral) {
660 counter = ns_statscounter_referral;
661 } else {
662 counter = ns_statscounter_nxrrset;
663 }
664 } else {
665 counter = ns_statscounter_success;
666 }
667 } else if (client->message->rcode == dns_rcode_nxdomain) {
668 counter = ns_statscounter_nxdomain;
669 } else if (client->message->rcode == dns_rcode_badcookie) {
670 counter = ns_statscounter_badcookie;
671 } else { /* We end up here in case of YXDOMAIN, and maybe others */
672 counter = ns_statscounter_failure;
673 }
674
675 inc_stats(client, counter);
676 ns_client_send(client);
677
678 if ((client->manager->sctx->options & NS_SERVER_LOGRESPONSES) != 0) {
679 log_response(client, client->message->rcode);
680 }
681
682 isc_nmhandle_detach(&client->reqhandle);
683 }
684
685 static void
686 query_error(ns_client_t *client, isc_result_t result, int line) {
687 int loglevel = ISC_LOG_DEBUG(3);
688 dns_rcode_t rcode;
689
690 rcode = dns_result_torcode(result);
691 switch (rcode) {
692 case dns_rcode_servfail:
693 loglevel = ISC_LOG_DEBUG(1);
694 inc_stats(client, ns_statscounter_servfail);
695 break;
696 case dns_rcode_formerr:
697 inc_stats(client, ns_statscounter_formerr);
698 break;
699 default:
700 inc_stats(client, ns_statscounter_failure);
701 break;
702 }
703
704 if ((client->manager->sctx->options & NS_SERVER_LOGQUERIES) != 0) {
705 loglevel = ISC_LOG_INFO;
706 }
707
708 log_queryerror(client, result, line, loglevel);
709
710 ns_client_error(client, result);
711
712 if (client->query.origqname != NULL &&
713 (client->manager->sctx->options & NS_SERVER_LOGRESPONSES) != 0)
714 {
715 log_response(client, rcode);
716 }
717
718 isc_nmhandle_detach(&client->reqhandle);
719 }
720
721 static void
722 query_next(ns_client_t *client, isc_result_t result) {
723 if (result == DNS_R_DUPLICATE) {
724 inc_stats(client, ns_statscounter_duplicate);
725 } else if (result == DNS_R_DROP) {
726 inc_stats(client, ns_statscounter_dropped);
727 } else {
728 inc_stats(client, ns_statscounter_failure);
729 }
730 ns_client_drop(client, result);
731 isc_nmhandle_detach(&client->reqhandle);
732 }
733
734 static void
735 query_freefreeversions(ns_client_t *client, bool everything) {
736 ns_dbversion_t *dbversion, *dbversion_next;
737 unsigned int i;
738
739 for (dbversion = ISC_LIST_HEAD(client->query.freeversions), i = 0;
740 dbversion != NULL; dbversion = dbversion_next, i++)
741 {
742 dbversion_next = ISC_LIST_NEXT(dbversion, link);
743 /*
744 * If we're not freeing everything, we keep the first three
745 * dbversions structures around.
746 */
747 if (i > 3 || everything) {
748 ISC_LIST_UNLINK(client->query.freeversions, dbversion,
749 link);
750 isc_mem_put(client->manager->mctx, dbversion,
751 sizeof(*dbversion));
752 }
753 }
754 }
755
756 void
757 ns_query_cancel(ns_client_t *client) {
758 REQUIRE(NS_CLIENT_VALID(client));
759
760 LOCK(&client->query.fetchlock);
761 for (int i = 0; i < RECTYPE_COUNT; i++) {
762 dns_fetch_t **fetchp = &client->query.recursions[i].fetch;
763 if (*fetchp != NULL) {
764 dns_resolver_cancelfetch(*fetchp);
765 *fetchp = NULL;
766 }
767 }
768 if (client->query.hookactx != NULL) {
769 client->query.hookactx->cancel(client->query.hookactx);
770 client->query.hookactx = NULL;
771 }
772 UNLOCK(&client->query.fetchlock);
773 }
774
775 static void
776 query_reset(ns_client_t *client, bool everything) {
777 isc_buffer_t *dbuf, *dbuf_next;
778 ns_dbversion_t *dbversion, *dbversion_next;
779
780 CTRACE(ISC_LOG_DEBUG(3), "query_reset");
781
782 /*%
783 * Reset the query state of a client to its default state.
784 */
785
786 /*
787 * Cancel the fetch if it's running.
788 */
789 ns_query_cancel(client);
790
791 /*
792 * Cleanup any active versions.
793 */
794 for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
795 dbversion != NULL; dbversion = dbversion_next)
796 {
797 dbversion_next = ISC_LIST_NEXT(dbversion, link);
798 dns_db_closeversion(dbversion->db, &dbversion->version, false);
799 dns_db_detach(&dbversion->db);
800 ISC_LIST_INITANDAPPEND(client->query.freeversions, dbversion,
801 link);
802 }
803 ISC_LIST_INIT(client->query.activeversions);
804
805 if (client->query.authdb != NULL) {
806 dns_db_detach(&client->query.authdb);
807 }
808 if (client->query.authzone != NULL) {
809 dns_zone_detach(&client->query.authzone);
810 }
811
812 if (client->query.dns64_aaaa != NULL) {
813 ns_client_putrdataset(client, &client->query.dns64_aaaa);
814 }
815 if (client->query.dns64_sigaaaa != NULL) {
816 ns_client_putrdataset(client, &client->query.dns64_sigaaaa);
817 }
818 if (client->query.dns64_aaaaok != NULL) {
819 isc_mem_cput(client->manager->mctx, client->query.dns64_aaaaok,
820 client->query.dns64_aaaaoklen, sizeof(bool));
821 client->query.dns64_aaaaok = NULL;
822 client->query.dns64_aaaaoklen = 0;
823 }
824
825 ns_client_putrdataset(client, &client->query.redirect.rdataset);
826 ns_client_putrdataset(client, &client->query.redirect.sigrdataset);
827 if (client->query.redirect.db != NULL) {
828 if (client->query.redirect.node != NULL) {
829 dns_db_detachnode(client->query.redirect.db,
830 &client->query.redirect.node);
831 }
832 dns_db_detach(&client->query.redirect.db);
833 }
834 if (client->query.redirect.zone != NULL) {
835 dns_zone_detach(&client->query.redirect.zone);
836 }
837
838 query_freefreeversions(client, everything);
839
840 for (dbuf = ISC_LIST_HEAD(client->query.namebufs); dbuf != NULL;
841 dbuf = dbuf_next)
842 {
843 dbuf_next = ISC_LIST_NEXT(dbuf, link);
844 if (dbuf_next != NULL || everything) {
845 ISC_LIST_UNLINK(client->query.namebufs, dbuf, link);
846 isc_buffer_free(&dbuf);
847 }
848 }
849
850 if (client->query.restarts > 0) {
851 /*
852 * client->query.qname was dynamically allocated.
853 */
854 dns_message_puttempname(client->message, &client->query.qname);
855 }
856 client->query.qname = NULL;
857 client->query.attributes = (NS_QUERYATTR_RECURSIONOK |
858 NS_QUERYATTR_CACHEOK | NS_QUERYATTR_SECURE);
859 client->query.restarts = 0;
860 client->query.timerset = false;
861 if (client->query.rpz_st != NULL) {
862 rpz_st_clear(client);
863 if (everything) {
864 INSIST(client->query.rpz_st->rpsdb == NULL);
865 isc_mem_put(client->manager->mctx, client->query.rpz_st,
866 sizeof(*client->query.rpz_st));
867 client->query.rpz_st = NULL;
868 }
869 }
870 if (client->query.qc != NULL) {
871 isc_counter_detach(&client->query.qc);
872 }
873 client->query.origqname = NULL;
874 client->query.dboptions = 0;
875 client->query.fetchoptions = 0;
876 client->query.gluedb = NULL;
877 client->query.authdbset = false;
878 client->query.isreferral = false;
879 client->query.dns64_options = 0;
880 client->query.dns64_ttl = UINT32_MAX;
881 recparam_update(&client->query.recparam, 0, NULL, NULL);
882 client->query.root_key_sentinel_keyid = 0;
883 client->query.root_key_sentinel_is_ta = false;
884 client->query.root_key_sentinel_not_ta = false;
885 }
886
887 static void
888 query_cleanup(ns_client_t *client) {
889 query_reset(client, false);
890 }
891
892 void
893 ns_query_free(ns_client_t *client) {
894 REQUIRE(NS_CLIENT_VALID(client));
895
896 query_reset(client, true);
897 }
898
899 void
900 ns_query_init(ns_client_t *client) {
901 REQUIRE(NS_CLIENT_VALID(client));
902
903 client->query = (ns_query_t){ 0 };
904
905 ISC_LIST_INIT(client->query.namebufs);
906 ISC_LIST_INIT(client->query.activeversions);
907 ISC_LIST_INIT(client->query.freeversions);
908
909 /*
910 * This mutex is destroyed when the client is destroyed in
911 * exit_check().
912 */
913 isc_mutex_init(&client->query.fetchlock);
914 client->query.redirect.fname =
915 dns_fixedname_initname(&client->query.redirect.fixed);
916 query_reset(client, false);
917 ns_client_newdbversion(client, 3);
918 ns_client_newnamebuf(client);
919 }
920
921 /*%
922 * Check if 'client' is allowed to query the cache of its associated view.
923 * Unless 'options' has the 'nolog' flag set, log the result of cache ACL
924 * evaluation using the appropriate level, along with 'name' and 'qtype'.
925 *
926 * The cache ACL is only evaluated once for each client and then the result is
927 * cached: if NS_QUERYATTR_CACHEACLOKVALID is set in client->query.attributes,
928 * cache ACL evaluation has already been performed. The evaluation result is
929 * also stored in client->query.attributes: if NS_QUERYATTR_CACHEACLOK is set,
930 * the client is allowed cache access.
931 *
932 * Returns:
933 *
934 *\li #ISC_R_SUCCESS 'client' is allowed to access cache
935 *\li #DNS_R_REFUSED 'client' is not allowed to access cache
936 */
937 static isc_result_t
938 query_checkcacheaccess(ns_client_t *client, const dns_name_t *name,
939 dns_rdatatype_t qtype, dns_getdb_options_t options) {
940 isc_result_t result;
941
942 if ((client->query.attributes & NS_QUERYATTR_CACHEACLOKVALID) == 0) {
943 enum refusal_reasons {
944 ALLOW_QUERY_CACHE,
945 ALLOW_QUERY_CACHE_ON
946 };
947 static const char *acl_desc[] = {
948 "allow-query-cache did not match",
949 "allow-query-cache-on did not match",
950 };
951
952 /*
953 * The view's cache ACLs have not yet been evaluated.
954 * Do it now. Both allow-query-cache and
955 * allow-query-cache-on must be satisfied.
956 */
957 char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")];
958
959 enum refusal_reasons refusal_reason = ALLOW_QUERY_CACHE;
960 result = ns_client_checkaclsilent(client, NULL,
961 client->view->cacheacl, true);
962 if (result == ISC_R_SUCCESS) {
963 refusal_reason = ALLOW_QUERY_CACHE_ON;
964 result = ns_client_checkaclsilent(
965 client, &client->destaddr,
966 client->view->cacheonacl, true);
967 }
968 if (result == ISC_R_SUCCESS) {
969 /*
970 * We were allowed by the "allow-query-cache" ACL.
971 */
972 client->query.attributes |= NS_QUERYATTR_CACHEACLOK;
973 if (!options.nolog &&
974 isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(3)))
975 {
976 ns_client_aclmsg("query (cache)", name, qtype,
977 client->view->rdclass, msg,
978 sizeof(msg));
979 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
980 NS_LOGMODULE_QUERY,
981 ISC_LOG_DEBUG(3), "%s approved",
982 msg);
983 }
984 } else {
985 /*
986 * We were denied by the "allow-query-cache" ACL.
987 * There is no need to clear NS_QUERYATTR_CACHEACLOK
988 * since it is cleared by query_reset(), before query
989 * processing starts.
990 */
991 dns_ede_add(&client->edectx, DNS_EDE_PROHIBITED, NULL);
992
993 if (!options.nolog) {
994 ns_client_aclmsg("query (cache)", name, qtype,
995 client->view->rdclass, msg,
996 sizeof(msg));
997 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
998 NS_LOGMODULE_QUERY, ISC_LOG_INFO,
999 "%s denied (%s)", msg,
1000 acl_desc[refusal_reason]);
1001 }
1002 }
1003
1004 /*
1005 * Evaluation has been finished; make sure we will just consult
1006 * NS_QUERYATTR_CACHEACLOK for this client from now on.
1007 */
1008 client->query.attributes |= NS_QUERYATTR_CACHEACLOKVALID;
1009 }
1010
1011 return (client->query.attributes & NS_QUERYATTR_CACHEACLOK) != 0
1012 ? ISC_R_SUCCESS
1013 : DNS_R_REFUSED;
1014 }
1015
1016 static isc_result_t
1017 query_validatezonedb(ns_client_t *client, const dns_name_t *name,
1018 dns_rdatatype_t qtype, dns_getdb_options_t options,
1019 dns_zone_t *zone, dns_db_t *db,
1020 dns_dbversion_t **versionp) {
1021 isc_result_t result;
1022 dns_acl_t *queryacl, *queryonacl;
1023 ns_dbversion_t *dbversion;
1024
1025 REQUIRE(zone != NULL);
1026 REQUIRE(db != NULL);
1027
1028 /*
1029 * Mirror zone data is treated as cache data.
1030 */
1031 if (dns_zone_gettype(zone) == dns_zone_mirror) {
1032 return query_checkcacheaccess(client, name, qtype, options);
1033 }
1034
1035 /*
1036 * This limits our searching to the zone where the first name
1037 * (the query target) was looked for. This prevents following
1038 * CNAMES or DNAMES into other zones and prevents returning
1039 * additional data from other zones. This does not apply if we're
1040 * answering a query where recursion is requested and allowed.
1041 */
1042 if (client->query.rpz_st == NULL &&
1043 !(WANTRECURSION(client) && RECURSIONOK(client)) &&
1044 client->query.authdbset && db != client->query.authdb)
1045 {
1046 return DNS_R_REFUSED;
1047 }
1048
1049 /*
1050 * Non recursive query to a static-stub zone is prohibited; its
1051 * zone content is not public data, but a part of local configuration
1052 * and should not be disclosed.
1053 */
1054 if (dns_zone_gettype(zone) == dns_zone_staticstub &&
1055 !RECURSIONOK(client))
1056 {
1057 return DNS_R_REFUSED;
1058 }
1059
1060 /*
1061 * If the zone has an ACL, we'll check it, otherwise
1062 * we use the view's "allow-query" ACL. Each ACL is only checked
1063 * once per query.
1064 *
1065 * Also, get the database version to use.
1066 */
1067
1068 /*
1069 * Get the current version of this database.
1070 */
1071 dbversion = ns_client_findversion(client, db);
1072 if (dbversion == NULL) {
1073 CTRACE(ISC_LOG_ERROR, "unable to get db version");
1074 return DNS_R_SERVFAIL;
1075 }
1076
1077 if (options.ignoreacl) {
1078 goto approved;
1079 }
1080 if (dbversion->acl_checked) {
1081 if (!dbversion->queryok) {
1082 return DNS_R_REFUSED;
1083 }
1084 goto approved;
1085 }
1086
1087 queryacl = dns_zone_getqueryacl(zone);
1088 if (queryacl == NULL) {
1089 queryacl = client->view->queryacl;
1090 if ((client->query.attributes & NS_QUERYATTR_QUERYOKVALID) != 0)
1091 {
1092 /*
1093 * We've evaluated the view's queryacl already. If
1094 * NS_QUERYATTR_QUERYOK is set, then the client is
1095 * allowed to make queries, otherwise the query should
1096 * be refused.
1097 */
1098 dbversion->acl_checked = true;
1099 if ((client->query.attributes & NS_QUERYATTR_QUERYOK) ==
1100 0)
1101 {
1102 dbversion->queryok = false;
1103 return DNS_R_REFUSED;
1104 }
1105 dbversion->queryok = true;
1106 goto approved;
1107 }
1108 }
1109
1110 result = ns_client_checkaclsilent(client, NULL, queryacl, true);
1111 if (!options.nolog) {
1112 char msg[NS_CLIENT_ACLMSGSIZE("query")];
1113 if (result == ISC_R_SUCCESS) {
1114 if (isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(3))) {
1115 ns_client_aclmsg("query", name, qtype,
1116 client->view->rdclass, msg,
1117 sizeof(msg));
1118 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1119 NS_LOGMODULE_QUERY,
1120 ISC_LOG_DEBUG(3), "%s approved",
1121 msg);
1122 }
1123 } else {
1124 ns_client_aclmsg("query", name, qtype,
1125 client->view->rdclass, msg,
1126 sizeof(msg));
1127 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1128 NS_LOGMODULE_QUERY, ISC_LOG_INFO,
1129 "%s denied", msg);
1130 dns_ede_add(&client->edectx, DNS_EDE_PROHIBITED, NULL);
1131 }
1132 }
1133
1134 if (queryacl == client->view->queryacl) {
1135 if (result == ISC_R_SUCCESS) {
1136 /*
1137 * We were allowed by the default
1138 * "allow-query" ACL. Remember this so we
1139 * don't have to check again.
1140 */
1141 client->query.attributes |= NS_QUERYATTR_QUERYOK;
1142 }
1143 /*
1144 * We've now evaluated the view's query ACL, and
1145 * the NS_QUERYATTR_QUERYOK attribute is now valid.
1146 */
1147 client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
1148 }
1149
1150 /* If and only if we've gotten this far, check allow-query-on too */
1151 if (result == ISC_R_SUCCESS) {
1152 queryonacl = dns_zone_getqueryonacl(zone);
1153 if (queryonacl == NULL) {
1154 queryonacl = client->view->queryonacl;
1155 }
1156
1157 result = ns_client_checkaclsilent(client, &client->destaddr,
1158 queryonacl, true);
1159 if (result != ISC_R_SUCCESS) {
1160 dns_ede_add(&client->edectx, DNS_EDE_PROHIBITED, NULL);
1161 }
1162 if (!options.nolog && result != ISC_R_SUCCESS) {
1163 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1164 NS_LOGMODULE_QUERY, ISC_LOG_INFO,
1165 "query-on denied");
1166 }
1167 }
1168
1169 dbversion->acl_checked = true;
1170 if (result != ISC_R_SUCCESS) {
1171 dbversion->queryok = false;
1172 return DNS_R_REFUSED;
1173 }
1174 dbversion->queryok = true;
1175
1176 approved:
1177 /* Transfer ownership, if necessary. */
1178 SET_IF_NOT_NULL(versionp, dbversion->version);
1179 return ISC_R_SUCCESS;
1180 }
1181
1182 static isc_result_t
1183 query_getzonedb(ns_client_t *client, const dns_name_t *name,
1184 dns_rdatatype_t qtype, dns_getdb_options_t options,
1185 dns_zone_t **zonep, dns_db_t **dbp,
1186 dns_dbversion_t **versionp) {
1187 isc_result_t result;
1188 unsigned int ztoptions;
1189 dns_zone_t *zone = NULL;
1190 dns_db_t *db = NULL;
1191 bool partial = false;
1192
1193 REQUIRE(zonep != NULL && *zonep == NULL);
1194 REQUIRE(dbp != NULL && *dbp == NULL);
1195
1196 /*%
1197 * Find a zone database to answer the query.
1198 */
1199 ztoptions = DNS_ZTFIND_MIRROR;
1200 if (options.noexact) {
1201 ztoptions |= DNS_ZTFIND_NOEXACT;
1202 }
1203
1204 result = dns_view_findzone(client->view, name, ztoptions, &zone);
1205
1206 if (result == DNS_R_PARTIALMATCH) {
1207 partial = true;
1208 }
1209 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
1210 result = dns_zone_getdb(zone, &db);
1211 }
1212
1213 if (result != ISC_R_SUCCESS) {
1214 goto fail;
1215 }
1216
1217 result = query_validatezonedb(client, name, qtype, options, zone, db,
1218 versionp);
1219
1220 if (result != ISC_R_SUCCESS) {
1221 goto fail;
1222 }
1223
1224 /* Transfer ownership. */
1225 *zonep = zone;
1226 *dbp = db;
1227
1228 if (partial && options.partial) {
1229 return DNS_R_PARTIALMATCH;
1230 }
1231 return ISC_R_SUCCESS;
1232
1233 fail:
1234 if (zone != NULL) {
1235 dns_zone_detach(&zone);
1236 }
1237 if (db != NULL) {
1238 dns_db_detach(&db);
1239 }
1240
1241 return result;
1242 }
1243
1244 static void
1245 rpz_log_rewrite(ns_client_t *client, bool disabled, dns_rpz_policy_t policy,
1246 dns_rpz_type_t type, dns_zone_t *p_zone, dns_name_t *p_name,
1247 dns_name_t *cname, dns_rpz_num_t rpz_num) {
1248 char cname_buf[DNS_NAME_FORMATSIZE] = { 0 };
1249 char p_name_buf[DNS_NAME_FORMATSIZE];
1250 char qname_buf[DNS_NAME_FORMATSIZE];
1251 char classbuf[DNS_RDATACLASS_FORMATSIZE];
1252 char typebuf[DNS_RDATATYPE_FORMATSIZE];
1253 const char *s1 = cname_buf, *s2 = cname_buf;
1254 dns_rdataset_t *rdataset;
1255 dns_rpz_st_t *st;
1256 isc_stats_t *zonestats;
1257
1258 /*
1259 * Count enabled rewrites in the global counter.
1260 * Count both enabled and disabled rewrites for each zone.
1261 */
1262 if (!disabled && policy != DNS_RPZ_POLICY_PASSTHRU) {
1263 ns_stats_increment(client->manager->sctx->nsstats,
1264 ns_statscounter_rpz_rewrites);
1265 }
1266 if (p_zone != NULL) {
1267 zonestats = dns_zone_getrequeststats(p_zone);
1268 if (zonestats != NULL) {
1269 isc_stats_increment(zonestats,
1270 ns_statscounter_rpz_rewrites);
1271 }
1272 }
1273
1274 if (!isc_log_wouldlog(ns_lctx, DNS_RPZ_INFO_LEVEL)) {
1275 return;
1276 }
1277
1278 st = client->query.rpz_st;
1279 if ((st->popt.no_log & DNS_RPZ_ZBIT(rpz_num)) != 0) {
1280 return;
1281 }
1282
1283 dns_name_format(client->query.qname, qname_buf, sizeof(qname_buf));
1284 dns_name_format(p_name, p_name_buf, sizeof(p_name_buf));
1285 if (cname != NULL) {
1286 s1 = " (CNAME to: ";
1287 dns_name_format(cname, cname_buf, sizeof(cname_buf));
1288 s2 = ")";
1289 }
1290
1291 /*
1292 * Log Qclass and Qtype in addition to existing
1293 * fields.
1294 */
1295 rdataset = ISC_LIST_HEAD(client->query.origqname->list);
1296 INSIST(rdataset != NULL);
1297 dns_rdataclass_format(rdataset->rdclass, classbuf, sizeof(classbuf));
1298 dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf));
1299
1300 /* It's possible to have a separate log channel for rpz passthru. */
1301 isc_logcategory_t *log_cat = (policy == DNS_RPZ_POLICY_PASSTHRU)
1302 ? DNS_LOGCATEGORY_RPZ_PASSTHRU
1303 : DNS_LOGCATEGORY_RPZ;
1304
1305 ns_client_log(client, log_cat, NS_LOGMODULE_QUERY, DNS_RPZ_INFO_LEVEL,
1306 "%srpz %s %s rewrite %s/%s/%s via %s%s%s%s",
1307 disabled ? "disabled " : "", dns_rpz_type2str(type),
1308 dns_rpz_policy2str(policy), qname_buf, typebuf, classbuf,
1309 p_name_buf, s1, cname_buf, s2);
1310 }
1311
1312 static void
1313 rpz_log_fail_helper(ns_client_t *client, int level, dns_name_t *p_name,
1314 dns_rpz_type_t rpz_type1, dns_rpz_type_t rpz_type2,
1315 const char *str, isc_result_t result) {
1316 char qnamebuf[DNS_NAME_FORMATSIZE];
1317 char p_namebuf[DNS_NAME_FORMATSIZE];
1318 const char *failed, *via, *slash, *str_blank;
1319 const char *rpztypestr1;
1320 const char *rpztypestr2;
1321
1322 if (!isc_log_wouldlog(ns_lctx, level)) {
1323 return;
1324 }
1325
1326 /*
1327 * bin/tests/system/rpz/tests.sh looks for "rpz.*failed" for problems.
1328 */
1329 if (level <= DNS_RPZ_DEBUG_LEVEL1) {
1330 failed = " failed: ";
1331 } else {
1332 failed = ": ";
1333 }
1334
1335 rpztypestr1 = dns_rpz_type2str(rpz_type1);
1336 if (rpz_type2 != DNS_RPZ_TYPE_BAD) {
1337 slash = "/";
1338 rpztypestr2 = dns_rpz_type2str(rpz_type2);
1339 } else {
1340 slash = "";
1341 rpztypestr2 = "";
1342 }
1343
1344 str_blank = (*str != ' ' && *str != '\0') ? " " : "";
1345
1346 dns_name_format(client->query.qname, qnamebuf, sizeof(qnamebuf));
1347
1348 if (p_name != NULL) {
1349 via = " via ";
1350 dns_name_format(p_name, p_namebuf, sizeof(p_namebuf));
1351 } else {
1352 via = "";
1353 p_namebuf[0] = '\0';
1354 }
1355
1356 ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS, NS_LOGMODULE_QUERY,
1357 level, "rpz %s%s%s rewrite %s%s%s%s%s%s%s", rpztypestr1,
1358 slash, rpztypestr2, qnamebuf, via, p_namebuf, str_blank,
1359 str, failed, isc_result_totext(result));
1360 }
1361
1362 static void
1363 rpz_log_fail(ns_client_t *client, int level, dns_name_t *p_name,
1364 dns_rpz_type_t rpz_type, const char *str, isc_result_t result) {
1365 rpz_log_fail_helper(client, level, p_name, rpz_type, DNS_RPZ_TYPE_BAD,
1366 str, result);
1367 }
1368
1369 /*
1370 * Get a policy rewrite zone database.
1371 */
1372 static isc_result_t
1373 rpz_getdb(ns_client_t *client, dns_name_t *p_name, dns_rpz_type_t rpz_type,
1374 dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp) {
1375 char qnamebuf[DNS_NAME_FORMATSIZE];
1376 char p_namebuf[DNS_NAME_FORMATSIZE];
1377 dns_dbversion_t *rpz_version = NULL;
1378 isc_result_t result;
1379
1380 CTRACE(ISC_LOG_DEBUG(3), "rpz_getdb");
1381
1382 dns_getdb_options_t options = { .ignoreacl = true };
1383 result = query_getzonedb(client, p_name, dns_rdatatype_any, options,
1384 zonep, dbp, &rpz_version);
1385 if (result == ISC_R_SUCCESS) {
1386 dns_rpz_st_t *st = client->query.rpz_st;
1387
1388 /*
1389 * It isn't meaningful to log this message when
1390 * logging is disabled for some policy zones.
1391 */
1392 if (st->popt.no_log == 0 &&
1393 isc_log_wouldlog(ns_lctx, DNS_RPZ_DEBUG_LEVEL2))
1394 {
1395 dns_name_format(client->query.qname, qnamebuf,
1396 sizeof(qnamebuf));
1397 dns_name_format(p_name, p_namebuf, sizeof(p_namebuf));
1398 ns_client_log(client, DNS_LOGCATEGORY_RPZ,
1399 NS_LOGMODULE_QUERY, DNS_RPZ_DEBUG_LEVEL2,
1400 "try rpz %s rewrite %s via %s",
1401 dns_rpz_type2str(rpz_type), qnamebuf,
1402 p_namebuf);
1403 }
1404 *versionp = rpz_version;
1405 return ISC_R_SUCCESS;
1406 }
1407 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type,
1408 "query_getzonedb()", result);
1409 return result;
1410 }
1411
1412 /*%
1413 * Find a cache database to answer the query. This may fail with DNS_R_REFUSED
1414 * if the client is not allowed to use the cache.
1415 */
1416 static isc_result_t
1417 query_getcachedb(ns_client_t *client, const dns_name_t *name,
1418 dns_rdatatype_t qtype, dns_db_t **dbp,
1419 dns_getdb_options_t options) {
1420 isc_result_t result;
1421 dns_db_t *db = NULL;
1422
1423 REQUIRE(dbp != NULL && *dbp == NULL);
1424
1425 if (!USECACHE(client)) {
1426 return DNS_R_REFUSED;
1427 }
1428
1429 dns_db_attach(client->view->cachedb, &db);
1430
1431 result = query_checkcacheaccess(client, name, qtype, options);
1432 if (result != ISC_R_SUCCESS) {
1433 dns_db_detach(&db);
1434 }
1435
1436 /*
1437 * If query_checkcacheaccess() succeeded, transfer ownership of 'db'.
1438 * Otherwise, 'db' will be NULL due to the dns_db_detach() call above.
1439 */
1440 *dbp = db;
1441
1442 return result;
1443 }
1444
1445 static isc_result_t
1446 query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
1447 dns_getdb_options_t options, dns_zone_t **zonep, dns_db_t **dbp,
1448 dns_dbversion_t **versionp, bool *is_zonep) {
1449 isc_result_t result;
1450 isc_result_t tresult;
1451 unsigned int namelabels;
1452 unsigned int zonelabels;
1453 dns_zone_t *zone = NULL;
1454
1455 REQUIRE(zonep != NULL && *zonep == NULL);
1456
1457 /* Calculate how many labels are in name. */
1458 namelabels = dns_name_countlabels(name);
1459 zonelabels = 0;
1460
1461 /* Try to find name in bind's standard database. */
1462 result = query_getzonedb(client, name, qtype, options, &zone, dbp,
1463 versionp);
1464
1465 /* See how many labels are in the zone's name. */
1466 if (result == ISC_R_SUCCESS && zone != NULL) {
1467 zonelabels = dns_name_countlabels(dns_zone_getorigin(zone));
1468 }
1469
1470 /*
1471 * If # zone labels < # name labels, try to find an even better match
1472 * Only try if DLZ drivers are loaded for this view
1473 */
1474 if (zonelabels < namelabels &&
1475 !ISC_LIST_EMPTY(client->view->dlz_searched))
1476 {
1477 dns_clientinfomethods_t cm;
1478 dns_clientinfo_t ci;
1479 dns_db_t *tdbp;
1480
1481 dns_clientinfomethods_init(&cm, ns_client_sourceip);
1482 dns_clientinfo_init(&ci, client, NULL);
1483 dns_clientinfo_setecs(&ci, &client->ecs);
1484
1485 tdbp = NULL;
1486 tresult = dns_view_searchdlz(client->view, name, zonelabels,
1487 &cm, &ci, &tdbp);
1488 /* If we successful, we found a better match. */
1489 if (tresult == ISC_R_SUCCESS) {
1490 ns_dbversion_t *dbversion;
1491
1492 /*
1493 * If the previous search returned a zone, detach it.
1494 */
1495 if (zone != NULL) {
1496 dns_zone_detach(&zone);
1497 }
1498
1499 /*
1500 * If the previous search returned a database,
1501 * detach it.
1502 */
1503 if (*dbp != NULL) {
1504 dns_db_detach(dbp);
1505 }
1506
1507 /*
1508 * If the previous search returned a version, clear it.
1509 */
1510 *versionp = NULL;
1511
1512 dbversion = ns_client_findversion(client, tdbp);
1513 if (dbversion == NULL) {
1514 tresult = ISC_R_NOMEMORY;
1515 } else {
1516 /*
1517 * Be sure to return our database.
1518 */
1519 *dbp = tdbp;
1520 *versionp = dbversion->version;
1521 }
1522
1523 /*
1524 * We return a null zone, No stats for DLZ zones.
1525 */
1526 zone = NULL;
1527 result = tresult;
1528 }
1529 }
1530
1531 /* If successful, Transfer ownership of zone. */
1532 if (result == ISC_R_SUCCESS) {
1533 *zonep = zone;
1534 /*
1535 * If neither attempt above succeeded, return the cache instead
1536 */
1537 *is_zonep = true;
1538 } else {
1539 if (result == ISC_R_NOTFOUND) {
1540 result = query_getcachedb(client, name, qtype, dbp,
1541 options);
1542 }
1543 *is_zonep = false;
1544 }
1545 return result;
1546 }
1547
1548 static bool
1549 query_isduplicate(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
1550 dns_name_t **mnamep) {
1551 dns_section_t section;
1552 dns_name_t *mname = NULL;
1553 isc_result_t result;
1554
1555 CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate");
1556
1557 for (section = DNS_SECTION_ANSWER; section <= DNS_SECTION_ADDITIONAL;
1558 section++)
1559 {
1560 result = dns_message_findname(client->message, section, name,
1561 type, 0, &mname, NULL);
1562 if (result == ISC_R_SUCCESS) {
1563 /*
1564 * We've already got this RRset in the response.
1565 */
1566 CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate: true: "
1567 "done");
1568 return true;
1569 } else if (result == DNS_R_NXRRSET) {
1570 /*
1571 * The name exists, but the rdataset does not.
1572 */
1573 if (section == DNS_SECTION_ADDITIONAL) {
1574 break;
1575 }
1576 } else {
1577 RUNTIME_CHECK(result == DNS_R_NXDOMAIN);
1578 }
1579 mname = NULL;
1580 }
1581
1582 SET_IF_NOT_NULL(mnamep, mname);
1583
1584 CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate: false: done");
1585 return false;
1586 }
1587
1588 /*
1589 * Look up data for given 'name' and 'type' in given 'version' of 'db' for
1590 * 'client'. Called from query_additionalauth().
1591 *
1592 * If the lookup is successful:
1593 *
1594 * - store the node containing the result at 'nodep',
1595 *
1596 * - store the owner name of the returned node in 'fname',
1597 *
1598 * - if 'type' is not ANY, dns_db_findext() will put the exact rdataset being
1599 * looked for in 'rdataset' and its signatures (if any) in 'sigrdataset',
1600 *
1601 * - if 'type' is ANY, dns_db_findext() will leave 'rdataset' and
1602 * 'sigrdataset' disassociated and the returned node will be iterated in
1603 * query_additional_cb().
1604 *
1605 * If the lookup is not successful:
1606 *
1607 * - 'nodep' will not be written to,
1608 * - 'fname' may still be modified as it is passed to dns_db_findext(),
1609 * - 'rdataset' and 'sigrdataset' will remain disassociated.
1610 */
1611 static isc_result_t
1612 query_additionalauthfind(dns_db_t *db, dns_dbversion_t *version,
1613 const dns_name_t *name, dns_rdatatype_t type,
1614 ns_client_t *client, dns_dbnode_t **nodep,
1615 dns_name_t *fname, dns_rdataset_t *rdataset,
1616 dns_rdataset_t *sigrdataset) {
1617 dns_clientinfomethods_t cm;
1618 dns_dbnode_t *node = NULL;
1619 dns_clientinfo_t ci;
1620 isc_result_t result;
1621
1622 dns_clientinfomethods_init(&cm, ns_client_sourceip);
1623 dns_clientinfo_init(&ci, client, NULL);
1624
1625 /*
1626 * Since we are looking for authoritative data, we do not set
1627 * the GLUEOK flag. Glue will be looked for later, but not
1628 * necessarily in the same database.
1629 */
1630 result = dns_db_findext(db, name, version, type,
1631 client->query.dboptions, client->now, &node,
1632 fname, &cm, &ci, rdataset, sigrdataset);
1633 if (result != ISC_R_SUCCESS) {
1634 if (dns_rdataset_isassociated(rdataset)) {
1635 dns_rdataset_disassociate(rdataset);
1636 }
1637
1638 if (sigrdataset != NULL &&
1639 dns_rdataset_isassociated(sigrdataset))
1640 {
1641 dns_rdataset_disassociate(sigrdataset);
1642 }
1643
1644 if (node != NULL) {
1645 dns_db_detachnode(db, &node);
1646 }
1647
1648 return result;
1649 }
1650
1651 /*
1652 * Do not return signatures if the zone is not fully signed.
1653 */
1654 if (sigrdataset != NULL && !dns_db_issecure(db) &&
1655 dns_rdataset_isassociated(sigrdataset))
1656 {
1657 dns_rdataset_disassociate(sigrdataset);
1658 }
1659
1660 *nodep = node;
1661
1662 return ISC_R_SUCCESS;
1663 }
1664
1665 /*
1666 * For query context 'qctx', try finding authoritative additional data for
1667 * given 'name' and 'type'. Called from query_additional_cb().
1668 *
1669 * If successful:
1670 *
1671 * - store pointers to the database and node which contain the result in
1672 * 'dbp' and 'nodep', respectively,
1673 *
1674 * - store the owner name of the returned node in 'fname',
1675 *
1676 * - potentially bind 'rdataset' and 'sigrdataset', as explained in the
1677 * comment for query_additionalauthfind().
1678 *
1679 * If unsuccessful:
1680 *
1681 * - 'dbp' and 'nodep' will not be written to,
1682 * - 'fname' may still be modified as it is passed to dns_db_findext(),
1683 * - 'rdataset' and 'sigrdataset' will remain disassociated.
1684 */
1685 static isc_result_t
1686 query_additionalauth(query_ctx_t *qctx, const dns_name_t *name,
1687 dns_rdatatype_t type, dns_db_t **dbp, dns_dbnode_t **nodep,
1688 dns_name_t *fname, dns_rdataset_t *rdataset,
1689 dns_rdataset_t *sigrdataset) {
1690 ns_client_t *client = qctx->client;
1691 ns_dbversion_t *dbversion = NULL;
1692 dns_dbversion_t *version = NULL;
1693 dns_dbnode_t *node = NULL;
1694 dns_zone_t *zone = NULL;
1695 dns_db_t *db = NULL;
1696 isc_result_t result;
1697
1698 /*
1699 * First, look within the same zone database for authoritative
1700 * additional data.
1701 */
1702 if (!client->query.authdbset || client->query.authdb == NULL) {
1703 return ISC_R_NOTFOUND;
1704 }
1705
1706 dbversion = ns_client_findversion(client, client->query.authdb);
1707 if (dbversion == NULL) {
1708 return ISC_R_NOTFOUND;
1709 }
1710
1711 dns_db_attach(client->query.authdb, &db);
1712 version = dbversion->version;
1713
1714 CTRACE(ISC_LOG_DEBUG(3), "query_additionalauth: same zone");
1715
1716 result = query_additionalauthfind(db, version, name, type, client,
1717 &node, fname, rdataset, sigrdataset);
1718 if (result != ISC_R_SUCCESS &&
1719 qctx->view->minimalresponses == dns_minimal_no &&
1720 RECURSIONOK(client))
1721 {
1722 /*
1723 * If we aren't doing response minimization and recursion is
1724 * allowed, we can try and see if any other zone matches.
1725 */
1726 version = NULL;
1727 dns_db_detach(&db);
1728 dns_getdb_options_t options = { .nolog = true };
1729 result = query_getzonedb(client, name, type, options, &zone,
1730 &db, &version);
1731 if (result != ISC_R_SUCCESS) {
1732 return result;
1733 }
1734 dns_zone_detach(&zone);
1735
1736 CTRACE(ISC_LOG_DEBUG(3), "query_additionalauth: other zone");
1737
1738 result = query_additionalauthfind(db, version, name, type,
1739 client, &node, fname,
1740 rdataset, sigrdataset);
1741 }
1742
1743 if (result != ISC_R_SUCCESS) {
1744 dns_db_detach(&db);
1745 } else {
1746 *nodep = node;
1747 node = NULL;
1748
1749 *dbp = db;
1750 db = NULL;
1751 }
1752
1753 return result;
1754 }
1755
1756 static isc_result_t
1757 query_additional_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
1758 dns_rdataset_t *found DNS__DB_FLARG) {
1759 query_ctx_t *qctx = arg;
1760 ns_client_t *client = qctx->client;
1761 isc_result_t result, eresult = ISC_R_SUCCESS;
1762 dns_dbnode_t *node = NULL;
1763 dns_db_t *db = NULL;
1764 dns_name_t *fname = NULL, *mname = NULL;
1765 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
1766 dns_rdataset_t *trdataset = NULL;
1767 isc_buffer_t *dbuf = NULL;
1768 isc_buffer_t b;
1769 ns_dbversion_t *dbversion = NULL;
1770 dns_dbversion_t *version = NULL;
1771 bool added_something = false, need_addname = false;
1772 dns_rdatatype_t type;
1773 dns_clientinfomethods_t cm;
1774 dns_clientinfo_t ci;
1775 dns_rdatasetadditional_t additionaltype =
1776 dns_rdatasetadditional_fromauth;
1777
1778 REQUIRE(NS_CLIENT_VALID(client));
1779 REQUIRE(qtype != dns_rdatatype_any);
1780
1781 if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype)) {
1782 return ISC_R_SUCCESS;
1783 }
1784
1785 CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb");
1786
1787 dns_clientinfomethods_init(&cm, ns_client_sourceip);
1788 dns_clientinfo_init(&ci, client, NULL);
1789
1790 /*
1791 * We treat type A additional section processing as if it
1792 * were "any address type" additional section processing.
1793 * To avoid multiple lookups, we do an 'any' database
1794 * lookup and iterate over the node.
1795 */
1796 if (qtype == dns_rdatatype_a) {
1797 type = dns_rdatatype_any;
1798 } else {
1799 type = qtype;
1800 }
1801
1802 /*
1803 * Get some resources.
1804 */
1805 dbuf = ns_client_getnamebuf(client);
1806 fname = ns_client_newname(client, dbuf, &b);
1807 rdataset = ns_client_newrdataset(client);
1808 if (WANTDNSSEC(client)) {
1809 sigrdataset = ns_client_newrdataset(client);
1810 }
1811
1812 /*
1813 * If we want only minimal responses and are here, then it must
1814 * be for glue.
1815 */
1816 if (qctx->view->minimalresponses == dns_minimal_yes &&
1817 client->query.qtype != dns_rdatatype_ns)
1818 {
1819 goto try_glue;
1820 }
1821
1822 /*
1823 * First, look for authoritative additional data.
1824 */
1825 result = query_additionalauth(qctx, name, type, &db, &node, fname,
1826 rdataset, sigrdataset);
1827 if (result == ISC_R_SUCCESS) {
1828 goto found;
1829 }
1830
1831 /*
1832 * No authoritative data was found. The cache is our next best bet.
1833 */
1834 if (!qctx->view->recursion) {
1835 goto try_glue;
1836 }
1837
1838 additionaltype = dns_rdatasetadditional_fromcache;
1839 dns_getdb_options_t options = { .nolog = true };
1840 result = query_getcachedb(client, name, qtype, &db, options);
1841 if (result != ISC_R_SUCCESS) {
1842 /*
1843 * Most likely the client isn't allowed to query the cache.
1844 */
1845 goto try_glue;
1846 }
1847 /*
1848 * Attempt to validate glue.
1849 */
1850 if (sigrdataset == NULL) {
1851 sigrdataset = ns_client_newrdataset(client);
1852 }
1853
1854 version = NULL;
1855 result = dns_db_findext(db, name, version, type,
1856 client->query.dboptions | DNS_DBFIND_GLUEOK |
1857 DNS_DBFIND_ADDITIONALOK,
1858 client->now, &node, fname, &cm, &ci, rdataset,
1859 sigrdataset);
1860
1861 dns_cache_updatestats(qctx->view->cache, result);
1862 if (!WANTDNSSEC(client)) {
1863 ns_client_putrdataset(client, &sigrdataset);
1864 }
1865 if (result == ISC_R_SUCCESS) {
1866 goto found;
1867 }
1868
1869 if (dns_rdataset_isassociated(rdataset)) {
1870 dns_rdataset_disassociate(rdataset);
1871 }
1872 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
1873 dns_rdataset_disassociate(sigrdataset);
1874 }
1875 if (node != NULL) {
1876 dns_db_detachnode(db, &node);
1877 }
1878 dns_db_detach(&db);
1879
1880 try_glue:
1881 /*
1882 * No cached data was found. Glue is our last chance.
1883 * RFC1035 sayeth:
1884 *
1885 * NS records cause both the usual additional section
1886 * processing to locate a type A record, and, when used
1887 * in a referral, a special search of the zone in which
1888 * they reside for glue information.
1889 *
1890 * This is the "special search". Note that we must search
1891 * the zone where the NS record resides, not the zone it
1892 * points to, and that we only do the search in the delegation
1893 * case (identified by client->query.gluedb being set).
1894 */
1895
1896 if (client->query.gluedb == NULL) {
1897 goto cleanup;
1898 }
1899
1900 /*
1901 * Don't poison caches using the bailiwick protection model.
1902 */
1903 if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb))) {
1904 goto cleanup;
1905 }
1906
1907 dbversion = ns_client_findversion(client, client->query.gluedb);
1908 if (dbversion == NULL) {
1909 goto cleanup;
1910 }
1911
1912 dns_db_attach(client->query.gluedb, &db);
1913 version = dbversion->version;
1914 additionaltype = dns_rdatasetadditional_fromglue;
1915 result = dns_db_findext(db, name, version, type,
1916 client->query.dboptions | DNS_DBFIND_GLUEOK,
1917 client->now, &node, fname, &cm, &ci, rdataset,
1918 sigrdataset);
1919 if (result != ISC_R_SUCCESS && result != DNS_R_ZONECUT &&
1920 result != DNS_R_GLUE)
1921 {
1922 goto cleanup;
1923 }
1924
1925 found:
1926 /*
1927 * We have found a potential additional data rdataset, or
1928 * at least a node to iterate over.
1929 */
1930 ns_client_keepname(client, fname, dbuf);
1931
1932 /*
1933 * Does the caller want the found rdataset?
1934 */
1935 if (found != NULL && dns_rdataset_isassociated(rdataset)) {
1936 dns_rdataset_clone(rdataset, found);
1937 }
1938
1939 /*
1940 * If we have an rdataset, add it to the additional data
1941 * section.
1942 */
1943 mname = NULL;
1944 if (dns_rdataset_isassociated(rdataset) &&
1945 !query_isduplicate(client, fname, type, &mname))
1946 {
1947 if (mname != NULL) {
1948 INSIST(mname != fname);
1949 ns_client_releasename(client, &fname);
1950 fname = mname;
1951 } else {
1952 need_addname = true;
1953 }
1954 ISC_LIST_APPEND(fname->list, rdataset, link);
1955 trdataset = rdataset;
1956 rdataset = NULL;
1957 added_something = true;
1958 /*
1959 * Note: we only add SIGs if we've added the type they cover,
1960 * so we do not need to check if the SIG rdataset is already
1961 * in the response.
1962 */
1963 if (sigrdataset != NULL &&
1964 dns_rdataset_isassociated(sigrdataset))
1965 {
1966 ISC_LIST_APPEND(fname->list, sigrdataset, link);
1967 sigrdataset = NULL;
1968 }
1969 }
1970
1971 if (qtype == dns_rdatatype_a) {
1972 /*
1973 * We now go looking for A and AAAA records, along with
1974 * their signatures.
1975 *
1976 * XXXRTH This code could be more efficient.
1977 */
1978 if (rdataset != NULL) {
1979 if (dns_rdataset_isassociated(rdataset)) {
1980 dns_rdataset_disassociate(rdataset);
1981 }
1982 } else {
1983 rdataset = ns_client_newrdataset(client);
1984 }
1985 if (sigrdataset != NULL) {
1986 if (dns_rdataset_isassociated(sigrdataset)) {
1987 dns_rdataset_disassociate(sigrdataset);
1988 }
1989 } else if (WANTDNSSEC(client)) {
1990 sigrdataset = ns_client_newrdataset(client);
1991 }
1992 if (query_isduplicate(client, fname, dns_rdatatype_a, NULL)) {
1993 goto aaaa_lookup;
1994 }
1995 result = dns_db_findrdataset(db, node, version, dns_rdatatype_a,
1996 0, client->now, rdataset,
1997 sigrdataset);
1998 if (result == DNS_R_NCACHENXDOMAIN) {
1999 goto addname;
2000 } else if (result == DNS_R_NCACHENXRRSET) {
2001 dns_rdataset_disassociate(rdataset);
2002 if (sigrdataset != NULL &&
2003 dns_rdataset_isassociated(sigrdataset))
2004 {
2005 dns_rdataset_disassociate(sigrdataset);
2006 }
2007 } else if (result == ISC_R_SUCCESS) {
2008 bool invalid = false;
2009 mname = NULL;
2010 if (additionaltype ==
2011 dns_rdatasetadditional_fromcache &&
2012 (DNS_TRUST_PENDING(rdataset->trust) ||
2013 DNS_TRUST_GLUE(rdataset->trust)))
2014 {
2015 /* validate() may change rdataset->trust */
2016 invalid = !validate(client, db, fname, rdataset,
2017 sigrdataset);
2018 }
2019 if (invalid && DNS_TRUST_PENDING(rdataset->trust)) {
2020 dns_rdataset_disassociate(rdataset);
2021 if (sigrdataset != NULL &&
2022 dns_rdataset_isassociated(sigrdataset))
2023 {
2024 dns_rdataset_disassociate(sigrdataset);
2025 }
2026 } else if (!query_isduplicate(client, fname,
2027 dns_rdatatype_a, &mname))
2028 {
2029 if (mname != fname) {
2030 if (mname != NULL) {
2031 ns_client_releasename(client,
2032 &fname);
2033 fname = mname;
2034 } else {
2035 need_addname = true;
2036 }
2037 }
2038 ISC_LIST_APPEND(fname->list, rdataset, link);
2039 added_something = true;
2040 if (sigrdataset != NULL &&
2041 dns_rdataset_isassociated(sigrdataset))
2042 {
2043 ISC_LIST_APPEND(fname->list,
2044 sigrdataset, link);
2045 sigrdataset =
2046 ns_client_newrdataset(client);
2047 }
2048 rdataset = ns_client_newrdataset(client);
2049 } else {
2050 dns_rdataset_disassociate(rdataset);
2051 if (sigrdataset != NULL &&
2052 dns_rdataset_isassociated(sigrdataset))
2053 {
2054 dns_rdataset_disassociate(sigrdataset);
2055 }
2056 }
2057 }
2058 aaaa_lookup:
2059 if (query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL))
2060 {
2061 goto addname;
2062 }
2063 result = dns_db_findrdataset(db, node, version,
2064 dns_rdatatype_aaaa, 0, client->now,
2065 rdataset, sigrdataset);
2066 if (result == DNS_R_NCACHENXDOMAIN) {
2067 goto addname;
2068 } else if (result == DNS_R_NCACHENXRRSET) {
2069 dns_rdataset_disassociate(rdataset);
2070 if (sigrdataset != NULL &&
2071 dns_rdataset_isassociated(sigrdataset))
2072 {
2073 dns_rdataset_disassociate(sigrdataset);
2074 }
2075 } else if (result == ISC_R_SUCCESS) {
2076 bool invalid = false;
2077 mname = NULL;
2078
2079 if (additionaltype ==
2080 dns_rdatasetadditional_fromcache &&
2081 (DNS_TRUST_PENDING(rdataset->trust) ||
2082 DNS_TRUST_GLUE(rdataset->trust)))
2083 {
2084 /* validate() may change rdataset->trust */
2085 invalid = !validate(client, db, fname, rdataset,
2086 sigrdataset);
2087 }
2088
2089 if (invalid && DNS_TRUST_PENDING(rdataset->trust)) {
2090 dns_rdataset_disassociate(rdataset);
2091 if (sigrdataset != NULL &&
2092 dns_rdataset_isassociated(sigrdataset))
2093 {
2094 dns_rdataset_disassociate(sigrdataset);
2095 }
2096 } else if (!query_isduplicate(client, fname,
2097 dns_rdatatype_aaaa,
2098 &mname))
2099 {
2100 if (mname != fname) {
2101 if (mname != NULL) {
2102 ns_client_releasename(client,
2103 &fname);
2104 fname = mname;
2105 } else {
2106 need_addname = true;
2107 }
2108 }
2109 ISC_LIST_APPEND(fname->list, rdataset, link);
2110 added_something = true;
2111 if (sigrdataset != NULL &&
2112 dns_rdataset_isassociated(sigrdataset))
2113 {
2114 ISC_LIST_APPEND(fname->list,
2115 sigrdataset, link);
2116 sigrdataset = NULL;
2117 }
2118 rdataset = NULL;
2119 }
2120 }
2121 }
2122
2123 addname:
2124 CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb: addname");
2125 /*
2126 * If we haven't added anything, then we're done.
2127 */
2128 if (!added_something) {
2129 goto cleanup;
2130 }
2131
2132 /*
2133 * We may have added our rdatasets to an existing name, if so, then
2134 * need_addname will be false. Whether we used an existing name
2135 * or a new one, we must set fname to NULL to prevent cleanup.
2136 */
2137 if (need_addname) {
2138 dns_message_addname(client->message, fname,
2139 DNS_SECTION_ADDITIONAL);
2140 }
2141
2142 /*
2143 * In some cases, a record that has been added as additional
2144 * data may *also* trigger the addition of additional data.
2145 * This cannot go more than 'max-restarts' levels deep.
2146 */
2147 if (trdataset != NULL && dns_rdatatype_followadditional(type)) {
2148 if (client->additionaldepth++ < client->view->max_restarts) {
2149 eresult = dns_rdataset_additionaldata(
2150 trdataset, fname, query_additional_cb, qctx,
2151 DNS_RDATASET_MAXADDITIONAL);
2152 }
2153 client->additionaldepth--;
2154 }
2155
2156 /*
2157 * Don't release fname.
2158 */
2159 fname = NULL;
2160
2161 cleanup:
2162 CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb: cleanup");
2163 ns_client_putrdataset(client, &rdataset);
2164 if (sigrdataset != NULL) {
2165 ns_client_putrdataset(client, &sigrdataset);
2166 }
2167 if (fname != NULL) {
2168 ns_client_releasename(client, &fname);
2169 }
2170 if (node != NULL) {
2171 dns_db_detachnode(db, &node);
2172 }
2173 if (db != NULL) {
2174 dns_db_detach(&db);
2175 }
2176
2177 CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb: done");
2178 return eresult;
2179 }
2180
2181 /*
2182 * Add 'rdataset' to 'name'.
2183 */
2184 static void
2185 query_addtoname(dns_name_t *name, dns_rdataset_t *rdataset) {
2186 ISC_LIST_APPEND(name->list, rdataset, link);
2187 }
2188
2189 /*
2190 * Set the ordering for 'rdataset'.
2191 */
2192 static void
2193 query_setorder(query_ctx_t *qctx, dns_name_t *name, dns_rdataset_t *rdataset) {
2194 ns_client_t *client = qctx->client;
2195 dns_order_t *order = client->view->order;
2196
2197 CTRACE(ISC_LOG_DEBUG(3), "query_setorder");
2198
2199 UNUSED(client);
2200
2201 if (order != NULL) {
2202 rdataset->attributes |= dns_order_find(
2203 order, name, rdataset->type, rdataset->rdclass);
2204 }
2205 rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
2206 }
2207
2208 /*
2209 * Handle glue and fetch any other needed additional data for 'rdataset'.
2210 */
2211 static void
2212 query_additional(query_ctx_t *qctx, dns_name_t *name,
2213 dns_rdataset_t *rdataset) {
2214 ns_client_t *client = qctx->client;
2215 isc_result_t result;
2216
2217 CTRACE(ISC_LOG_DEBUG(3), "query_additional");
2218
2219 if (NOADDITIONAL(client)) {
2220 return;
2221 }
2222
2223 /*
2224 * Try to process glue directly.
2225 */
2226 if (rdataset->type == dns_rdatatype_ns &&
2227 client->query.gluedb != NULL && dns_db_iszone(client->query.gluedb))
2228 {
2229 ns_dbversion_t *dbversion = NULL;
2230
2231 dbversion = ns_client_findversion(client, client->query.gluedb);
2232 if (dbversion == NULL) {
2233 goto regular;
2234 }
2235
2236 result = dns_db_addglue(qctx->db, dbversion->version, rdataset,
2237 client->message);
2238 if (result == ISC_R_SUCCESS) {
2239 return;
2240 }
2241 }
2242
2243 regular:
2244 /*
2245 * Add other additional data if needed.
2246 * We don't care if dns_rdataset_additionaldata() fails.
2247 */
2248 (void)dns_rdataset_additionaldata(rdataset, name, query_additional_cb,
2249 qctx, DNS_RDATASET_MAXADDITIONAL);
2250 CTRACE(ISC_LOG_DEBUG(3), "query_additional: done");
2251 }
2252
2253 static void
2254 query_addrrset(query_ctx_t *qctx, dns_name_t **namep,
2255 dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp,
2256 isc_buffer_t *dbuf, dns_section_t section) {
2257 isc_result_t result;
2258 ns_client_t *client = qctx->client;
2259 dns_name_t *name = *namep, *mname = NULL;
2260 dns_rdataset_t *rdataset = *rdatasetp, *mrdataset = NULL;
2261 dns_rdataset_t *sigrdataset = NULL;
2262
2263 CTRACE(ISC_LOG_DEBUG(3), "query_addrrset");
2264
2265 REQUIRE(name != NULL);
2266
2267 if (sigrdatasetp != NULL) {
2268 sigrdataset = *sigrdatasetp;
2269 }
2270
2271 /*%
2272 * To the current response for 'client', add the answer RRset
2273 * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
2274 * owner name '*namep', to section 'section', unless they are
2275 * already there. Also add any pertinent additional data, unless
2276 * the query was for type ANY.
2277 *
2278 * If 'dbuf' is not NULL, then '*namep' is the name whose data is
2279 * stored in 'dbuf'. In this case, query_addrrset() guarantees that
2280 * when it returns the name will either have been kept or released.
2281 */
2282 result = dns_message_findname(client->message, section, name,
2283 rdataset->type, rdataset->covers, &mname,
2284 &mrdataset);
2285 if (result == ISC_R_SUCCESS) {
2286 /*
2287 * We've already got an RRset of the given name and type.
2288 */
2289 CTRACE(ISC_LOG_DEBUG(3), "query_addrrset: dns_message_findname "
2290 "succeeded: done");
2291 if (dbuf != NULL) {
2292 ns_client_releasename(client, namep);
2293 }
2294 if ((rdataset->attributes & DNS_RDATASETATTR_REQUIRED) != 0) {
2295 mrdataset->attributes |= DNS_RDATASETATTR_REQUIRED;
2296 }
2297 if ((rdataset->attributes & DNS_RDATASETATTR_STALE_ADDED) != 0)
2298 {
2299 mrdataset->attributes |= DNS_RDATASETATTR_STALE_ADDED;
2300 }
2301 return;
2302 } else if (result == DNS_R_NXDOMAIN) {
2303 /*
2304 * The name doesn't exist.
2305 */
2306 if (dbuf != NULL) {
2307 ns_client_keepname(client, name, dbuf);
2308 }
2309 dns_message_addname(client->message, name, section);
2310 *namep = NULL;
2311 mname = name;
2312 } else {
2313 RUNTIME_CHECK(result == DNS_R_NXRRSET);
2314 if (dbuf != NULL) {
2315 ns_client_releasename(client, namep);
2316 }
2317 }
2318
2319 if (rdataset->trust != dns_trust_secure &&
2320 (section == DNS_SECTION_ANSWER || section == DNS_SECTION_AUTHORITY))
2321 {
2322 client->query.attributes &= ~NS_QUERYATTR_SECURE;
2323 }
2324
2325 /*
2326 * Update message name, set rdataset order, and do additional
2327 * section processing if needed.
2328 */
2329 query_addtoname(mname, rdataset);
2330 query_setorder(qctx, mname, rdataset);
2331 if (qctx->qtype != dns_rdatatype_any) {
2332 query_additional(qctx, mname, rdataset);
2333 }
2334
2335 /*
2336 * Note: we only add SIGs if we've added the type they cover, so
2337 * we do not need to check if the SIG rdataset is already in the
2338 * response.
2339 */
2340 *rdatasetp = NULL;
2341 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
2342 /*
2343 * We have a signature. Add it to the response.
2344 */
2345 ISC_LIST_APPEND(mname->list, sigrdataset, link);
2346 *sigrdatasetp = NULL;
2347 }
2348
2349 CTRACE(ISC_LOG_DEBUG(3), "query_addrrset: done");
2350 }
2351
2352 /*
2353 * Mark the RRsets as secure. Update the cache (db) to reflect the
2354 * change in trust level.
2355 */
2356 static void
2357 mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name,
2358 dns_rdata_rrsig_t *rrsig, dns_rdataset_t *rdataset,
2359 dns_rdataset_t *sigrdataset) {
2360 isc_result_t result;
2361 dns_dbnode_t *node = NULL;
2362 dns_clientinfomethods_t cm;
2363 dns_clientinfo_t ci;
2364 isc_stdtime_t now;
2365
2366 rdataset->trust = dns_trust_secure;
2367 sigrdataset->trust = dns_trust_secure;
2368 dns_clientinfomethods_init(&cm, ns_client_sourceip);
2369 dns_clientinfo_init(&ci, client, NULL);
2370
2371 /*
2372 * Save the updated secure state. Ignore failures.
2373 */
2374 result = dns_db_findnodeext(db, name, true, &cm, &ci, &node);
2375 if (result != ISC_R_SUCCESS) {
2376 return;
2377 }
2378
2379 now = isc_stdtime_now();
2380 dns_rdataset_trimttl(rdataset, sigrdataset, rrsig, now,
2381 client->view->acceptexpired);
2382
2383 (void)dns_db_addrdataset(db, node, NULL, client->now, rdataset, 0,
2384 NULL);
2385 (void)dns_db_addrdataset(db, node, NULL, client->now, sigrdataset, 0,
2386 NULL);
2387 dns_db_detachnode(db, &node);
2388 }
2389
2390 /*
2391 * Find the secure key that corresponds to rrsig.
2392 * Note: 'keyrdataset' maintains state between successive calls,
2393 * there may be multiple keys with the same keyid.
2394 * Return false if we have exhausted all the possible keys.
2395 */
2396 static bool
2397 get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
2398 dns_rdataset_t *keyrdataset, dst_key_t **keyp) {
2399 isc_result_t result;
2400 dns_dbnode_t *node = NULL;
2401 bool secure = false;
2402 dns_clientinfomethods_t cm;
2403 dns_clientinfo_t ci;
2404
2405 dns_clientinfomethods_init(&cm, ns_client_sourceip);
2406 dns_clientinfo_init(&ci, client, NULL);
2407
2408 if (!dns_rdataset_isassociated(keyrdataset)) {
2409 result = dns_db_findnodeext(db, &rrsig->signer, false, &cm, &ci,
2410 &node);
2411 if (result != ISC_R_SUCCESS) {
2412 return false;
2413 }
2414
2415 result = dns_db_findrdataset(db, node, NULL,
2416 dns_rdatatype_dnskey, 0,
2417 client->now, keyrdataset, NULL);
2418 dns_db_detachnode(db, &node);
2419 if (result != ISC_R_SUCCESS) {
2420 return false;
2421 }
2422
2423 if (keyrdataset->trust != dns_trust_secure) {
2424 return false;
2425 }
2426
2427 result = dns_rdataset_first(keyrdataset);
2428 } else {
2429 result = dns_rdataset_next(keyrdataset);
2430 }
2431
2432 for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(keyrdataset))
2433 {
2434 dns_rdata_t rdata = DNS_RDATA_INIT;
2435 isc_buffer_t b;
2436
2437 dns_rdataset_current(keyrdataset, &rdata);
2438 isc_buffer_init(&b, rdata.data, rdata.length);
2439 isc_buffer_add(&b, rdata.length);
2440 result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b,
2441 client->manager->mctx, keyp);
2442 if (result != ISC_R_SUCCESS) {
2443 continue;
2444 }
2445 if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) &&
2446 rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) &&
2447 dst_key_iszonekey(*keyp))
2448 {
2449 secure = true;
2450 break;
2451 }
2452 dst_key_free(keyp);
2453 }
2454 return secure;
2455 }
2456
2457 static bool
2458 verify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset,
2459 dns_rdata_t *rdata, ns_client_t *client) {
2460 isc_result_t result;
2461 dns_fixedname_t fixed;
2462 bool ignore = false;
2463
2464 dns_fixedname_init(&fixed);
2465
2466 again:
2467 result = dns_dnssec_verify(name, rdataset, key, ignore,
2468 client->view->maxbits, client->manager->mctx,
2469 rdata, NULL);
2470 if (result == DNS_R_SIGEXPIRED && client->view->acceptexpired) {
2471 ignore = true;
2472 goto again;
2473 }
2474 if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) {
2475 return true;
2476 }
2477 return false;
2478 }
2479
2480 /*
2481 * Validate the rdataset if possible with available records.
2482 */
2483 static bool
2484 validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
2485 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
2486 isc_result_t result;
2487 dns_rdata_t rdata = DNS_RDATA_INIT;
2488 dns_rdata_rrsig_t rrsig;
2489 dst_key_t *key = NULL;
2490 dns_rdataset_t keyrdataset;
2491
2492 if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset)) {
2493 return false;
2494 }
2495
2496 for (result = dns_rdataset_first(sigrdataset); result == ISC_R_SUCCESS;
2497 result = dns_rdataset_next(sigrdataset))
2498 {
2499 dns_rdata_reset(&rdata);
2500 dns_rdataset_current(sigrdataset, &rdata);
2501 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
2502 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2503 if (!dns_resolver_algorithm_supported(client->view->resolver,
2504 name, rrsig.algorithm))
2505 {
2506 char txt[DNS_NAME_FORMATSIZE + 32];
2507 isc_buffer_t buffer;
2508
2509 isc_buffer_init(&buffer, txt, sizeof(txt));
2510 dns_secalg_totext(rrsig.algorithm, &buffer);
2511 isc_buffer_putstr(&buffer, " ");
2512 dns_name_totext(name, DNS_NAME_OMITFINALDOT, &buffer);
2513 isc_buffer_putstr(&buffer, " (cached)");
2514 isc_buffer_putuint8(&buffer, 0);
2515
2516 dns_ede_add(&client->edectx, DNS_EDE_DNSKEYALG,
2517 isc_buffer_base(&buffer));
2518 continue;
2519 }
2520 if (!dns_name_issubdomain(name, &rrsig.signer)) {
2521 continue;
2522 }
2523 dns_rdataset_init(&keyrdataset);
2524 do {
2525 if (!get_key(client, db, &rrsig, &keyrdataset, &key)) {
2526 break;
2527 }
2528 if (verify(key, name, rdataset, &rdata, client)) {
2529 dst_key_free(&key);
2530 dns_rdataset_disassociate(&keyrdataset);
2531 mark_secure(client, db, name, &rrsig, rdataset,
2532 sigrdataset);
2533 return true;
2534 }
2535 dst_key_free(&key);
2536 } while (1);
2537 if (dns_rdataset_isassociated(&keyrdataset)) {
2538 dns_rdataset_disassociate(&keyrdataset);
2539 }
2540 }
2541 return false;
2542 }
2543
2544 static void
2545 fixrdataset(ns_client_t *client, dns_rdataset_t **rdataset) {
2546 if (*rdataset == NULL) {
2547 *rdataset = ns_client_newrdataset(client);
2548 } else if (dns_rdataset_isassociated(*rdataset)) {
2549 dns_rdataset_disassociate(*rdataset);
2550 }
2551 }
2552
2553 static void
2554 fixfname(ns_client_t *client, dns_name_t **fname, isc_buffer_t **dbuf,
2555 isc_buffer_t *nbuf) {
2556 if (*fname == NULL) {
2557 *dbuf = ns_client_getnamebuf(client);
2558 *fname = ns_client_newname(client, *dbuf, nbuf);
2559 }
2560 }
2561
2562 static void
2563 free_fresp(ns_client_t *client, dns_fetchresponse_t **frespp) {
2564 dns_fetchresponse_t *fresp = *frespp;
2565
2566 CTRACE(ISC_LOG_DEBUG(3), "free_fresp");
2567
2568 if (fresp->fetch != NULL) {
2569 dns_resolver_destroyfetch(&fresp->fetch);
2570 }
2571 if (fresp->node != NULL) {
2572 dns_db_detachnode(fresp->db, &fresp->node);
2573 }
2574 if (fresp->db != NULL) {
2575 dns_db_detach(&fresp->db);
2576 }
2577 if (fresp->rdataset != NULL) {
2578 ns_client_putrdataset(client, &fresp->rdataset);
2579 }
2580 if (fresp->sigrdataset != NULL) {
2581 ns_client_putrdataset(client, &fresp->sigrdataset);
2582 }
2583
2584 dns_resolver_freefresp(frespp);
2585 }
2586
2587 static isc_result_t
2588 recursionquotatype_attach(ns_client_t *client, bool soft_limit) {
2589 isc_statscounter_t recurscount;
2590 isc_result_t result;
2591
2592 result = isc_quota_acquire(&client->manager->sctx->recursionquota);
2593 switch (result) {
2594 case ISC_R_SUCCESS:
2595 break;
2596 case ISC_R_SOFTQUOTA:
2597 if (soft_limit) {
2598 /*
2599 * Exceeding soft quota was allowed, so continue as if
2600 * 'result' was ISC_R_SUCCESS while retaining the
2601 * original result code.
2602 */
2603 break;
2604 }
2605
2606 isc_quota_release(&client->manager->sctx->recursionquota);
2607 FALLTHROUGH;
2608 default:
2609 return result;
2610 }
2611
2612 recurscount = ns_stats_increment(client->manager->sctx->nsstats,
2613 ns_statscounter_recursclients);
2614
2615 ns_stats_update_if_greater(client->manager->sctx->nsstats,
2616 ns_statscounter_recurshighwater,
2617 recurscount + 1);
2618
2619 return result;
2620 }
2621
2622 static isc_result_t
2623 recursionquotatype_attach_hard(ns_client_t *client) {
2624 return recursionquotatype_attach(client, false);
2625 }
2626
2627 static isc_result_t
2628 recursionquotatype_attach_soft(ns_client_t *client) {
2629 return recursionquotatype_attach(client, true);
2630 }
2631
2632 static void
2633 recursionquotatype_detach(ns_client_t *client) {
2634 isc_quota_release(&client->manager->sctx->recursionquota);
2635 ns_stats_decrement(client->manager->sctx->nsstats,
2636 ns_statscounter_recursclients);
2637 }
2638
2639 static void
2640 stale_refresh_aftermath(ns_client_t *client, isc_result_t result) {
2641 dns_db_t *db = NULL;
2642 unsigned int dboptions;
2643 isc_buffer_t buffer;
2644 query_ctx_t qctx;
2645 dns_clientinfomethods_t cm;
2646 dns_clientinfo_t ci;
2647 char namebuf[DNS_NAME_FORMATSIZE];
2648 char typebuf[DNS_RDATATYPE_FORMATSIZE];
2649
2650 /*
2651 * If refreshing a stale RRset failed, we need to set the
2652 * stale-refresh-time window, so that on future requests for this
2653 * RRset the stale entry may be used immediately.
2654 */
2655 switch (result) {
2656 case ISC_R_SUCCESS:
2657 case DNS_R_GLUE:
2658 case DNS_R_ZONECUT:
2659 case ISC_R_NOTFOUND:
2660 case DNS_R_DELEGATION:
2661 case DNS_R_EMPTYNAME:
2662 case DNS_R_NXRRSET:
2663 case DNS_R_EMPTYWILD:
2664 case DNS_R_NXDOMAIN:
2665 case DNS_R_COVERINGNSEC:
2666 case DNS_R_NCACHENXDOMAIN:
2667 case DNS_R_NCACHENXRRSET:
2668 case DNS_R_CNAME:
2669 case DNS_R_DNAME:
2670 break;
2671 default:
2672 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
2673 dns_rdatatype_format(client->query.qtype, typebuf,
2674 sizeof(typebuf));
2675 ns_client_log(client, NS_LOGCATEGORY_SERVE_STALE,
2676 NS_LOGMODULE_QUERY, ISC_LOG_NOTICE,
2677 "%s/%s stale refresh failed: timed out", namebuf,
2678 typebuf);
2679
2680 /*
2681 * Set up a short lived query context, solely to set the
2682 * last refresh failure time on the RRset in the cache
2683 * database, starting the stale-refresh-time window for it.
2684 * This is a condensed form of query_lookup().
2685 */
2686 client->now = isc_stdtime_now();
2687 client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK;
2688 qctx_init(client, NULL, 0, &qctx);
2689
2690 dns_clientinfomethods_init(&cm, ns_client_sourceip);
2691 dns_clientinfo_init(&ci, qctx.client, NULL);
2692 if (HAVEECS(qctx.client)) {
2693 dns_clientinfo_setecs(&ci, &qctx.client->ecs);
2694 }
2695
2696 result = qctx_prepare_buffers(&qctx, &buffer);
2697 if (result != ISC_R_SUCCESS) {
2698 goto cleanup;
2699 }
2700
2701 dboptions = qctx.client->query.dboptions;
2702 dboptions |= DNS_DBFIND_STALEOK;
2703 dboptions |= DNS_DBFIND_STALESTART;
2704
2705 dns_db_attach(qctx.client->view->cachedb, &db);
2706 (void)dns_db_findext(db, qctx.client->query.qname, NULL,
2707 qctx.client->query.qtype, dboptions,
2708 qctx.client->now, &qctx.node, qctx.fname,
2709 &cm, &ci, qctx.rdataset, qctx.sigrdataset);
2710 if (qctx.node != NULL) {
2711 dns_db_detachnode(db, &qctx.node);
2712 }
2713 dns_db_detach(&db);
2714
2715 cleanup:
2716 qctx_freedata(&qctx);
2717 qctx_destroy(&qctx);
2718 }
2719 }
2720
2721 static void
2722 cleanup_after_fetch(dns_fetchresponse_t *resp, const char *ctracestr,
2723 ns_query_rectype_t recursion_type) {
2724 ns_client_t *client = resp->arg;
2725 isc_nmhandle_t **handlep = NULL;
2726 dns_fetch_t **fetchp = NULL;
2727 isc_result_t result;
2728
2729 REQUIRE(NS_CLIENT_VALID(client));
2730
2731 CTRACE(ISC_LOG_DEBUG(3), ctracestr);
2732
2733 handlep = &client->query.recursions[recursion_type].handle;
2734 fetchp = &client->query.recursions[recursion_type].fetch;
2735 result = resp->result;
2736
2737 LOCK(&client->query.fetchlock);
2738 if (*fetchp != NULL) {
2739 INSIST(resp->fetch == *fetchp);
2740 *fetchp = NULL;
2741 }
2742 UNLOCK(&client->query.fetchlock);
2743
2744 /* Some type of recursions require a bit of aftermath. */
2745 if (recursion_type == RECTYPE_STALE_REFRESH) {
2746 stale_refresh_aftermath(client, result);
2747 }
2748
2749 recursionquotatype_detach(client);
2750 free_fresp(client, &resp);
2751 isc_nmhandle_detach(handlep);
2752 }
2753
2754 static void
2755 prefetch_done(void *arg) {
2756 cleanup_after_fetch(arg, "prefetch_done", RECTYPE_PREFETCH);
2757 }
2758
2759 static void
2760 rpzfetch_done(void *arg) {
2761 cleanup_after_fetch(arg, "rpzfetch_done", RECTYPE_RPZ);
2762 }
2763
2764 static void
2765 stale_refresh_done(void *arg) {
2766 cleanup_after_fetch(arg, "stale_refresh_done", RECTYPE_STALE_REFRESH);
2767 }
2768
2769 /*
2770 * Try initiating a fetch for the given 'qname' and 'qtype' (using the slot in
2771 * the 'recursions' array indicated by 'recursion_type') that will be
2772 * associated with 'client'. If the recursive clients quota (or even soft
2773 * quota) is reached or some other error occurs, just return without starting
2774 * the fetch. If a fetch is successfully created, its results will be cached
2775 * upon successful completion, but no further actions will be taken afterwards.
2776 */
2777 static void
2778 fetch_and_forget(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t qtype,
2779 ns_query_rectype_t recursion_type) {
2780 dns_rdataset_t *tmprdataset;
2781 isc_sockaddr_t *peeraddr;
2782 unsigned int options;
2783 isc_job_cb cb;
2784 isc_nmhandle_t **handlep;
2785 dns_fetch_t **fetchp;
2786 isc_result_t result;
2787
2788 result = recursionquotatype_attach_hard(client);
2789 if (result != ISC_R_SUCCESS) {
2790 return;
2791 }
2792
2793 tmprdataset = ns_client_newrdataset(client);
2794
2795 if (!TCP(client)) {
2796 peeraddr = &client->peeraddr;
2797 } else {
2798 peeraddr = NULL;
2799 }
2800
2801 switch (recursion_type) {
2802 case RECTYPE_PREFETCH:
2803 options = client->query.fetchoptions | DNS_FETCHOPT_PREFETCH;
2804 cb = prefetch_done;
2805 break;
2806 case RECTYPE_RPZ:
2807 options = client->query.fetchoptions;
2808 cb = rpzfetch_done;
2809 break;
2810 case RECTYPE_STALE_REFRESH:
2811 options = client->query.fetchoptions;
2812 cb = stale_refresh_done;
2813 break;
2814 default:
2815 UNREACHABLE();
2816 }
2817
2818 handlep = &client->query.recursions[recursion_type].handle;
2819 fetchp = &client->query.recursions[recursion_type].fetch;
2820
2821 isc_nmhandle_attach(client->handle, handlep);
2822 result = dns_resolver_createfetch(
2823 client->view->resolver, qname, qtype, NULL, NULL, NULL,
2824 peeraddr, client->message->id, options, 0, NULL,
2825 client->query.qc, client->manager->loop, cb, client, NULL,
2826 tmprdataset, NULL, fetchp);
2827 if (result != ISC_R_SUCCESS) {
2828 ns_client_putrdataset(client, &tmprdataset);
2829 isc_nmhandle_detach(handlep);
2830 recursionquotatype_detach(client);
2831 }
2832 }
2833
2834 static void
2835 query_prefetch(ns_client_t *client, dns_name_t *qname,
2836 dns_rdataset_t *rdataset) {
2837 CTRACE(ISC_LOG_DEBUG(3), "query_prefetch");
2838
2839 if (FETCH_RECTYPE_PREFETCH(client) != NULL ||
2840 client->view->prefetch_trigger == 0U ||
2841 rdataset->ttl > client->view->prefetch_trigger ||
2842 (rdataset->attributes & DNS_RDATASETATTR_PREFETCH) == 0)
2843 {
2844 return;
2845 }
2846
2847 fetch_and_forget(client, qname, rdataset->type, RECTYPE_PREFETCH);
2848
2849 dns_rdataset_clearprefetch(rdataset);
2850 ns_stats_increment(client->manager->sctx->nsstats,
2851 ns_statscounter_prefetch);
2852 }
2853
2854 static void
2855 query_stale_refresh(ns_client_t *client) {
2856 dns_name_t *qname;
2857
2858 CTRACE(ISC_LOG_DEBUG(3), "query_stale_refresh");
2859
2860 if (FETCH_RECTYPE_STALE_REFRESH(client) != NULL) {
2861 return;
2862 }
2863
2864 client->query.dboptions &= ~(DNS_DBFIND_STALETIMEOUT |
2865 DNS_DBFIND_STALEOK |
2866 DNS_DBFIND_STALEENABLED);
2867
2868 if (client->query.origqname != NULL) {
2869 qname = client->query.origqname;
2870 } else {
2871 qname = client->query.qname;
2872 }
2873
2874 fetch_and_forget(client, qname, client->query.qtype,
2875 RECTYPE_STALE_REFRESH);
2876 }
2877
2878 static void
2879 rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep,
2880 dns_rdataset_t **rdatasetp) {
2881 if (nodep != NULL && *nodep != NULL) {
2882 REQUIRE(dbp != NULL && *dbp != NULL);
2883 dns_db_detachnode(*dbp, nodep);
2884 }
2885 if (dbp != NULL && *dbp != NULL) {
2886 dns_db_detach(dbp);
2887 }
2888 if (zonep != NULL && *zonep != NULL) {
2889 dns_zone_detach(zonep);
2890 }
2891 if (rdatasetp != NULL && *rdatasetp != NULL &&
2892 dns_rdataset_isassociated(*rdatasetp))
2893 {
2894 dns_rdataset_disassociate(*rdatasetp);
2895 }
2896 }
2897
2898 static void
2899 rpz_match_clear(dns_rpz_st_t *st) {
2900 rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset);
2901 st->m.version = NULL;
2902 }
2903
2904 static isc_result_t
2905 rpz_ready(ns_client_t *client, dns_rdataset_t **rdatasetp) {
2906 REQUIRE(rdatasetp != NULL);
2907
2908 CTRACE(ISC_LOG_DEBUG(3), "rpz_ready");
2909
2910 if (*rdatasetp == NULL) {
2911 *rdatasetp = ns_client_newrdataset(client);
2912 } else if (dns_rdataset_isassociated(*rdatasetp)) {
2913 dns_rdataset_disassociate(*rdatasetp);
2914 }
2915 return ISC_R_SUCCESS;
2916 }
2917
2918 static void
2919 rpz_st_clear(ns_client_t *client) {
2920 dns_rpz_st_t *st = client->query.rpz_st;
2921
2922 CTRACE(ISC_LOG_DEBUG(3), "rpz_st_clear");
2923
2924 if (st->m.rdataset != NULL) {
2925 ns_client_putrdataset(client, &st->m.rdataset);
2926 }
2927 rpz_match_clear(st);
2928
2929 rpz_clean(NULL, &st->r.db, NULL, NULL);
2930 if (st->r.ns_rdataset != NULL) {
2931 ns_client_putrdataset(client, &st->r.ns_rdataset);
2932 }
2933 if (st->r.r_rdataset != NULL) {
2934 ns_client_putrdataset(client, &st->r.r_rdataset);
2935 }
2936
2937 rpz_clean(&st->q.zone, &st->q.db, &st->q.node, NULL);
2938 if (st->q.rdataset != NULL) {
2939 ns_client_putrdataset(client, &st->q.rdataset);
2940 }
2941 if (st->q.sigrdataset != NULL) {
2942 ns_client_putrdataset(client, &st->q.sigrdataset);
2943 }
2944 st->state = 0;
2945 st->m.type = DNS_RPZ_TYPE_BAD;
2946 st->m.policy = DNS_RPZ_POLICY_MISS;
2947 if (st->rpsdb != NULL) {
2948 dns_db_detach(&st->rpsdb);
2949 }
2950 }
2951
2952 static dns_rpz_zbits_t
2953 rpz_get_zbits(ns_client_t *client, dns_rdatatype_t ip_type,
2954 dns_rpz_type_t rpz_type) {
2955 dns_rpz_st_t *st;
2956 dns_rpz_zbits_t zbits = 0;
2957
2958 REQUIRE(client != NULL);
2959 REQUIRE(client->query.rpz_st != NULL);
2960
2961 st = client->query.rpz_st;
2962
2963 #ifdef USE_DNSRPS
2964 if (st->popt.dnsrps_enabled) {
2965 if (st->rpsdb == NULL ||
2966 librpz->have_trig(dns_dnsrps_type2trig(rpz_type),
2967 ip_type == dns_rdatatype_aaaa,
2968 ((dns_rpsdb_t *)st->rpsdb)->rsp))
2969 {
2970 return DNS_RPZ_ALL_ZBITS;
2971 }
2972 return 0;
2973 }
2974 #endif /* ifdef USE_DNSRPS */
2975
2976 switch (rpz_type) {
2977 case DNS_RPZ_TYPE_CLIENT_IP:
2978 zbits = st->have.client_ip;
2979 break;
2980 case DNS_RPZ_TYPE_QNAME:
2981 zbits = st->have.qname;
2982 break;
2983 case DNS_RPZ_TYPE_IP:
2984 if (ip_type == dns_rdatatype_a) {
2985 zbits = st->have.ipv4;
2986 } else if (ip_type == dns_rdatatype_aaaa) {
2987 zbits = st->have.ipv6;
2988 } else {
2989 zbits = st->have.ip;
2990 }
2991 break;
2992 case DNS_RPZ_TYPE_NSDNAME:
2993 zbits = st->have.nsdname;
2994 break;
2995 case DNS_RPZ_TYPE_NSIP:
2996 if (ip_type == dns_rdatatype_a) {
2997 zbits = st->have.nsipv4;
2998 } else if (ip_type == dns_rdatatype_aaaa) {
2999 zbits = st->have.nsipv6;
3000 } else {
3001 zbits = st->have.nsip;
3002 }
3003 break;
3004 default:
3005 UNREACHABLE();
3006 }
3007
3008 /*
3009 * Choose
3010 * the earliest configured policy zone (rpz->num)
3011 * QNAME over IP over NSDNAME over NSIP (rpz_type)
3012 * the smallest name,
3013 * the longest IP address prefix,
3014 * the lexically smallest address.
3015 */
3016 if (st->m.policy != DNS_RPZ_POLICY_MISS) {
3017 if (st->m.type >= rpz_type) {
3018 zbits &= DNS_RPZ_ZMASK(st->m.rpz->num);
3019 } else {
3020 zbits &= DNS_RPZ_ZMASK(st->m.rpz->num) >> 1;
3021 }
3022 }
3023
3024 /*
3025 * If the client wants recursion, allow only compatible policies.
3026 */
3027 if (!RECURSIONOK(client)) {
3028 zbits &= st->popt.no_rd_ok;
3029 }
3030
3031 return zbits;
3032 }
3033
3034 static void
3035 query_rpzfetch(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t type) {
3036 CTRACE(ISC_LOG_DEBUG(3), "query_rpzfetch");
3037
3038 if (FETCH_RECTYPE_RPZ(client) != NULL) {
3039 return;
3040 }
3041
3042 fetch_and_forget(client, qname, type, RECTYPE_RPZ);
3043 }
3044
3045 /*
3046 * Get an NS, A, or AAAA rrset related to the response for the client
3047 * to check the contents of that rrset for hits by eligible policy zones.
3048 */
3049 static isc_result_t
3050 rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
3051 unsigned int options, dns_rpz_type_t rpz_type, dns_db_t **dbp,
3052 dns_dbversion_t *version, dns_rdataset_t **rdatasetp,
3053 bool resuming) {
3054 dns_rpz_st_t *st;
3055 bool is_zone;
3056 dns_dbnode_t *node;
3057 dns_fixedname_t fixed;
3058 dns_name_t *found;
3059 isc_result_t result;
3060 dns_clientinfomethods_t cm;
3061 dns_clientinfo_t ci;
3062
3063 CTRACE(ISC_LOG_DEBUG(3), "rpz_rrset_find");
3064
3065 st = client->query.rpz_st;
3066 if ((st->state & DNS_RPZ_RECURSING) != 0) {
3067 INSIST(st->r.r_type == type);
3068 INSIST(dns_name_equal(name, st->r_name));
3069 INSIST(*rdatasetp == NULL ||
3070 !dns_rdataset_isassociated(*rdatasetp));
3071 st->state &= ~DNS_RPZ_RECURSING;
3072 RESTORE(*dbp, st->r.db);
3073 if (*rdatasetp != NULL) {
3074 ns_client_putrdataset(client, rdatasetp);
3075 }
3076 RESTORE(*rdatasetp, st->r.r_rdataset);
3077 result = st->r.r_result;
3078 if (result == DNS_R_DELEGATION) {
3079 CTRACE(ISC_LOG_ERROR, "RPZ recursing");
3080 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
3081 rpz_type, "rpz_rrset_find(1)", result);
3082 st->m.policy = DNS_RPZ_POLICY_ERROR;
3083 result = DNS_R_SERVFAIL;
3084 }
3085 return result;
3086 }
3087
3088 result = rpz_ready(client, rdatasetp);
3089 if (result != ISC_R_SUCCESS) {
3090 st->m.policy = DNS_RPZ_POLICY_ERROR;
3091 return result;
3092 }
3093 if (*dbp != NULL) {
3094 is_zone = false;
3095 } else {
3096 dns_zone_t *zone;
3097
3098 version = NULL;
3099 zone = NULL;
3100 result = query_getdb(client, name, type,
3101 (dns_getdb_options_t){ 0 }, &zone, dbp,
3102 &version, &is_zone);
3103 if (result != ISC_R_SUCCESS) {
3104 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
3105 rpz_type, "rpz_rrset_find(2)", result);
3106 st->m.policy = DNS_RPZ_POLICY_ERROR;
3107 if (zone != NULL) {
3108 dns_zone_detach(&zone);
3109 }
3110 return result;
3111 }
3112 if (zone != NULL) {
3113 dns_zone_detach(&zone);
3114 }
3115 }
3116
3117 node = NULL;
3118 found = dns_fixedname_initname(&fixed);
3119 dns_clientinfomethods_init(&cm, ns_client_sourceip);
3120 dns_clientinfo_init(&ci, client, NULL);
3121 result = dns_db_findext(*dbp, name, version, type, options, client->now,
3122 &node, found, &cm, &ci, *rdatasetp, NULL);
3123 if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) {
3124 /*
3125 * Try the cache if we're authoritative for an
3126 * ancestor but not the domain itself.
3127 */
3128 rpz_clean(NULL, dbp, &node, rdatasetp);
3129 version = NULL;
3130 dns_db_attach(client->view->cachedb, dbp);
3131 result = dns_db_findext(*dbp, name, version, type, 0,
3132 client->now, &node, found, &cm, &ci,
3133 *rdatasetp, NULL);
3134 }
3135 rpz_clean(NULL, dbp, &node, NULL);
3136 if (result == DNS_R_DELEGATION) {
3137 rpz_clean(NULL, NULL, NULL, rdatasetp);
3138 /*
3139 * Recurse for NS rrset or A or AAAA rrset for an NS.
3140 * Do not recurse for addresses for the query name.
3141 */
3142 if (rpz_type == DNS_RPZ_TYPE_IP) {
3143 result = DNS_R_NXRRSET;
3144 } else if (!client->view->rpzs->p.nsip_wait_recurse ||
3145 (!client->view->rpzs->p.nsdname_wait_recurse &&
3146 rpz_type == DNS_RPZ_TYPE_NSDNAME))
3147 {
3148 query_rpzfetch(client, name, type);
3149 result = DNS_R_NXRRSET;
3150 } else {
3151 dns_name_copy(name, st->r_name);
3152 result = ns_query_recurse(client, type, st->r_name,
3153 NULL, NULL, resuming);
3154 if (result == ISC_R_SUCCESS) {
3155 st->state |= DNS_RPZ_RECURSING;
3156 result = DNS_R_DELEGATION;
3157 }
3158 }
3159 }
3160 return result;
3161 }
3162
3163 /*
3164 * Compute a policy owner name, p_name, in a policy zone given the needed
3165 * policy type and the trigger name.
3166 */
3167 static isc_result_t
3168 rpz_get_p_name(ns_client_t *client, dns_name_t *p_name, dns_rpz_zone_t *rpz,
3169 dns_rpz_type_t rpz_type, dns_name_t *trig_name) {
3170 dns_offsets_t prefix_offsets;
3171 dns_name_t prefix, *suffix;
3172 unsigned int first, labels;
3173 isc_result_t result;
3174
3175 CTRACE(ISC_LOG_DEBUG(3), "rpz_get_p_name");
3176
3177 /*
3178 * The policy owner name consists of a suffix depending on the type
3179 * and policy zone and a prefix that is the longest possible string
3180 * from the trigger name that keesp the resulting policy owner name
3181 * from being too long.
3182 */
3183 switch (rpz_type) {
3184 case DNS_RPZ_TYPE_CLIENT_IP:
3185 suffix = &rpz->client_ip;
3186 break;
3187 case DNS_RPZ_TYPE_QNAME:
3188 suffix = &rpz->origin;
3189 break;
3190 case DNS_RPZ_TYPE_IP:
3191 suffix = &rpz->ip;
3192 break;
3193 case DNS_RPZ_TYPE_NSDNAME:
3194 suffix = &rpz->nsdname;
3195 break;
3196 case DNS_RPZ_TYPE_NSIP:
3197 suffix = &rpz->nsip;
3198 break;
3199 default:
3200 UNREACHABLE();
3201 }
3202
3203 /*
3204 * Start with relative version of the full trigger name,
3205 * and trim enough allow the addition of the suffix.
3206 */
3207 dns_name_init(&prefix, prefix_offsets);
3208 labels = dns_name_countlabels(trig_name);
3209 first = 0;
3210 for (;;) {
3211 dns_name_getlabelsequence(trig_name, first, labels - first - 1,
3212 &prefix);
3213 result = dns_name_concatenate(&prefix, suffix, p_name, NULL);
3214 if (result == ISC_R_SUCCESS) {
3215 break;
3216 }
3217 INSIST(result == DNS_R_NAMETOOLONG);
3218 /*
3219 * Trim the trigger name until the combination is not too long.
3220 */
3221 if (labels - first < 2) {
3222 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, suffix,
3223 rpz_type, "concatenate()", result);
3224 return ISC_R_FAILURE;
3225 }
3226 /*
3227 * Complain once about trimming the trigger name.
3228 */
3229 if (first == 0) {
3230 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, suffix,
3231 rpz_type, "concatenate()", result);
3232 }
3233 ++first;
3234 }
3235 return ISC_R_SUCCESS;
3236 }
3237
3238 /*
3239 * Look in policy zone rpz for a policy of rpz_type by p_name.
3240 * The self-name (usually the client qname or an NS name) is compared with
3241 * the target of a CNAME policy for the old style passthru encoding.
3242 * If found, the policy is recorded in *zonep, *dbp, *versionp, *nodep,
3243 * *rdatasetp, and *policyp.
3244 * The target DNS type, qtype, chooses the best rdataset for *rdatasetp.
3245 * The caller must decide if the found policy is most suitable, including
3246 * better than a previously found policy.
3247 * If it is best, the caller records it in client->query.rpz_st->m.
3248 */
3249 static isc_result_t
3250 rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
3251 dns_name_t *p_name, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
3252 dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp,
3253 dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
3254 dns_rpz_policy_t *policyp) {
3255 dns_fixedname_t foundf;
3256 dns_name_t *found;
3257 isc_result_t result;
3258 dns_clientinfomethods_t cm;
3259 dns_clientinfo_t ci;
3260 bool found_a = false;
3261
3262 REQUIRE(nodep != NULL);
3263
3264 CTRACE(ISC_LOG_DEBUG(3), "rpz_find_p");
3265
3266 dns_clientinfomethods_init(&cm, ns_client_sourceip);
3267 dns_clientinfo_init(&ci, client, NULL);
3268
3269 /*
3270 * Try to find either a CNAME or the type of record demanded by the
3271 * request from the policy zone.
3272 */
3273 rpz_clean(zonep, dbp, nodep, rdatasetp);
3274 result = rpz_ready(client, rdatasetp);
3275 if (result != ISC_R_SUCCESS) {
3276 CTRACE(ISC_LOG_ERROR, "rpz_ready() failed");
3277 return DNS_R_SERVFAIL;
3278 }
3279 *versionp = NULL;
3280 result = rpz_getdb(client, p_name, rpz_type, zonep, dbp, versionp);
3281 if (result != ISC_R_SUCCESS) {
3282 return DNS_R_NXDOMAIN;
3283 }
3284 found = dns_fixedname_initname(&foundf);
3285
3286 result = dns_db_findext(*dbp, p_name, *versionp, dns_rdatatype_any, 0,
3287 client->now, nodep, found, &cm, &ci, *rdatasetp,
3288 NULL);
3289 /*
3290 * Choose the best rdataset if we found something.
3291 */
3292 if (result == ISC_R_SUCCESS) {
3293 dns_rdatasetiter_t *rdsiter;
3294
3295 rdsiter = NULL;
3296 result = dns_db_allrdatasets(*dbp, *nodep, *versionp, 0, 0,
3297 &rdsiter);
3298 if (result != ISC_R_SUCCESS) {
3299 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name,
3300 rpz_type, "allrdatasets()", result);
3301 CTRACE(ISC_LOG_ERROR,
3302 "rpz_find_p: allrdatasets failed");
3303 return DNS_R_SERVFAIL;
3304 }
3305 if (qtype == dns_rdatatype_aaaa &&
3306 !ISC_LIST_EMPTY(client->view->dns64))
3307 {
3308 for (result = dns_rdatasetiter_first(rdsiter);
3309 result == ISC_R_SUCCESS;
3310 result = dns_rdatasetiter_next(rdsiter))
3311 {
3312 dns_rdatasetiter_current(rdsiter, *rdatasetp);
3313 if ((*rdatasetp)->type == dns_rdatatype_a) {
3314 found_a = true;
3315 }
3316 dns_rdataset_disassociate(*rdatasetp);
3317 }
3318 }
3319 for (result = dns_rdatasetiter_first(rdsiter);
3320 result == ISC_R_SUCCESS;
3321 result = dns_rdatasetiter_next(rdsiter))
3322 {
3323 dns_rdatasetiter_current(rdsiter, *rdatasetp);
3324 if ((*rdatasetp)->type == dns_rdatatype_cname ||
3325 (*rdatasetp)->type == qtype)
3326 {
3327 break;
3328 }
3329 dns_rdataset_disassociate(*rdatasetp);
3330 }
3331 dns_rdatasetiter_destroy(&rdsiter);
3332 if (result != ISC_R_SUCCESS) {
3333 if (result != ISC_R_NOMORE) {
3334 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
3335 p_name, rpz_type, "rdatasetiter",
3336 result);
3337 CTRACE(ISC_LOG_ERROR, "rpz_find_p: "
3338 "rdatasetiter failed");
3339 return DNS_R_SERVFAIL;
3340 }
3341 /*
3342 * Ask again to get the right DNS_R_DNAME/NXRRSET/...
3343 * result if there is neither a CNAME nor target type.
3344 */
3345 if (dns_rdataset_isassociated(*rdatasetp)) {
3346 dns_rdataset_disassociate(*rdatasetp);
3347 }
3348 dns_db_detachnode(*dbp, nodep);
3349
3350 if (qtype == dns_rdatatype_rrsig ||
3351 qtype == dns_rdatatype_sig)
3352 {
3353 result = DNS_R_NXRRSET;
3354 } else {
3355 result = dns_db_findext(*dbp, p_name, *versionp,
3356 qtype, 0, client->now,
3357 nodep, found, &cm, &ci,
3358 *rdatasetp, NULL);
3359 }
3360 }
3361 }
3362 switch (result) {
3363 case ISC_R_SUCCESS:
3364 if ((*rdatasetp)->type != dns_rdatatype_cname) {
3365 *policyp = DNS_RPZ_POLICY_RECORD;
3366 } else {
3367 *policyp = dns_rpz_decode_cname(rpz, *rdatasetp,
3368 self_name);
3369 if ((*policyp == DNS_RPZ_POLICY_RECORD ||
3370 *policyp == DNS_RPZ_POLICY_WILDCNAME) &&
3371 qtype != dns_rdatatype_cname &&
3372 qtype != dns_rdatatype_any)
3373 {
3374 return DNS_R_CNAME;
3375 }
3376 }
3377 return ISC_R_SUCCESS;
3378 case DNS_R_NXRRSET:
3379 if (found_a) {
3380 *policyp = DNS_RPZ_POLICY_DNS64;
3381 } else {
3382 *policyp = DNS_RPZ_POLICY_NODATA;
3383 }
3384 return result;
3385 case DNS_R_DNAME:
3386 /*
3387 * DNAME policy RRs have very few if any uses that are not
3388 * better served with simple wildcards. Making them work would
3389 * require complications to get the number of labels matched
3390 * in the name or the found name to the main DNS_R_DNAME case
3391 * in query_dname(). The domain also does not appear in the
3392 * summary database at the right level, so this happens only
3393 * with a single policy zone when we have no summary database.
3394 * Treat it as a miss.
3395 */
3396 case DNS_R_NXDOMAIN:
3397 case DNS_R_EMPTYNAME:
3398 return DNS_R_NXDOMAIN;
3399 default:
3400 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type, "",
3401 result);
3402 CTRACE(ISC_LOG_ERROR, "rpz_find_p: unexpected result");
3403 return DNS_R_SERVFAIL;
3404 }
3405 }
3406
3407 static void
3408 rpz_save_p(dns_rpz_st_t *st, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
3409 dns_rpz_policy_t policy, dns_name_t *p_name, dns_rpz_prefix_t prefix,
3410 isc_result_t result, dns_zone_t **zonep, dns_db_t **dbp,
3411 dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
3412 dns_dbversion_t *version) {
3413 dns_rdataset_t *trdataset = NULL;
3414
3415 rpz_match_clear(st);
3416 st->m.rpz = rpz;
3417 st->m.type = rpz_type;
3418 st->m.policy = policy;
3419 dns_name_copy(p_name, st->p_name);
3420 st->m.prefix = prefix;
3421 st->m.result = result;
3422 SAVE(st->m.zone, *zonep);
3423 SAVE(st->m.db, *dbp);
3424 SAVE(st->m.node, *nodep);
3425 if (*rdatasetp != NULL && dns_rdataset_isassociated(*rdatasetp)) {
3426 /*
3427 * Save the replacement rdataset from the policy
3428 * and make the previous replacement rdataset scratch.
3429 */
3430 SAVE(trdataset, st->m.rdataset);
3431 SAVE(st->m.rdataset, *rdatasetp);
3432 SAVE(*rdatasetp, trdataset);
3433 st->m.ttl = ISC_MIN(st->m.rdataset->ttl, rpz->max_policy_ttl);
3434 } else {
3435 st->m.ttl = ISC_MIN(DNS_RPZ_TTL_DEFAULT, rpz->max_policy_ttl);
3436 }
3437 SAVE(st->m.version, version);
3438 }
3439
3440 #ifdef USE_DNSRPS
3441 /*
3442 * Check the results of a RPZ service interface lookup.
3443 * Stop after an error (<0) or not a hit on a disabled zone (0).
3444 * Continue after a hit on a disabled zone (>0).
3445 */
3446 static int
3447 dnsrps_ck(librpz_emsg_t *emsg, ns_client_t *client, dns_rpsdb_t *rpsdb,
3448 bool recursed) {
3449 isc_region_t region;
3450 librpz_domain_buf_t pname_buf;
3451
3452 CTRACE(ISC_LOG_DEBUG(3), "dnsrps_ck");
3453
3454 if (!librpz->rsp_result(emsg, &rpsdb->result, recursed, rpsdb->rsp)) {
3455 return -1;
3456 }
3457
3458 /*
3459 * Forget the state from before the IP address or domain check
3460 * if the lookup hit nothing.
3461 */
3462 if (rpsdb->result.policy == LIBRPZ_POLICY_UNDEFINED ||
3463 rpsdb->result.hit_id != rpsdb->hit_id ||
3464 rpsdb->result.policy != LIBRPZ_POLICY_DISABLED)
3465 {
3466 if (!librpz->rsp_pop_discard(emsg, rpsdb->rsp)) {
3467 return -1;
3468 }
3469 return 0;
3470 }
3471
3472 /*
3473 * Log a hit on a disabled zone.
3474 * Forget the zone to not try it again, and restore the pre-hit state.
3475 */
3476 if (!librpz->rsp_domain(emsg, &pname_buf, rpsdb->rsp)) {
3477 return -1;
3478 }
3479 region.base = pname_buf.d;
3480 region.length = pname_buf.size;
3481 dns_name_fromregion(client->query.rpz_st->p_name, ®ion);
3482 rpz_log_rewrite(client, true, dns_dnsrps_2policy(rpsdb->result.zpolicy),
3483 dns_dnsrps_trig2type(rpsdb->result.trig), NULL,
3484 client->query.rpz_st->p_name, NULL,
3485 rpsdb->result.cznum);
3486
3487 if (!librpz->rsp_forget_zone(emsg, rpsdb->result.cznum, rpsdb->rsp) ||
3488 !librpz->rsp_pop(emsg, &rpsdb->result, rpsdb->rsp))
3489 {
3490 return -1;
3491 }
3492 return 1;
3493 }
3494
3495 /*
3496 * Ready the shim database and rdataset for a DNSRPS hit.
3497 */
3498 static bool
3499 dnsrps_set_p(librpz_emsg_t *emsg, ns_client_t *client, dns_rpz_st_t *st,
3500 dns_rdatatype_t qtype, dns_rdataset_t **p_rdatasetp,
3501 bool recursed) {
3502 dns_rpsdb_t *rpsdb = NULL;
3503 librpz_domain_buf_t pname_buf;
3504 isc_region_t region;
3505 dns_zone_t *p_zone = NULL;
3506 dns_db_t *p_db = NULL;
3507 dns_dbnode_t *p_node = NULL;
3508 dns_rpz_policy_t policy;
3509 dns_rdatatype_t foundtype, searchtype;
3510 isc_result_t result;
3511
3512 CTRACE(ISC_LOG_DEBUG(3), "dnsrps_set_p");
3513
3514 rpsdb = (dns_rpsdb_t *)st->rpsdb;
3515
3516 if (!librpz->rsp_result(emsg, &rpsdb->result, recursed, rpsdb->rsp)) {
3517 return false;
3518 }
3519
3520 if (rpsdb->result.policy == LIBRPZ_POLICY_UNDEFINED) {
3521 return true;
3522 }
3523
3524 /*
3525 * Give the fake or shim DNSRPS database its new origin.
3526 */
3527 if (!librpz->rsp_soa(emsg, NULL, NULL, &rpsdb->origin_buf,
3528 &rpsdb->result, rpsdb->rsp))
3529 {
3530 return false;
3531 }
3532 region.base = rpsdb->origin_buf.d;
3533 region.length = rpsdb->origin_buf.size;
3534 dns_name_fromregion(&rpsdb->common.origin, ®ion);
3535
3536 if (!librpz->rsp_domain(emsg, &pname_buf, rpsdb->rsp)) {
3537 return false;
3538 }
3539 region.base = pname_buf.d;
3540 region.length = pname_buf.size;
3541 dns_name_fromregion(st->p_name, ®ion);
3542
3543 result = rpz_ready(client, p_rdatasetp);
3544 if (result != ISC_R_SUCCESS) {
3545 return false;
3546 }
3547 dns_db_attach(st->rpsdb, &p_db);
3548 policy = dns_dnsrps_2policy(rpsdb->result.policy);
3549 if (policy != DNS_RPZ_POLICY_RECORD) {
3550 result = ISC_R_SUCCESS;
3551 } else if (qtype == dns_rdatatype_rrsig) {
3552 /*
3553 * dns_find_db() refuses to look for and fail to
3554 * find dns_rdatatype_rrsig.
3555 */
3556 result = DNS_R_NXRRSET;
3557 policy = DNS_RPZ_POLICY_NODATA;
3558 } else {
3559 dns_fixedname_t foundf;
3560 dns_name_t *found = NULL;
3561
3562 /*
3563 * Get the next (and so first) RR from the policy node.
3564 * If it is a CNAME, then look for it regardless of the
3565 * query type.
3566 */
3567 if (!librpz->rsp_rr(emsg, &foundtype, NULL, NULL, NULL,
3568 &rpsdb->result, rpsdb->qname->ndata,
3569 rpsdb->qname->length, rpsdb->rsp))
3570 {
3571 return false;
3572 }
3573
3574 if (foundtype == dns_rdatatype_cname) {
3575 searchtype = dns_rdatatype_cname;
3576 } else {
3577 searchtype = qtype;
3578 }
3579 /*
3580 * Get the DNSPRS imitation rdataset.
3581 */
3582 found = dns_fixedname_initname(&foundf);
3583 result = dns_db_find(p_db, st->p_name, NULL, searchtype, 0, 0,
3584 &p_node, found, *p_rdatasetp, NULL);
3585
3586 if (result == ISC_R_SUCCESS) {
3587 if (searchtype == dns_rdatatype_cname &&
3588 qtype != dns_rdatatype_cname)
3589 {
3590 result = DNS_R_CNAME;
3591 }
3592 } else if (result == DNS_R_NXRRSET) {
3593 policy = DNS_RPZ_POLICY_NODATA;
3594 } else {
3595 snprintf(emsg->c, sizeof(emsg->c), "dns_db_find(): %s",
3596 isc_result_totext(result));
3597 return false;
3598 }
3599 }
3600
3601 rpz_save_p(st, client->view->rpzs->zones[rpsdb->result.cznum],
3602 dns_dnsrps_trig2type(rpsdb->result.trig), policy, st->p_name,
3603 0, result, &p_zone, &p_db, &p_node, p_rdatasetp, NULL);
3604
3605 rpz_clean(NULL, NULL, NULL, p_rdatasetp);
3606
3607 return true;
3608 }
3609
3610 static isc_result_t
3611 dnsrps_rewrite_ip(ns_client_t *client, const isc_netaddr_t *netaddr,
3612 dns_rpz_type_t rpz_type, dns_rdataset_t **p_rdatasetp) {
3613 dns_rpz_st_t *st;
3614 dns_rpsdb_t *rpsdb;
3615 librpz_trig_t trig = LIBRPZ_TRIG_CLIENT_IP;
3616 bool recursed = false;
3617 int res;
3618 librpz_emsg_t emsg;
3619 isc_result_t result;
3620
3621 CTRACE(ISC_LOG_DEBUG(3), "dnsrps_rewrite_ip");
3622
3623 st = client->query.rpz_st;
3624 rpsdb = (dns_rpsdb_t *)st->rpsdb;
3625
3626 result = rpz_ready(client, p_rdatasetp);
3627 if (result != ISC_R_SUCCESS) {
3628 st->m.policy = DNS_RPZ_POLICY_ERROR;
3629 return result;
3630 }
3631
3632 switch (rpz_type) {
3633 case DNS_RPZ_TYPE_CLIENT_IP:
3634 trig = LIBRPZ_TRIG_CLIENT_IP;
3635 recursed = false;
3636 break;
3637 case DNS_RPZ_TYPE_IP:
3638 trig = LIBRPZ_TRIG_IP;
3639 recursed = true;
3640 break;
3641 case DNS_RPZ_TYPE_NSIP:
3642 trig = LIBRPZ_TRIG_NSIP;
3643 recursed = true;
3644 break;
3645 default:
3646 UNREACHABLE();
3647 }
3648
3649 do {
3650 if (!librpz->rsp_push(&emsg, rpsdb->rsp) ||
3651 !librpz->ck_ip(&emsg,
3652 netaddr->family == AF_INET
3653 ? (const void *)&netaddr->type.in
3654 : (const void *)&netaddr->type.in6,
3655 netaddr->family, trig, ++rpsdb->hit_id,
3656 recursed, rpsdb->rsp) ||
3657 (res = dnsrps_ck(&emsg, client, rpsdb, recursed)) < 0)
3658 {
3659 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
3660 rpz_type, emsg.c, DNS_R_SERVFAIL);
3661 st->m.policy = DNS_RPZ_POLICY_ERROR;
3662 return DNS_R_SERVFAIL;
3663 }
3664 } while (res != 0);
3665 return ISC_R_SUCCESS;
3666 }
3667
3668 static isc_result_t
3669 dnsrps_rewrite_name(ns_client_t *client, dns_name_t *trig_name, bool recursed,
3670 dns_rpz_type_t rpz_type, dns_rdataset_t **p_rdatasetp) {
3671 dns_rpz_st_t *st;
3672 dns_rpsdb_t *rpsdb;
3673 librpz_trig_t trig = LIBRPZ_TRIG_CLIENT_IP;
3674 isc_region_t r;
3675 int res;
3676 librpz_emsg_t emsg;
3677 isc_result_t result;
3678
3679 CTRACE(ISC_LOG_DEBUG(3), "dnsrps_rewrite_name");
3680
3681 st = client->query.rpz_st;
3682 rpsdb = (dns_rpsdb_t *)st->rpsdb;
3683
3684 result = rpz_ready(client, p_rdatasetp);
3685 if (result != ISC_R_SUCCESS) {
3686 st->m.policy = DNS_RPZ_POLICY_ERROR;
3687 return result;
3688 }
3689
3690 switch (rpz_type) {
3691 case DNS_RPZ_TYPE_QNAME:
3692 trig = LIBRPZ_TRIG_QNAME;
3693 break;
3694 case DNS_RPZ_TYPE_NSDNAME:
3695 trig = LIBRPZ_TRIG_NSDNAME;
3696 break;
3697 default:
3698 UNREACHABLE();
3699 }
3700
3701 dns_name_toregion(trig_name, &r);
3702 do {
3703 if (!librpz->rsp_push(&emsg, rpsdb->rsp) ||
3704 !librpz->ck_domain(&emsg, r.base, r.length, trig,
3705 ++rpsdb->hit_id, recursed, rpsdb->rsp) ||
3706 (res = dnsrps_ck(&emsg, client, rpsdb, recursed)) < 0)
3707 {
3708 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
3709 rpz_type, emsg.c, DNS_R_SERVFAIL);
3710 st->m.policy = DNS_RPZ_POLICY_ERROR;
3711 return DNS_R_SERVFAIL;
3712 }
3713 } while (res != 0);
3714 return ISC_R_SUCCESS;
3715 }
3716 #endif /* USE_DNSRPS */
3717
3718 /*
3719 * Check this address in every eligible policy zone.
3720 */
3721 static isc_result_t
3722 rpz_rewrite_ip(ns_client_t *client, const isc_netaddr_t *netaddr,
3723 dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
3724 dns_rpz_zbits_t zbits, dns_rdataset_t **p_rdatasetp) {
3725 dns_rpz_zones_t *rpzs;
3726 dns_rpz_st_t *st;
3727 dns_rpz_zone_t *rpz;
3728 dns_rpz_prefix_t prefix;
3729 dns_rpz_num_t rpz_num;
3730 dns_fixedname_t ip_namef, p_namef;
3731 dns_name_t *ip_name, *p_name;
3732 dns_zone_t *p_zone;
3733 dns_db_t *p_db;
3734 dns_dbversion_t *p_version;
3735 dns_dbnode_t *p_node;
3736 dns_rpz_policy_t policy;
3737 isc_result_t result;
3738
3739 CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip");
3740
3741 rpzs = client->view->rpzs;
3742 st = client->query.rpz_st;
3743 #ifdef USE_DNSRPS
3744 if (st->popt.dnsrps_enabled) {
3745 return dnsrps_rewrite_ip(client, netaddr, rpz_type,
3746 p_rdatasetp);
3747 }
3748 #endif /* ifdef USE_DNSRPS */
3749
3750 ip_name = dns_fixedname_initname(&ip_namef);
3751
3752 p_zone = NULL;
3753 p_db = NULL;
3754 p_node = NULL;
3755
3756 while (zbits != 0) {
3757 rpz_num = dns_rpz_find_ip(rpzs, rpz_type, zbits, netaddr,
3758 ip_name, &prefix);
3759 if (rpz_num == DNS_RPZ_INVALID_NUM) {
3760 break;
3761 }
3762 zbits &= (DNS_RPZ_ZMASK(rpz_num) >> 1);
3763
3764 /*
3765 * Do not try applying policy zones that cannot replace a
3766 * previously found policy zone.
3767 * Stop looking if the next best choice cannot
3768 * replace what we already have.
3769 */
3770 rpz = rpzs->zones[rpz_num];
3771 if (st->m.policy != DNS_RPZ_POLICY_MISS) {
3772 if (st->m.rpz->num < rpz->num) {
3773 break;
3774 }
3775 if (st->m.rpz->num == rpz->num &&
3776 (st->m.type < rpz_type || st->m.prefix > prefix))
3777 {
3778 break;
3779 }
3780 }
3781
3782 /*
3783 * Get the policy for a prefix at least as long
3784 * as the prefix of the entry we had before.
3785 */
3786 p_name = dns_fixedname_initname(&p_namef);
3787 result = rpz_get_p_name(client, p_name, rpz, rpz_type, ip_name);
3788 if (result != ISC_R_SUCCESS) {
3789 continue;
3790 }
3791 result = rpz_find_p(client, ip_name, qtype, p_name, rpz,
3792 rpz_type, &p_zone, &p_db, &p_version,
3793 &p_node, p_rdatasetp, &policy);
3794 switch (result) {
3795 case DNS_R_NXDOMAIN:
3796 /*
3797 * Continue after a policy record that is missing
3798 * contrary to the summary data. The summary
3799 * data can out of date during races with and among
3800 * policy zone updates.
3801 */
3802 CTRACE(ISC_LOG_ERROR, "rpz_rewrite_ip: mismatched "
3803 "summary data; "
3804 "continuing");
3805 continue;
3806 case DNS_R_SERVFAIL:
3807 rpz_clean(&p_zone, &p_db, &p_node, p_rdatasetp);
3808 st->m.policy = DNS_RPZ_POLICY_ERROR;
3809 return DNS_R_SERVFAIL;
3810 default:
3811 /*
3812 * Forget this policy if it is not preferable
3813 * to the previously found policy.
3814 * If this policy is not good, then stop looking
3815 * because none of the later policy zones would work.
3816 *
3817 * With more than one applicable policy, prefer
3818 * the earliest configured policy,
3819 * client-IP over QNAME over IP over NSDNAME over NSIP,
3820 * the longest prefix
3821 * the lexically smallest address.
3822 * dns_rpz_find_ip() ensures st->m.rpz->num >= rpz->num.
3823 * We can compare new and current p_name because
3824 * both are of the same type and in the same zone.
3825 * The tests above eliminate other reasons to
3826 * reject this policy. If this policy can't work,
3827 * then neither can later zones.
3828 */
3829 if (st->m.policy != DNS_RPZ_POLICY_MISS &&
3830 rpz->num == st->m.rpz->num &&
3831 (st->m.type == rpz_type && st->m.prefix == prefix &&
3832 0 > dns_name_rdatacompare(st->p_name, p_name)))
3833 {
3834 break;
3835 }
3836
3837 /*
3838 * Stop checking after saving an enabled hit in this
3839 * policy zone. The radix tree in the policy zone
3840 * ensures that we found the longest match.
3841 */
3842 if (rpz->policy != DNS_RPZ_POLICY_DISABLED) {
3843 CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip: "
3844 "rpz_save_p");
3845 rpz_save_p(st, rpz, rpz_type, policy, p_name,
3846 prefix, result, &p_zone, &p_db,
3847 &p_node, p_rdatasetp, p_version);
3848 break;
3849 }
3850
3851 /*
3852 * Log DNS_RPZ_POLICY_DISABLED zones
3853 * and try the next eligible policy zone.
3854 */
3855 rpz_log_rewrite(client, true, policy, rpz_type, p_zone,
3856 p_name, NULL, rpz_num);
3857 }
3858 }
3859
3860 rpz_clean(&p_zone, &p_db, &p_node, p_rdatasetp);
3861 return ISC_R_SUCCESS;
3862 }
3863
3864 /*
3865 * Check the IP addresses in the A or AAAA rrsets for name against
3866 * all eligible rpz_type (IP or NSIP) response policy rewrite rules.
3867 */
3868 static isc_result_t
3869 rpz_rewrite_ip_rrset(ns_client_t *client, dns_name_t *name,
3870 dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
3871 dns_rdatatype_t ip_type, dns_db_t **ip_dbp,
3872 dns_dbversion_t *ip_version, dns_rdataset_t **ip_rdatasetp,
3873 dns_rdataset_t **p_rdatasetp, bool resuming) {
3874 dns_rpz_zbits_t zbits;
3875 isc_netaddr_t netaddr;
3876 struct in_addr ina;
3877 struct in6_addr in6a;
3878 isc_result_t result;
3879 unsigned int options = client->query.dboptions | DNS_DBFIND_GLUEOK;
3880 bool done = false;
3881
3882 CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip_rrset");
3883
3884 do {
3885 zbits = rpz_get_zbits(client, ip_type, rpz_type);
3886 if (zbits == 0) {
3887 return ISC_R_SUCCESS;
3888 }
3889
3890 /*
3891 * Get the A or AAAA rdataset.
3892 */
3893 result = rpz_rrset_find(client, name, ip_type, options,
3894 rpz_type, ip_dbp, ip_version,
3895 ip_rdatasetp, resuming);
3896 switch (result) {
3897 case ISC_R_SUCCESS:
3898 case DNS_R_GLUE:
3899 case DNS_R_ZONECUT:
3900 break;
3901 case DNS_R_EMPTYNAME:
3902 case DNS_R_EMPTYWILD:
3903 case DNS_R_NXDOMAIN:
3904 case DNS_R_NCACHENXDOMAIN:
3905 case DNS_R_NXRRSET:
3906 case DNS_R_NCACHENXRRSET:
3907 case ISC_R_NOTFOUND:
3908 return ISC_R_SUCCESS;
3909 case DNS_R_DELEGATION:
3910 case DNS_R_DUPLICATE:
3911 case DNS_R_DROP:
3912 return result;
3913 case DNS_R_CNAME:
3914 case DNS_R_DNAME:
3915 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, name,
3916 rpz_type, "NS address rewrite rrset",
3917 result);
3918 return ISC_R_SUCCESS;
3919 default:
3920 if (client->query.rpz_st->m.policy !=
3921 DNS_RPZ_POLICY_ERROR)
3922 {
3923 client->query.rpz_st->m.policy =
3924 DNS_RPZ_POLICY_ERROR;
3925 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
3926 rpz_type,
3927 "NS address rewrite rrset",
3928 result);
3929 }
3930 CTRACE(ISC_LOG_ERROR,
3931 "rpz_rewrite_ip_rrset: unexpected "
3932 "result");
3933 return DNS_R_SERVFAIL;
3934 }
3935
3936 /*
3937 * If we are processing glue setup for the next loop
3938 * otherwise we are done.
3939 */
3940 if (result == DNS_R_GLUE) {
3941 options = client->query.dboptions;
3942 } else {
3943 options = client->query.dboptions | DNS_DBFIND_GLUEOK;
3944 done = true;
3945 }
3946
3947 /*
3948 * Check all of the IP addresses in the rdataset.
3949 */
3950 for (result = dns_rdataset_first(*ip_rdatasetp);
3951 result == ISC_R_SUCCESS;
3952 result = dns_rdataset_next(*ip_rdatasetp))
3953 {
3954 dns_rdata_t rdata = DNS_RDATA_INIT;
3955 dns_rdataset_current(*ip_rdatasetp, &rdata);
3956 switch (rdata.type) {
3957 case dns_rdatatype_a:
3958 INSIST(rdata.length == 4);
3959 memmove(&ina.s_addr, rdata.data, 4);
3960 isc_netaddr_fromin(&netaddr, &ina);
3961 break;
3962 case dns_rdatatype_aaaa:
3963 INSIST(rdata.length == 16);
3964 memmove(in6a.s6_addr, rdata.data, 16);
3965 isc_netaddr_fromin6(&netaddr, &in6a);
3966 break;
3967 default:
3968 continue;
3969 }
3970
3971 result = rpz_rewrite_ip(client, &netaddr, qtype,
3972 rpz_type, zbits, p_rdatasetp);
3973 if (result != ISC_R_SUCCESS) {
3974 return result;
3975 }
3976 }
3977 } while (!done &&
3978 client->query.rpz_st->m.policy == DNS_RPZ_POLICY_MISS);
3979
3980 return ISC_R_SUCCESS;
3981 }
3982
3983 /*
3984 * Look for IP addresses in A and AAAA rdatasets
3985 * that trigger all eligible IP or NSIP policy rules.
3986 */
3987 static isc_result_t
3988 rpz_rewrite_ip_rrsets(ns_client_t *client, dns_name_t *name,
3989 dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
3990 dns_rdataset_t **ip_rdatasetp, bool resuming) {
3991 dns_rpz_st_t *st;
3992 dns_dbversion_t *ip_version;
3993 dns_db_t *ip_db;
3994 dns_rdataset_t *p_rdataset;
3995 isc_result_t result;
3996
3997 CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip_rrsets");
3998
3999 st = client->query.rpz_st;
4000 ip_version = NULL;
4001 ip_db = NULL;
4002 p_rdataset = NULL;
4003 if ((st->state & DNS_RPZ_DONE_IPv4) == 0 &&
4004 (qtype == dns_rdatatype_a || qtype == dns_rdatatype_any ||
4005 rpz_type == DNS_RPZ_TYPE_NSIP))
4006 {
4007 /*
4008 * Rewrite based on an IPv4 address that will appear
4009 * in the ANSWER section or if we are checking IP addresses.
4010 */
4011 result = rpz_rewrite_ip_rrset(
4012 client, name, qtype, rpz_type, dns_rdatatype_a, &ip_db,
4013 ip_version, ip_rdatasetp, &p_rdataset, resuming);
4014 if (result == ISC_R_SUCCESS) {
4015 st->state |= DNS_RPZ_DONE_IPv4;
4016 }
4017 } else {
4018 result = ISC_R_SUCCESS;
4019 }
4020 if (result == ISC_R_SUCCESS &&
4021 (qtype == dns_rdatatype_aaaa || qtype == dns_rdatatype_any ||
4022 rpz_type == DNS_RPZ_TYPE_NSIP))
4023 {
4024 /*
4025 * Rewrite based on IPv6 addresses that will appear
4026 * in the ANSWER section or if we are checking IP addresses.
4027 */
4028 result = rpz_rewrite_ip_rrset(client, name, qtype, rpz_type,
4029 dns_rdatatype_aaaa, &ip_db,
4030 ip_version, ip_rdatasetp,
4031 &p_rdataset, resuming);
4032 }
4033 if (ip_db != NULL) {
4034 dns_db_detach(&ip_db);
4035 }
4036 ns_client_putrdataset(client, &p_rdataset);
4037 return result;
4038 }
4039
4040 /*
4041 * Try to rewrite a request for a qtype rdataset based on the trigger name
4042 * trig_name and rpz_type (DNS_RPZ_TYPE_QNAME or DNS_RPZ_TYPE_NSDNAME).
4043 * Record the results including the replacement rdataset if any
4044 * in client->query.rpz_st.
4045 * *rdatasetp is a scratch rdataset.
4046 */
4047 static isc_result_t
4048 rpz_rewrite_name(ns_client_t *client, dns_name_t *trig_name,
4049 dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
4050 dns_rpz_zbits_t allowed_zbits, bool recursed,
4051 dns_rdataset_t **rdatasetp) {
4052 dns_rpz_zones_t *rpzs;
4053 dns_rpz_zone_t *rpz;
4054 dns_rpz_st_t *st;
4055 dns_fixedname_t p_namef;
4056 dns_name_t *p_name;
4057 dns_rpz_zbits_t zbits;
4058 dns_rpz_num_t rpz_num;
4059 dns_zone_t *p_zone;
4060 dns_db_t *p_db;
4061 dns_dbversion_t *p_version;
4062 dns_dbnode_t *p_node;
4063 dns_rpz_policy_t policy;
4064 isc_result_t result;
4065
4066 #ifndef USE_DNSRPS
4067 UNUSED(recursed);
4068 #endif /* ifndef USE_DNSRPS */
4069
4070 CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_name");
4071
4072 rpzs = client->view->rpzs;
4073 st = client->query.rpz_st;
4074
4075 #ifdef USE_DNSRPS
4076 if (st->popt.dnsrps_enabled) {
4077 return dnsrps_rewrite_name(client, trig_name, recursed,
4078 rpz_type, rdatasetp);
4079 }
4080 #endif /* ifdef USE_DNSRPS */
4081
4082 zbits = rpz_get_zbits(client, qtype, rpz_type);
4083 zbits &= allowed_zbits;
4084 if (zbits == 0) {
4085 return ISC_R_SUCCESS;
4086 }
4087
4088 /*
4089 * Use the summary database to find the bit mask of policy zones
4090 * with policies for this trigger name. We do this even if there
4091 * is only one eligible policy zone so that wildcard triggers
4092 * are matched correctly, and not into their parent.
4093 */
4094 zbits = dns_rpz_find_name(rpzs, rpz_type, zbits, trig_name);
4095 if (zbits == 0) {
4096 return ISC_R_SUCCESS;
4097 }
4098
4099 p_name = dns_fixedname_initname(&p_namef);
4100
4101 p_zone = NULL;
4102 p_db = NULL;
4103 p_node = NULL;
4104
4105 /*
4106 * Check the trigger name in every policy zone that the summary data
4107 * says has a hit for the trigger name.
4108 * Most of the time there are no eligible zones and the summary data
4109 * keeps us from getting this far.
4110 * We check the most eligible zone first and so usually check only
4111 * one policy zone.
4112 */
4113 for (rpz_num = 0; zbits != 0; ++rpz_num, zbits >>= 1) {
4114 if ((zbits & 1) == 0) {
4115 continue;
4116 }
4117
4118 /*
4119 * Do not check policy zones that cannot replace a previously
4120 * found policy.
4121 */
4122 rpz = rpzs->zones[rpz_num];
4123 if (st->m.policy != DNS_RPZ_POLICY_MISS) {
4124 if (st->m.rpz->num < rpz->num) {
4125 break;
4126 }
4127 if (st->m.rpz->num == rpz->num && st->m.type < rpz_type)
4128 {
4129 break;
4130 }
4131 }
4132
4133 /*
4134 * Get the next policy zone's record for this trigger name.
4135 */
4136 result = rpz_get_p_name(client, p_name, rpz, rpz_type,
4137 trig_name);
4138 if (result != ISC_R_SUCCESS) {
4139 continue;
4140 }
4141 result = rpz_find_p(client, trig_name, qtype, p_name, rpz,
4142 rpz_type, &p_zone, &p_db, &p_version,
4143 &p_node, rdatasetp, &policy);
4144 switch (result) {
4145 case DNS_R_NXDOMAIN:
4146 /*
4147 * Continue after a missing policy record
4148 * contrary to the summary data. The summary
4149 * data can out of date during races with and among
4150 * policy zone updates.
4151 */
4152 CTRACE(ISC_LOG_ERROR, "rpz_rewrite_name: mismatched "
4153 "summary data; "
4154 "continuing");
4155 continue;
4156 case DNS_R_SERVFAIL:
4157 rpz_clean(&p_zone, &p_db, &p_node, rdatasetp);
4158 st->m.policy = DNS_RPZ_POLICY_ERROR;
4159 return DNS_R_SERVFAIL;
4160 default:
4161 /*
4162 * With more than one applicable policy, prefer
4163 * the earliest configured policy,
4164 * client-IP over QNAME over IP over NSDNAME over NSIP,
4165 * and the smallest name.
4166 * We known st->m.rpz->num >= rpz->num and either
4167 * st->m.rpz->num > rpz->num or st->m.type >= rpz_type
4168 */
4169 if (st->m.policy != DNS_RPZ_POLICY_MISS &&
4170 rpz->num == st->m.rpz->num &&
4171 (st->m.type < rpz_type ||
4172 (st->m.type == rpz_type &&
4173 0 >= dns_name_compare(p_name, st->p_name))))
4174 {
4175 continue;
4176 }
4177
4178 if (rpz->policy != DNS_RPZ_POLICY_DISABLED) {
4179 CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_name: "
4180 "rpz_save_p");
4181 rpz_save_p(st, rpz, rpz_type, policy, p_name, 0,
4182 result, &p_zone, &p_db, &p_node,
4183 rdatasetp, p_version);
4184 /*
4185 * After a hit, higher numbered policy zones
4186 * are irrelevant
4187 */
4188 rpz_clean(&p_zone, &p_db, &p_node, rdatasetp);
4189 return ISC_R_SUCCESS;
4190 }
4191 /*
4192 * Log DNS_RPZ_POLICY_DISABLED zones
4193 * and try the next eligible policy zone.
4194 */
4195 rpz_log_rewrite(client, true, policy, rpz_type, p_zone,
4196 p_name, NULL, rpz_num);
4197 break;
4198 }
4199 }
4200
4201 rpz_clean(&p_zone, &p_db, &p_node, rdatasetp);
4202 return ISC_R_SUCCESS;
4203 }
4204
4205 static void
4206 rpz_rewrite_ns_skip(ns_client_t *client, dns_name_t *nsname,
4207 isc_result_t result, int level, const char *str) {
4208 dns_rpz_st_t *st;
4209
4210 CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ns_skip");
4211
4212 st = client->query.rpz_st;
4213
4214 if (str != NULL) {
4215 rpz_log_fail_helper(client, level, nsname, DNS_RPZ_TYPE_NSIP,
4216 DNS_RPZ_TYPE_NSDNAME, str, result);
4217 }
4218 if (st->r.ns_rdataset != NULL &&
4219 dns_rdataset_isassociated(st->r.ns_rdataset))
4220 {
4221 dns_rdataset_disassociate(st->r.ns_rdataset);
4222 }
4223
4224 st->r.label--;
4225 }
4226
4227 /*
4228 * RPZ query result types
4229 */
4230 typedef enum {
4231 qresult_type_done = 0,
4232 qresult_type_restart = 1,
4233 qresult_type_recurse = 2
4234 } qresult_type_t;
4235
4236 /*
4237 * Look for response policy zone QNAME, NSIP, and NSDNAME rewriting.
4238 */
4239 static isc_result_t
4240 rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult,
4241 bool resuming, dns_rdataset_t *ordataset, dns_rdataset_t *osigset) {
4242 dns_rpz_zones_t *rpzs;
4243 dns_rpz_st_t *st;
4244 dns_rdataset_t *rdataset;
4245 dns_fixedname_t nsnamef;
4246 dns_name_t *nsname;
4247 qresult_type_t qresult_type;
4248 dns_rpz_zbits_t zbits;
4249 isc_result_t result = ISC_R_SUCCESS;
4250 dns_rpz_have_t have;
4251 dns_rpz_popt_t popt;
4252 int rpz_ver;
4253 unsigned int options;
4254 #ifdef USE_DNSRPS
4255 librpz_emsg_t emsg;
4256 #endif /* ifdef USE_DNSRPS */
4257
4258 CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite");
4259
4260 rpzs = client->view->rpzs;
4261 st = client->query.rpz_st;
4262
4263 if (rpzs == NULL) {
4264 return ISC_R_NOTFOUND;
4265 }
4266 if (st != NULL && (st->state & DNS_RPZ_REWRITTEN) != 0) {
4267 return DNS_R_DISALLOWED;
4268 }
4269 if (RECURSING(client)) {
4270 return DNS_R_DISALLOWED;
4271 }
4272
4273 RWLOCK(&rpzs->search_lock, isc_rwlocktype_read);
4274 if ((rpzs->p.num_zones == 0 && !rpzs->p.dnsrps_enabled) ||
4275 (!RECURSIONOK(client) && rpzs->p.no_rd_ok == 0) ||
4276 !rpz_ck_dnssec(client, qresult, ordataset, osigset))
4277 {
4278 RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read);
4279 return DNS_R_DISALLOWED;
4280 }
4281 have = rpzs->have;
4282 popt = rpzs->p;
4283 rpz_ver = rpzs->rpz_ver;
4284 RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read);
4285
4286 #ifndef USE_DNSRPS
4287 INSIST(!popt.dnsrps_enabled);
4288 #endif /* ifndef USE_DNSRPS */
4289
4290 if (st == NULL) {
4291 st = isc_mem_get(client->manager->mctx, sizeof(*st));
4292 st->state = 0;
4293 st->rpsdb = NULL;
4294 }
4295 if (st->state == 0) {
4296 st->state |= DNS_RPZ_ACTIVE;
4297 memset(&st->m, 0, sizeof(st->m));
4298 st->m.type = DNS_RPZ_TYPE_BAD;
4299 st->m.policy = DNS_RPZ_POLICY_MISS;
4300 st->m.ttl = ~0;
4301 memset(&st->r, 0, sizeof(st->r));
4302 memset(&st->q, 0, sizeof(st->q));
4303 st->p_name = dns_fixedname_initname(&st->_p_namef);
4304 st->r_name = dns_fixedname_initname(&st->_r_namef);
4305 st->fname = dns_fixedname_initname(&st->_fnamef);
4306 st->have = have;
4307 st->popt = popt;
4308 st->rpz_ver = rpz_ver;
4309 client->query.rpz_st = st;
4310 #ifdef USE_DNSRPS
4311 if (popt.dnsrps_enabled) {
4312 if (st->rpsdb != NULL) {
4313 dns_db_detach(&st->rpsdb);
4314 }
4315 CTRACE(ISC_LOG_DEBUG(3), "dns_dnsrps_rewrite_init");
4316 result = dns_dnsrps_rewrite_init(
4317 &emsg, st, rpzs, client->query.qname,
4318 client->manager->mctx, RECURSIONOK(client));
4319 if (result != ISC_R_SUCCESS) {
4320 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
4321 DNS_RPZ_TYPE_QNAME, emsg.c,
4322 result);
4323 st->m.policy = DNS_RPZ_POLICY_ERROR;
4324 return ISC_R_SUCCESS;
4325 }
4326 }
4327 #endif /* ifdef USE_DNSRPS */
4328 }
4329
4330 /*
4331 * There is nothing to rewrite if the main query failed.
4332 */
4333 switch (qresult) {
4334 case ISC_R_SUCCESS:
4335 case DNS_R_GLUE:
4336 case DNS_R_ZONECUT:
4337 qresult_type = qresult_type_done;
4338 break;
4339 case DNS_R_EMPTYNAME:
4340 case DNS_R_NXRRSET:
4341 case DNS_R_NXDOMAIN:
4342 case DNS_R_EMPTYWILD:
4343 case DNS_R_NCACHENXDOMAIN:
4344 case DNS_R_NCACHENXRRSET:
4345 case DNS_R_COVERINGNSEC:
4346 case DNS_R_CNAME:
4347 case DNS_R_DNAME:
4348 qresult_type = qresult_type_restart;
4349 break;
4350 case DNS_R_DELEGATION:
4351 case ISC_R_NOTFOUND:
4352 /*
4353 * If recursion is on, do only tentative rewriting.
4354 * If recursion is off, this the normal and only time we
4355 * can rewrite.
4356 */
4357 if (RECURSIONOK(client)) {
4358 qresult_type = qresult_type_recurse;
4359 } else {
4360 qresult_type = qresult_type_restart;
4361 }
4362 break;
4363 case ISC_R_FAILURE:
4364 case ISC_R_TIMEDOUT:
4365 case ISC_R_CANCELED:
4366 case DNS_R_BROKENCHAIN:
4367 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, NULL,
4368 DNS_RPZ_TYPE_QNAME,
4369 "stop on qresult in rpz_rewrite()", qresult);
4370 return ISC_R_SUCCESS;
4371 default:
4372 rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, NULL,
4373 DNS_RPZ_TYPE_QNAME,
4374 "stop on unrecognized qresult in rpz_rewrite()",
4375 qresult);
4376 return ISC_R_SUCCESS;
4377 }
4378
4379 rdataset = NULL;
4380
4381 if ((st->state & (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME)) !=
4382 (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME))
4383 {
4384 isc_netaddr_t netaddr;
4385 dns_rpz_zbits_t allowed;
4386
4387 if (!st->popt.dnsrps_enabled &&
4388 qresult_type == qresult_type_recurse)
4389 {
4390 /*
4391 * This request needs recursion that has not been done.
4392 * Get bits for the policy zones that do not need
4393 * to wait for the results of recursion.
4394 */
4395 allowed = st->have.qname_skip_recurse;
4396 if (allowed == 0) {
4397 return ISC_R_SUCCESS;
4398 }
4399 } else {
4400 allowed = DNS_RPZ_ALL_ZBITS;
4401 }
4402
4403 /*
4404 * Check once for triggers for the client IP address.
4405 */
4406 if ((st->state & DNS_RPZ_DONE_CLIENT_IP) == 0) {
4407 zbits = rpz_get_zbits(client, dns_rdatatype_none,
4408 DNS_RPZ_TYPE_CLIENT_IP);
4409 zbits &= allowed;
4410 if (zbits != 0) {
4411 isc_netaddr_fromsockaddr(&netaddr,
4412 &client->peeraddr);
4413 result = rpz_rewrite_ip(client, &netaddr, qtype,
4414 DNS_RPZ_TYPE_CLIENT_IP,
4415 zbits, &rdataset);
4416 if (result != ISC_R_SUCCESS) {
4417 goto cleanup;
4418 }
4419 }
4420 }
4421
4422 /*
4423 * Check triggers for the query name if this is the first time
4424 * for the current qname.
4425 * There is a first time for each name in a CNAME chain
4426 */
4427 if ((st->state & DNS_RPZ_DONE_QNAME) == 0) {
4428 bool norec = (qresult_type != qresult_type_recurse);
4429 result = rpz_rewrite_name(client, client->query.qname,
4430 qtype, DNS_RPZ_TYPE_QNAME,
4431 allowed, norec, &rdataset);
4432 if (result != ISC_R_SUCCESS) {
4433 goto cleanup;
4434 }
4435
4436 /*
4437 * Check IPv4 addresses in A RRs next.
4438 * Reset to the start of the NS names.
4439 */
4440 st->r.label = dns_name_countlabels(client->query.qname);
4441 st->state &= ~(DNS_RPZ_DONE_QNAME_IP |
4442 DNS_RPZ_DONE_IPv4);
4443 }
4444
4445 /*
4446 * Quit if this was an attempt to find a qname or
4447 * client-IP trigger before recursion.
4448 * We will be back if no pre-recursion triggers hit.
4449 * For example, consider 2 policy zones, both with qname and
4450 * IP address triggers. If the qname misses the 1st zone,
4451 * then we cannot know whether a hit for the qname in the
4452 * 2nd zone matters until after recursing to get the A RRs and
4453 * testing them in the first zone.
4454 * Do not bother saving the work from this attempt,
4455 * because recursion is so slow.
4456 */
4457 if (qresult_type == qresult_type_recurse) {
4458 goto cleanup;
4459 }
4460
4461 /*
4462 * DNS_RPZ_DONE_QNAME but not DNS_RPZ_DONE_CLIENT_IP
4463 * is reset at the end of dealing with each CNAME.
4464 */
4465 st->state |= (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME);
4466 }
4467
4468 /*
4469 * Check known IP addresses for the query name if the database lookup
4470 * resulted in some addresses (qresult_type == qresult_type_done)
4471 * and if we have not already checked them.
4472 * Any recursion required for the query has already happened.
4473 * Do not check addresses that will not be in the ANSWER section.
4474 */
4475 if ((st->state & DNS_RPZ_DONE_QNAME_IP) == 0 &&
4476 qresult_type == qresult_type_done &&
4477 rpz_get_zbits(client, qtype, DNS_RPZ_TYPE_IP) != 0)
4478 {
4479 result = rpz_rewrite_ip_rrsets(client, client->query.qname,
4480 qtype, DNS_RPZ_TYPE_IP,
4481 &rdataset, resuming);
4482 if (result != ISC_R_SUCCESS) {
4483 goto cleanup;
4484 }
4485 /*
4486 * We are finished checking the IP addresses for the qname.
4487 * Start with IPv4 if we will check NS IP addresses.
4488 */
4489 st->state |= DNS_RPZ_DONE_QNAME_IP;
4490 st->state &= ~DNS_RPZ_DONE_IPv4;
4491 }
4492
4493 /*
4494 * Stop looking for rules if there are none of the other kinds
4495 * that could override what we already have.
4496 */
4497 if (rpz_get_zbits(client, dns_rdatatype_any, DNS_RPZ_TYPE_NSDNAME) ==
4498 0 &&
4499 rpz_get_zbits(client, dns_rdatatype_any, DNS_RPZ_TYPE_NSIP) == 0)
4500 {
4501 result = ISC_R_SUCCESS;
4502 goto cleanup;
4503 }
4504
4505 dns_fixedname_init(&nsnamef);
4506 dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef));
4507 options = client->query.dboptions | DNS_DBFIND_GLUEOK;
4508 while (st->r.label > st->popt.min_ns_labels) {
4509 bool was_glue = false;
4510 /*
4511 * Get NS rrset for each domain in the current qname.
4512 */
4513 if (st->r.label == dns_name_countlabels(client->query.qname)) {
4514 nsname = client->query.qname;
4515 } else {
4516 nsname = dns_fixedname_name(&nsnamef);
4517 dns_name_split(client->query.qname, st->r.label, NULL,
4518 nsname);
4519 }
4520 if (st->r.ns_rdataset == NULL ||
4521 !dns_rdataset_isassociated(st->r.ns_rdataset))
4522 {
4523 dns_db_t *db = NULL;
4524 result = rpz_rrset_find(client, nsname,
4525 dns_rdatatype_ns, options,
4526 DNS_RPZ_TYPE_NSDNAME, &db, NULL,
4527 &st->r.ns_rdataset, resuming);
4528 if (db != NULL) {
4529 dns_db_detach(&db);
4530 }
4531 if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
4532 goto cleanup;
4533 }
4534 switch (result) {
4535 case DNS_R_GLUE:
4536 was_glue = true;
4537 FALLTHROUGH;
4538 case ISC_R_SUCCESS:
4539 result = dns_rdataset_first(st->r.ns_rdataset);
4540 if (result != ISC_R_SUCCESS) {
4541 goto cleanup;
4542 }
4543 st->state &= ~(DNS_RPZ_DONE_NSDNAME |
4544 DNS_RPZ_DONE_IPv4);
4545 break;
4546 case DNS_R_DELEGATION:
4547 case DNS_R_DUPLICATE:
4548 case DNS_R_DROP:
4549 goto cleanup;
4550 case DNS_R_EMPTYNAME:
4551 case DNS_R_NXRRSET:
4552 case DNS_R_EMPTYWILD:
4553 case DNS_R_NXDOMAIN:
4554 case DNS_R_NCACHENXDOMAIN:
4555 case DNS_R_NCACHENXRRSET:
4556 case ISC_R_NOTFOUND:
4557 case DNS_R_CNAME:
4558 case DNS_R_DNAME:
4559 rpz_rewrite_ns_skip(client, nsname, result, 0,
4560 NULL);
4561 continue;
4562 case ISC_R_TIMEDOUT:
4563 case DNS_R_BROKENCHAIN:
4564 case ISC_R_FAILURE:
4565 rpz_rewrite_ns_skip(client, nsname, result,
4566 DNS_RPZ_DEBUG_LEVEL3,
4567 " NS rpz_rrset_find()");
4568 continue;
4569 default:
4570 rpz_rewrite_ns_skip(client, nsname, result,
4571 DNS_RPZ_INFO_LEVEL,
4572 " unrecognized NS"
4573 " rpz_rrset_find()");
4574 continue;
4575 }
4576 }
4577
4578 /*
4579 * Check all NS names.
4580 */
4581 do {
4582 dns_rdata_ns_t ns;
4583 dns_rdata_t nsrdata = DNS_RDATA_INIT;
4584
4585 dns_rdataset_current(st->r.ns_rdataset, &nsrdata);
4586 result = dns_rdata_tostruct(&nsrdata, &ns, NULL);
4587 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4588 dns_rdata_reset(&nsrdata);
4589
4590 /*
4591 * Do nothing about "NS ."
4592 */
4593 if (dns_name_equal(&ns.name, dns_rootname)) {
4594 dns_rdata_freestruct(&ns);
4595 result = dns_rdataset_next(st->r.ns_rdataset);
4596 continue;
4597 }
4598 /*
4599 * Check this NS name if we did not handle it
4600 * during a previous recursion.
4601 */
4602 if ((st->state & DNS_RPZ_DONE_NSDNAME) == 0) {
4603 result = rpz_rewrite_name(
4604 client, &ns.name, qtype,
4605 DNS_RPZ_TYPE_NSDNAME, DNS_RPZ_ALL_ZBITS,
4606 true, &rdataset);
4607 if (result != ISC_R_SUCCESS) {
4608 dns_rdata_freestruct(&ns);
4609 goto cleanup;
4610 }
4611 st->state |= DNS_RPZ_DONE_NSDNAME;
4612 }
4613 /*
4614 * Check all IP addresses for this NS name.
4615 */
4616 result = rpz_rewrite_ip_rrsets(client, &ns.name, qtype,
4617 DNS_RPZ_TYPE_NSIP,
4618 &rdataset, resuming);
4619 dns_rdata_freestruct(&ns);
4620 if (result != ISC_R_SUCCESS) {
4621 goto cleanup;
4622 }
4623 st->state &= ~(DNS_RPZ_DONE_NSDNAME |
4624 DNS_RPZ_DONE_IPv4);
4625 result = dns_rdataset_next(st->r.ns_rdataset);
4626 } while (result == ISC_R_SUCCESS);
4627 dns_rdataset_disassociate(st->r.ns_rdataset);
4628
4629 /*
4630 * If we just checked a glue NS RRset retry without allowing
4631 * glue responses, otherwise setup for the next name.
4632 */
4633 if (was_glue) {
4634 options = client->query.dboptions;
4635 } else {
4636 options = client->query.dboptions | DNS_DBFIND_GLUEOK;
4637 st->r.label--;
4638 }
4639
4640 if (rpz_get_zbits(client, dns_rdatatype_any,
4641 DNS_RPZ_TYPE_NSDNAME) == 0 &&
4642 rpz_get_zbits(client, dns_rdatatype_any,
4643 DNS_RPZ_TYPE_NSIP) == 0)
4644 {
4645 break;
4646 }
4647 }
4648
4649 /*
4650 * Use the best hit, if any.
4651 */
4652 result = ISC_R_SUCCESS;
4653
4654 cleanup:
4655 #ifdef USE_DNSRPS
4656 if (st->popt.dnsrps_enabled && st->m.policy != DNS_RPZ_POLICY_ERROR &&
4657 !dnsrps_set_p(&emsg, client, st, qtype, &rdataset,
4658 qresult_type != qresult_type_recurse))
4659 {
4660 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
4661 DNS_RPZ_TYPE_BAD, emsg.c, DNS_R_SERVFAIL);
4662 st->m.policy = DNS_RPZ_POLICY_ERROR;
4663 }
4664 #endif /* ifdef USE_DNSRPS */
4665 if (st->m.policy != DNS_RPZ_POLICY_MISS &&
4666 st->m.policy != DNS_RPZ_POLICY_ERROR &&
4667 st->m.rpz->policy != DNS_RPZ_POLICY_GIVEN)
4668 {
4669 st->m.policy = st->m.rpz->policy;
4670 }
4671 if (st->m.policy == DNS_RPZ_POLICY_MISS ||
4672 st->m.policy == DNS_RPZ_POLICY_PASSTHRU ||
4673 st->m.policy == DNS_RPZ_POLICY_ERROR)
4674 {
4675 if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU &&
4676 result != DNS_R_DELEGATION)
4677 {
4678 rpz_log_rewrite(client, false, st->m.policy, st->m.type,
4679 st->m.zone, st->p_name, NULL,
4680 st->m.rpz->num);
4681 }
4682 rpz_match_clear(st);
4683 }
4684 if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
4685 CTRACE(ISC_LOG_ERROR, "SERVFAIL due to RPZ policy");
4686 st->m.type = DNS_RPZ_TYPE_BAD;
4687 result = DNS_R_SERVFAIL;
4688 }
4689 ns_client_putrdataset(client, &rdataset);
4690 if ((st->state & DNS_RPZ_RECURSING) == 0) {
4691 rpz_clean(NULL, &st->r.db, NULL, &st->r.ns_rdataset);
4692 }
4693
4694 return result;
4695 }
4696
4697 /*
4698 * See if response policy zone rewriting is allowed by a lack of interest
4699 * by the client in DNSSEC or a lack of signatures.
4700 */
4701 static bool
4702 rpz_ck_dnssec(ns_client_t *client, isc_result_t qresult,
4703 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
4704 dns_fixedname_t fixed;
4705 dns_name_t *found;
4706 dns_rdataset_t trdataset;
4707 dns_rdatatype_t type;
4708 isc_result_t result;
4709
4710 CTRACE(ISC_LOG_DEBUG(3), "rpz_ck_dnssec");
4711
4712 if (client->view->rpzs->p.break_dnssec || !WANTDNSSEC(client)) {
4713 return true;
4714 }
4715
4716 /*
4717 * We do not know if there are signatures if we have not recursed
4718 * for them.
4719 */
4720 if (qresult == DNS_R_DELEGATION || qresult == ISC_R_NOTFOUND) {
4721 return false;
4722 }
4723
4724 if (sigrdataset == NULL) {
4725 return true;
4726 }
4727 if (dns_rdataset_isassociated(sigrdataset)) {
4728 return false;
4729 }
4730
4731 /*
4732 * We are happy to rewrite nothing.
4733 */
4734 if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
4735 return true;
4736 }
4737 /*
4738 * Do not rewrite if there is any sign of signatures.
4739 */
4740 if (rdataset->type == dns_rdatatype_nsec ||
4741 rdataset->type == dns_rdatatype_nsec3 ||
4742 rdataset->type == dns_rdatatype_rrsig)
4743 {
4744 return false;
4745 }
4746
4747 /*
4748 * Look for a signature in a negative cache rdataset.
4749 */
4750 if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) == 0) {
4751 return true;
4752 }
4753 found = dns_fixedname_initname(&fixed);
4754 dns_rdataset_init(&trdataset);
4755 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4756 result = dns_rdataset_next(rdataset))
4757 {
4758 dns_ncache_current(rdataset, found, &trdataset);
4759 type = trdataset.type;
4760 dns_rdataset_disassociate(&trdataset);
4761 if (type == dns_rdatatype_nsec || type == dns_rdatatype_nsec3 ||
4762 type == dns_rdatatype_rrsig)
4763 {
4764 return false;
4765 }
4766 }
4767 return true;
4768 }
4769
4770 /*
4771 * Extract a network address from the RDATA of an A or AAAA
4772 * record.
4773 *
4774 * Returns:
4775 * ISC_R_SUCCESS
4776 * ISC_R_NOTIMPLEMENTED The rdata is not a known address type.
4777 */
4778 static isc_result_t
4779 rdata_tonetaddr(const dns_rdata_t *rdata, isc_netaddr_t *netaddr) {
4780 struct in_addr ina;
4781 struct in6_addr in6a;
4782
4783 switch (rdata->type) {
4784 case dns_rdatatype_a:
4785 INSIST(rdata->length == 4);
4786 memmove(&ina.s_addr, rdata->data, 4);
4787 isc_netaddr_fromin(netaddr, &ina);
4788 return ISC_R_SUCCESS;
4789 case dns_rdatatype_aaaa:
4790 INSIST(rdata->length == 16);
4791 memmove(in6a.s6_addr, rdata->data, 16);
4792 isc_netaddr_fromin6(netaddr, &in6a);
4793 return ISC_R_SUCCESS;
4794 default:
4795 return ISC_R_NOTIMPLEMENTED;
4796 }
4797 }
4798
4799 static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
4800 static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
4801 static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
4802
4803 static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
4804
4805 static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
4806 static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
4807 static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
4808 static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
4809 static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
4810 static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
4811 static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
4812 static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
4813 static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
4814 static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
4815 static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
4816 static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
4817 static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
4818 static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
4819 static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
4820 static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
4821
4822 static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
4823
4824 static dns_name_t rfc1918names[] = {
4825 DNS_NAME_INITABSOLUTE(inaddr10, inaddr10_offsets),
4826 DNS_NAME_INITABSOLUTE(inaddr16172, inaddr172_offsets),
4827 DNS_NAME_INITABSOLUTE(inaddr17172, inaddr172_offsets),
4828 DNS_NAME_INITABSOLUTE(inaddr18172, inaddr172_offsets),
4829 DNS_NAME_INITABSOLUTE(inaddr19172, inaddr172_offsets),
4830 DNS_NAME_INITABSOLUTE(inaddr20172, inaddr172_offsets),
4831 DNS_NAME_INITABSOLUTE(inaddr21172, inaddr172_offsets),
4832 DNS_NAME_INITABSOLUTE(inaddr22172, inaddr172_offsets),
4833 DNS_NAME_INITABSOLUTE(inaddr23172, inaddr172_offsets),
4834 DNS_NAME_INITABSOLUTE(inaddr24172, inaddr172_offsets),
4835 DNS_NAME_INITABSOLUTE(inaddr25172, inaddr172_offsets),
4836 DNS_NAME_INITABSOLUTE(inaddr26172, inaddr172_offsets),
4837 DNS_NAME_INITABSOLUTE(inaddr27172, inaddr172_offsets),
4838 DNS_NAME_INITABSOLUTE(inaddr28172, inaddr172_offsets),
4839 DNS_NAME_INITABSOLUTE(inaddr29172, inaddr172_offsets),
4840 DNS_NAME_INITABSOLUTE(inaddr30172, inaddr172_offsets),
4841 DNS_NAME_INITABSOLUTE(inaddr31172, inaddr172_offsets),
4842 DNS_NAME_INITABSOLUTE(inaddr168192, inaddr192_offsets)
4843 };
4844
4845 static unsigned char prisoner_data[] = "\010prisoner\004iana\003org";
4846 static unsigned char hostmaster_data[] = "\012hostmaster\014root-"
4847 "servers\003org";
4848
4849 static unsigned char prisoner_offsets[] = { 0, 9, 14, 18 };
4850 static unsigned char hostmaster_offsets[] = { 0, 11, 24, 28 };
4851
4852 static dns_name_t const prisoner = DNS_NAME_INITABSOLUTE(prisoner_data,
4853 prisoner_offsets);
4854 static dns_name_t const hostmaster = DNS_NAME_INITABSOLUTE(hostmaster_data,
4855 hostmaster_offsets);
4856
4857 static void
4858 warn_rfc1918(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) {
4859 unsigned int i;
4860 dns_rdata_t rdata = DNS_RDATA_INIT;
4861 dns_rdata_soa_t soa;
4862 dns_rdataset_t found;
4863 isc_result_t result;
4864
4865 for (i = 0; i < (sizeof(rfc1918names) / sizeof(*rfc1918names)); i++) {
4866 if (dns_name_issubdomain(fname, &rfc1918names[i])) {
4867 dns_rdataset_init(&found);
4868 result = dns_ncache_getrdataset(
4869 rdataset, &rfc1918names[i], dns_rdatatype_soa,
4870 &found);
4871 if (result != ISC_R_SUCCESS) {
4872 return;
4873 }
4874
4875 result = dns_rdataset_first(&found);
4876 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4877 dns_rdataset_current(&found, &rdata);
4878 result = dns_rdata_tostruct(&rdata, &soa, NULL);
4879 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4880 if (dns_name_equal(&soa.origin, &prisoner) &&
4881 dns_name_equal(&soa.contact, &hostmaster))
4882 {
4883 char buf[DNS_NAME_FORMATSIZE];
4884 dns_name_format(fname, buf, sizeof(buf));
4885 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
4886 NS_LOGMODULE_QUERY,
4887 ISC_LOG_WARNING,
4888 "RFC 1918 response from "
4889 "Internet for %s",
4890 buf);
4891 }
4892 dns_rdataset_disassociate(&found);
4893 return;
4894 }
4895 }
4896 }
4897
4898 static void
4899 query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
4900 dns_dbversion_t *version, ns_client_t *client,
4901 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
4902 dns_name_t *fname, bool exact, dns_name_t *found) {
4903 unsigned char salt[256];
4904 size_t salt_length;
4905 uint16_t iterations;
4906 isc_result_t result;
4907 unsigned int dboptions;
4908 dns_fixedname_t fixed;
4909 dns_hash_t hash;
4910 dns_name_t name;
4911 unsigned int skip = 0, labels;
4912 dns_rdata_nsec3_t nsec3;
4913 dns_rdata_t rdata = DNS_RDATA_INIT;
4914 bool optout;
4915 dns_clientinfomethods_t cm;
4916 dns_clientinfo_t ci;
4917
4918 salt_length = sizeof(salt);
4919 result = dns_db_getnsec3parameters(db, version, &hash, NULL,
4920 &iterations, salt, &salt_length);
4921 if (result != ISC_R_SUCCESS) {
4922 return;
4923 }
4924
4925 dns_name_init(&name, NULL);
4926 dns_name_clone(qname, &name);
4927 labels = dns_name_countlabels(&name);
4928 dns_clientinfomethods_init(&cm, ns_client_sourceip);
4929 dns_clientinfo_init(&ci, client, NULL);
4930
4931 /*
4932 * Map unknown algorithm to known value.
4933 */
4934 if (hash == DNS_NSEC3_UNKNOWNALG) {
4935 hash = 1;
4936 }
4937
4938 again:
4939 dns_fixedname_init(&fixed);
4940 result = dns_nsec3_hashname(&fixed, NULL, NULL, &name,
4941 dns_db_origin(db), hash, iterations, salt,
4942 salt_length);
4943 if (result != ISC_R_SUCCESS) {
4944 return;
4945 }
4946
4947 dboptions = client->query.dboptions | DNS_DBFIND_FORCENSEC3;
4948 result = dns_db_findext(db, dns_fixedname_name(&fixed), version,
4949 dns_rdatatype_nsec3, dboptions, client->now,
4950 NULL, fname, &cm, &ci, rdataset, sigrdataset);
4951
4952 if (result == DNS_R_NXDOMAIN) {
4953 if (!dns_rdataset_isassociated(rdataset)) {
4954 return;
4955 }
4956 result = dns_rdataset_first(rdataset);
4957 INSIST(result == ISC_R_SUCCESS);
4958 dns_rdataset_current(rdataset, &rdata);
4959 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
4960 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4961 dns_rdata_reset(&rdata);
4962 optout = ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0);
4963 if (found != NULL && optout &&
4964 dns_name_issubdomain(&name, dns_db_origin(db)))
4965 {
4966 dns_rdataset_disassociate(rdataset);
4967 if (dns_rdataset_isassociated(sigrdataset)) {
4968 dns_rdataset_disassociate(sigrdataset);
4969 }
4970 skip++;
4971 dns_name_getlabelsequence(qname, skip, labels - skip,
4972 &name);
4973 ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
4974 NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3),
4975 "looking for closest provable encloser");
4976 goto again;
4977 }
4978 if (exact) {
4979 ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
4980 NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
4981 "expected a exact match NSEC3, got "
4982 "a covering record");
4983 }
4984 } else if (result != ISC_R_SUCCESS) {
4985 return;
4986 } else if (!exact) {
4987 ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
4988 NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
4989 "expected covering NSEC3, got an exact match");
4990 }
4991 if (found == qname) {
4992 if (skip != 0U) {
4993 dns_name_getlabelsequence(qname, skip, labels - skip,
4994 found);
4995 }
4996 } else if (found != NULL) {
4997 dns_name_copy(&name, found);
4998 }
4999 return;
5000 }
5001
5002 static uint32_t
5003 dns64_ttl(dns_db_t *db, dns_dbversion_t *version) {
5004 dns_dbnode_t *node = NULL;
5005 dns_rdata_soa_t soa;
5006 dns_rdata_t rdata = DNS_RDATA_INIT;
5007 dns_rdataset_t rdataset;
5008 isc_result_t result;
5009 uint32_t ttl = UINT32_MAX;
5010
5011 dns_rdataset_init(&rdataset);
5012
5013 result = dns_db_getoriginnode(db, &node);
5014 if (result != ISC_R_SUCCESS) {
5015 goto cleanup;
5016 }
5017
5018 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa, 0, 0,
5019 &rdataset, NULL);
5020 if (result != ISC_R_SUCCESS) {
5021 goto cleanup;
5022 }
5023 result = dns_rdataset_first(&rdataset);
5024 if (result != ISC_R_SUCCESS) {
5025 goto cleanup;
5026 }
5027
5028 dns_rdataset_current(&rdataset, &rdata);
5029 result = dns_rdata_tostruct(&rdata, &soa, NULL);
5030 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5031 ttl = ISC_MIN(rdataset.ttl, soa.minimum);
5032
5033 cleanup:
5034 if (dns_rdataset_isassociated(&rdataset)) {
5035 dns_rdataset_disassociate(&rdataset);
5036 }
5037 if (node != NULL) {
5038 dns_db_detachnode(db, &node);
5039 }
5040 return ttl;
5041 }
5042
5043 static bool
5044 dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset,
5045 dns_rdataset_t *sigrdataset) {
5046 isc_netaddr_t netaddr;
5047 dns_aclenv_t *env = client->manager->aclenv;
5048 dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64);
5049 unsigned int flags = 0;
5050 unsigned int i, count;
5051 bool *aaaaok;
5052
5053 INSIST(client->query.dns64_aaaaok == NULL);
5054 INSIST(client->query.dns64_aaaaoklen == 0);
5055 INSIST(client->query.dns64_aaaa == NULL);
5056 INSIST(client->query.dns64_sigaaaa == NULL);
5057
5058 if (dns64 == NULL) {
5059 return true;
5060 }
5061
5062 if (RECURSIONOK(client)) {
5063 flags |= DNS_DNS64_RECURSIVE;
5064 }
5065
5066 if (WANTDNSSEC(client) && sigrdataset != NULL &&
5067 dns_rdataset_isassociated(sigrdataset))
5068 {
5069 flags |= DNS_DNS64_DNSSEC;
5070 }
5071
5072 count = dns_rdataset_count(rdataset);
5073 aaaaok = isc_mem_cget(client->manager->mctx, count, sizeof(bool));
5074
5075 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
5076 if (dns_dns64_aaaaok(dns64, &netaddr, client->signer, env, flags,
5077 rdataset, aaaaok, count))
5078 {
5079 for (i = 0; i < count; i++) {
5080 if (aaaaok != NULL && !aaaaok[i]) {
5081 SAVE(client->query.dns64_aaaaok, aaaaok);
5082 client->query.dns64_aaaaoklen = count;
5083 break;
5084 }
5085 }
5086 if (aaaaok != NULL) {
5087 isc_mem_cput(client->manager->mctx, aaaaok, count,
5088 sizeof(bool));
5089 }
5090 return true;
5091 }
5092 if (aaaaok != NULL) {
5093 isc_mem_cput(client->manager->mctx, aaaaok, count,
5094 sizeof(bool));
5095 }
5096 return false;
5097 }
5098
5099 /*
5100 * Look for the name and type in the redirection zone. If found update
5101 * the arguments as appropriate. Return true if a update was
5102 * performed.
5103 *
5104 * Only perform the update if the client is in the allow query acl and
5105 * returning the update would not cause a DNSSEC validation failure.
5106 */
5107 static isc_result_t
5108 redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
5109 dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp,
5110 dns_rdatatype_t qtype) {
5111 dns_db_t *db = NULL;
5112 dns_dbnode_t *node = NULL;
5113 dns_fixedname_t fixed;
5114 dns_name_t *found;
5115 dns_rdataset_t trdataset;
5116 isc_result_t result;
5117 dns_rdatatype_t type;
5118 dns_clientinfomethods_t cm;
5119 dns_clientinfo_t ci;
5120 ns_dbversion_t *dbversion;
5121
5122 CTRACE(ISC_LOG_DEBUG(3), "redirect");
5123
5124 if (client->view->redirect == NULL) {
5125 return ISC_R_NOTFOUND;
5126 }
5127
5128 found = dns_fixedname_initname(&fixed);
5129 dns_rdataset_init(&trdataset);
5130
5131 dns_clientinfomethods_init(&cm, ns_client_sourceip);
5132 dns_clientinfo_init(&ci, client, NULL);
5133 dns_clientinfo_setecs(&ci, &client->ecs);
5134
5135 if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp))
5136 {
5137 return ISC_R_NOTFOUND;
5138 }
5139
5140 if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) {
5141 if (rdataset->trust == dns_trust_secure) {
5142 return ISC_R_NOTFOUND;
5143 }
5144 if (rdataset->trust == dns_trust_ultimate &&
5145 (rdataset->type == dns_rdatatype_nsec ||
5146 rdataset->type == dns_rdatatype_nsec3))
5147 {
5148 return ISC_R_NOTFOUND;
5149 }
5150 if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
5151 for (result = dns_rdataset_first(rdataset);
5152 result == ISC_R_SUCCESS;
5153 result = dns_rdataset_next(rdataset))
5154 {
5155 dns_ncache_current(rdataset, found, &trdataset);
5156 type = trdataset.type;
5157 dns_rdataset_disassociate(&trdataset);
5158 if (type == dns_rdatatype_nsec ||
5159 type == dns_rdatatype_nsec3 ||
5160 type == dns_rdatatype_rrsig)
5161 {
5162 return ISC_R_NOTFOUND;
5163 }
5164 }
5165 }
5166 }
5167
5168 result = ns_client_checkaclsilent(
5169 client, NULL, dns_zone_getqueryacl(client->view->redirect),
5170 true);
5171 if (result != ISC_R_SUCCESS) {
5172 return ISC_R_NOTFOUND;
5173 }
5174
5175 result = dns_zone_getdb(client->view->redirect, &db);
5176 if (result != ISC_R_SUCCESS) {
5177 return ISC_R_NOTFOUND;
5178 }
5179
5180 dbversion = ns_client_findversion(client, db);
5181 if (dbversion == NULL) {
5182 dns_db_detach(&db);
5183 return ISC_R_NOTFOUND;
5184 }
5185
5186 /*
5187 * Lookup the requested data in the redirect zone.
5188 */
5189 result = dns_db_findext(db, client->query.qname, dbversion->version,
5190 qtype, DNS_DBFIND_NOZONECUT, client->now, &node,
5191 found, &cm, &ci, &trdataset, NULL);
5192 if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
5193 if (dns_rdataset_isassociated(rdataset)) {
5194 dns_rdataset_disassociate(rdataset);
5195 }
5196 if (dns_rdataset_isassociated(&trdataset)) {
5197 dns_rdataset_disassociate(&trdataset);
5198 }
5199 goto nxrrset;
5200 } else if (result != ISC_R_SUCCESS) {
5201 if (dns_rdataset_isassociated(&trdataset)) {
5202 dns_rdataset_disassociate(&trdataset);
5203 }
5204 if (node != NULL) {
5205 dns_db_detachnode(db, &node);
5206 }
5207 dns_db_detach(&db);
5208 return ISC_R_NOTFOUND;
5209 }
5210
5211 CTRACE(ISC_LOG_DEBUG(3), "redirect: found data: done");
5212 dns_name_copy(found, name);
5213 if (dns_rdataset_isassociated(rdataset)) {
5214 dns_rdataset_disassociate(rdataset);
5215 }
5216 if (dns_rdataset_isassociated(&trdataset)) {
5217 dns_rdataset_clone(&trdataset, rdataset);
5218 dns_rdataset_disassociate(&trdataset);
5219 }
5220 nxrrset:
5221 if (*nodep != NULL) {
5222 dns_db_detachnode(*dbp, nodep);
5223 }
5224 dns_db_detach(dbp);
5225 dns_db_attachnode(db, node, nodep);
5226 dns_db_attach(db, dbp);
5227 dns_db_detachnode(db, &node);
5228 dns_db_detach(&db);
5229 *versionp = dbversion->version;
5230
5231 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
5232 NS_QUERYATTR_NOADDITIONAL);
5233
5234 return result;
5235 }
5236
5237 static isc_result_t
5238 redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
5239 dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp,
5240 dns_rdatatype_t qtype, bool *is_zonep) {
5241 dns_db_t *db = NULL;
5242 dns_dbnode_t *node = NULL;
5243 dns_fixedname_t fixed;
5244 dns_fixedname_t fixedredirect;
5245 dns_name_t *found, *redirectname;
5246 dns_rdataset_t trdataset;
5247 isc_result_t result;
5248 dns_rdatatype_t type;
5249 dns_clientinfomethods_t cm;
5250 dns_clientinfo_t ci;
5251 dns_dbversion_t *version = NULL;
5252 dns_zone_t *zone = NULL;
5253 bool is_zone;
5254 unsigned int labels;
5255
5256 CTRACE(ISC_LOG_DEBUG(3), "redirect2");
5257
5258 if (client->view->redirectzone == NULL) {
5259 return ISC_R_NOTFOUND;
5260 }
5261
5262 if (dns_name_issubdomain(name, client->view->redirectzone)) {
5263 return ISC_R_NOTFOUND;
5264 }
5265
5266 found = dns_fixedname_initname(&fixed);
5267 dns_rdataset_init(&trdataset);
5268
5269 dns_clientinfomethods_init(&cm, ns_client_sourceip);
5270 dns_clientinfo_init(&ci, client, NULL);
5271 dns_clientinfo_setecs(&ci, &client->ecs);
5272
5273 if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp))
5274 {
5275 return ISC_R_NOTFOUND;
5276 }
5277
5278 if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) {
5279 if (rdataset->trust == dns_trust_secure) {
5280 return ISC_R_NOTFOUND;
5281 }
5282 if (rdataset->trust == dns_trust_ultimate &&
5283 (rdataset->type == dns_rdatatype_nsec ||
5284 rdataset->type == dns_rdatatype_nsec3))
5285 {
5286 return ISC_R_NOTFOUND;
5287 }
5288 if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
5289 for (result = dns_rdataset_first(rdataset);
5290 result == ISC_R_SUCCESS;
5291 result = dns_rdataset_next(rdataset))
5292 {
5293 dns_ncache_current(rdataset, found, &trdataset);
5294 type = trdataset.type;
5295 dns_rdataset_disassociate(&trdataset);
5296 if (type == dns_rdatatype_nsec ||
5297 type == dns_rdatatype_nsec3 ||
5298 type == dns_rdatatype_rrsig)
5299 {
5300 return ISC_R_NOTFOUND;
5301 }
5302 }
5303 }
5304 }
5305
5306 redirectname = dns_fixedname_initname(&fixedredirect);
5307 labels = dns_name_countlabels(client->query.qname);
5308 if (labels > 1U) {
5309 dns_name_t prefix;
5310
5311 dns_name_init(&prefix, NULL);
5312 dns_name_getlabelsequence(client->query.qname, 0, labels - 1,
5313 &prefix);
5314 result = dns_name_concatenate(&prefix,
5315 client->view->redirectzone,
5316 redirectname, NULL);
5317 if (result != ISC_R_SUCCESS) {
5318 return ISC_R_NOTFOUND;
5319 }
5320 } else {
5321 dns_name_copy(redirectname, client->view->redirectzone);
5322 }
5323
5324 result = query_getdb(client, redirectname, qtype,
5325 (dns_getdb_options_t){ 0 }, &zone, &db, &version,
5326 &is_zone);
5327 if (result != ISC_R_SUCCESS) {
5328 return ISC_R_NOTFOUND;
5329 }
5330 if (zone != NULL) {
5331 dns_zone_detach(&zone);
5332 }
5333
5334 /*
5335 * Lookup the requested data in the redirect zone.
5336 */
5337 result = dns_db_findext(db, redirectname, version, qtype, 0,
5338 client->now, &node, found, &cm, &ci, &trdataset,
5339 NULL);
5340 if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
5341 if (dns_rdataset_isassociated(rdataset)) {
5342 dns_rdataset_disassociate(rdataset);
5343 }
5344 if (dns_rdataset_isassociated(&trdataset)) {
5345 dns_rdataset_disassociate(&trdataset);
5346 }
5347 goto nxrrset;
5348 } else if (result == ISC_R_NOTFOUND || result == DNS_R_DELEGATION) {
5349 /*
5350 * Cleanup.
5351 */
5352 if (dns_rdataset_isassociated(&trdataset)) {
5353 dns_rdataset_disassociate(&trdataset);
5354 }
5355 if (node != NULL) {
5356 dns_db_detachnode(db, &node);
5357 }
5358 dns_db_detach(&db);
5359 /*
5360 * Don't loop forever if the lookup failed last time.
5361 */
5362 if (!REDIRECT(client)) {
5363 result = ns_query_recurse(client, qtype, redirectname,
5364 NULL, NULL, true);
5365 if (result == ISC_R_SUCCESS) {
5366 client->query.attributes |=
5367 NS_QUERYATTR_RECURSING;
5368 client->query.attributes |=
5369 NS_QUERYATTR_REDIRECT;
5370 return DNS_R_CONTINUE;
5371 }
5372 }
5373 return ISC_R_NOTFOUND;
5374 } else if (result != ISC_R_SUCCESS) {
5375 if (dns_rdataset_isassociated(&trdataset)) {
5376 dns_rdataset_disassociate(&trdataset);
5377 }
5378 if (node != NULL) {
5379 dns_db_detachnode(db, &node);
5380 }
5381 dns_db_detach(&db);
5382 return ISC_R_NOTFOUND;
5383 }
5384
5385 CTRACE(ISC_LOG_DEBUG(3), "redirect2: found data: done");
5386 /*
5387 * Adjust the found name to not include the redirectzone suffix.
5388 */
5389 dns_name_split(found, dns_name_countlabels(client->view->redirectzone),
5390 found, NULL);
5391 /*
5392 * Make the name absolute.
5393 */
5394 result = dns_name_concatenate(found, dns_rootname, found, NULL);
5395 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5396
5397 dns_name_copy(found, name);
5398 if (dns_rdataset_isassociated(rdataset)) {
5399 dns_rdataset_disassociate(rdataset);
5400 }
5401 if (dns_rdataset_isassociated(&trdataset)) {
5402 dns_rdataset_clone(&trdataset, rdataset);
5403 dns_rdataset_disassociate(&trdataset);
5404 }
5405 nxrrset:
5406 if (*nodep != NULL) {
5407 dns_db_detachnode(*dbp, nodep);
5408 }
5409 dns_db_detach(dbp);
5410 dns_db_attachnode(db, node, nodep);
5411 dns_db_attach(db, dbp);
5412 dns_db_detachnode(db, &node);
5413 dns_db_detach(&db);
5414 *is_zonep = is_zone;
5415 *versionp = version;
5416
5417 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
5418 NS_QUERYATTR_NOADDITIONAL);
5419
5420 return result;
5421 }
5422
5423 /*%
5424 * Initialize query context 'qctx'. Run by query_setup() when
5425 * first handling a client query, and by query_resume() when
5426 * returning from recursion.
5427 *
5428 * Whenever this function is called, qctx_destroy() must be called
5429 * when leaving the scope or freeing the qctx.
5430 */
5431 static void
5432 qctx_init(ns_client_t *client, dns_fetchresponse_t **frespp,
5433 dns_rdatatype_t qtype, query_ctx_t *qctx) {
5434 REQUIRE(qctx != NULL);
5435 REQUIRE(client != NULL);
5436
5437 memset(qctx, 0, sizeof(*qctx));
5438
5439 /* Set this first so CCTRACE will work */
5440 qctx->client = client;
5441
5442 dns_view_attach(client->view, &qctx->view);
5443
5444 CCTRACE(ISC_LOG_DEBUG(3), "qctx_init");
5445
5446 if (frespp != NULL) {
5447 qctx->fresp = *frespp;
5448 *frespp = NULL;
5449 } else {
5450 qctx->fresp = NULL;
5451 }
5452 qctx->qtype = qctx->type = qtype;
5453 qctx->result = ISC_R_SUCCESS;
5454 qctx->findcoveringnsec = qctx->view->synthfromdnssec;
5455
5456 /*
5457 * If it's an RRSIG or SIG query, we'll iterate the node.
5458 */
5459 if (qctx->qtype == dns_rdatatype_rrsig ||
5460 qctx->qtype == dns_rdatatype_sig)
5461 {
5462 qctx->type = dns_rdatatype_any;
5463 }
5464
5465 CALL_HOOK_NORETURN(NS_QUERY_QCTX_INITIALIZED, qctx);
5466 }
5467
5468 /*%
5469 * Clean up and disassociate the rdataset and node pointers in qctx.
5470 */
5471 static void
5472 qctx_clean(query_ctx_t *qctx) {
5473 if (qctx->rdataset != NULL && dns_rdataset_isassociated(qctx->rdataset))
5474 {
5475 dns_rdataset_disassociate(qctx->rdataset);
5476 }
5477 if (qctx->sigrdataset != NULL &&
5478 dns_rdataset_isassociated(qctx->sigrdataset))
5479 {
5480 dns_rdataset_disassociate(qctx->sigrdataset);
5481 }
5482 if (qctx->db != NULL && qctx->node != NULL) {
5483 dns_db_detachnode(qctx->db, &qctx->node);
5484 }
5485 if (qctx->client != NULL && qctx->client->query.gluedb != NULL) {
5486 dns_db_detach(&qctx->client->query.gluedb);
5487 }
5488 }
5489
5490 /*%
5491 * Free any allocated memory associated with qctx.
5492 */
5493 static void
5494 qctx_freedata(query_ctx_t *qctx) {
5495 if (qctx->rdataset != NULL) {
5496 ns_client_putrdataset(qctx->client, &qctx->rdataset);
5497 }
5498
5499 if (qctx->sigrdataset != NULL) {
5500 ns_client_putrdataset(qctx->client, &qctx->sigrdataset);
5501 }
5502
5503 if (qctx->fname != NULL) {
5504 ns_client_releasename(qctx->client, &qctx->fname);
5505 }
5506
5507 if (qctx->db != NULL) {
5508 INSIST(qctx->node == NULL);
5509 dns_db_detach(&qctx->db);
5510 }
5511
5512 if (qctx->zone != NULL) {
5513 dns_zone_detach(&qctx->zone);
5514 }
5515
5516 if (qctx->zdb != NULL) {
5517 ns_client_putrdataset(qctx->client, &qctx->zsigrdataset);
5518 ns_client_putrdataset(qctx->client, &qctx->zrdataset);
5519 ns_client_releasename(qctx->client, &qctx->zfname);
5520 dns_db_detachnode(qctx->zdb, &qctx->znode);
5521 dns_db_detach(&qctx->zdb);
5522 qctx->zversion = NULL;
5523 }
5524
5525 if (qctx->fresp != NULL) {
5526 free_fresp(qctx->client, &qctx->fresp);
5527 }
5528 }
5529
5530 static void
5531 qctx_destroy(query_ctx_t *qctx) {
5532 CALL_HOOK_NORETURN(NS_QUERY_QCTX_DESTROYED, qctx);
5533
5534 dns_view_detach(&qctx->view);
5535 }
5536
5537 /*
5538 * Call SAVE but set 'a' to NULL first so as not to assert.
5539 */
5540 #define INITANDSAVE(a, b) \
5541 do { \
5542 a = NULL; \
5543 SAVE(a, b); \
5544 } while (0)
5545
5546 /*
5547 * "save" qctx data from 'src' to 'tgt'.
5548 * It essentially moves ownership of the data from src to tgt, so the former
5549 * becomes unusable except for final cleanup (such as by qctx_destroy).
5550 * Note: this function doesn't attach to the client's handle. It's the caller's
5551 * responsibility to do it if it's necessary.
5552 */
5553 static void
5554 qctx_save(query_ctx_t *src, query_ctx_t *tgt) {
5555 /* First copy all fields in a straightforward way */
5556 *tgt = *src;
5557
5558 /* Then "move" pointers (except client and view) */
5559 INITANDSAVE(tgt->dbuf, src->dbuf);
5560 INITANDSAVE(tgt->fname, src->fname);
5561 INITANDSAVE(tgt->tname, src->tname);
5562 INITANDSAVE(tgt->rdataset, src->rdataset);
5563 INITANDSAVE(tgt->sigrdataset, src->sigrdataset);
5564 INITANDSAVE(tgt->noqname, src->noqname);
5565 INITANDSAVE(tgt->fresp, src->fresp);
5566 INITANDSAVE(tgt->db, src->db);
5567 INITANDSAVE(tgt->version, src->version);
5568 INITANDSAVE(tgt->node, src->node);
5569 INITANDSAVE(tgt->zdb, src->zdb);
5570 INITANDSAVE(tgt->znode, src->znode);
5571 INITANDSAVE(tgt->zfname, src->zfname);
5572 INITANDSAVE(tgt->zversion, src->zversion);
5573 INITANDSAVE(tgt->zrdataset, src->zrdataset);
5574 INITANDSAVE(tgt->zsigrdataset, src->zsigrdataset);
5575 INITANDSAVE(tgt->rpz_st, src->rpz_st);
5576 INITANDSAVE(tgt->zone, src->zone);
5577
5578 /* View has to stay in 'src' for qctx_destroy. */
5579 tgt->view = NULL;
5580 dns_view_attach(src->view, &tgt->view);
5581 }
5582
5583 /*%
5584 * Log detailed information about the query immediately after
5585 * the client request or a return from recursion.
5586 */
5587 static void
5588 query_trace(query_ctx_t *qctx) {
5589 #ifdef WANT_QUERYTRACE
5590 char mbuf[2 * DNS_NAME_FORMATSIZE];
5591 char qbuf[DNS_NAME_FORMATSIZE];
5592
5593 if (qctx->client->query.origqname != NULL) {
5594 dns_name_format(qctx->client->query.origqname, qbuf,
5595 sizeof(qbuf));
5596 } else {
5597 snprintf(qbuf, sizeof(qbuf), "<unset>");
5598 }
5599
5600 snprintf(mbuf, sizeof(mbuf) - 1,
5601 "client attr:0x%x, query attr:0x%X, restarts:%u, "
5602 "origqname:%s, timer:%d, authdb:%d, referral:%d",
5603 qctx->client->attributes, qctx->client->query.attributes,
5604 qctx->client->query.restarts, qbuf,
5605 (int)qctx->client->query.timerset,
5606 (int)qctx->client->query.authdbset,
5607 (int)qctx->client->query.isreferral);
5608 CCTRACE(ISC_LOG_DEBUG(3), mbuf);
5609 #else /* ifdef WANT_QUERYTRACE */
5610 UNUSED(qctx);
5611 #endif /* ifdef WANT_QUERYTRACE */
5612 }
5613
5614 /*
5615 * Set up query processing for the current query of 'client'.
5616 * Calls qctx_init() to initialize a query context, checks
5617 * the SERVFAIL cache, then hands off processing to ns__query_start().
5618 *
5619 * This is called only from ns_query_start(), to begin a query
5620 * for the first time. Restarting an existing query (for
5621 * instance, to handle CNAME lookups), is done by calling
5622 * ns__query_start() again with the same query context. Resuming from
5623 * recursion is handled by query_resume().
5624 */
5625 static void
5626 query_setup(ns_client_t *client, dns_rdatatype_t qtype) {
5627 isc_result_t result = ISC_R_UNSET;
5628 query_ctx_t qctx;
5629
5630 qctx_init(client, NULL, qtype, &qctx);
5631 query_trace(&qctx);
5632
5633 CALL_HOOK(NS_QUERY_SETUP, &qctx);
5634
5635 /*
5636 * Check SERVFAIL cache
5637 */
5638 result = ns__query_sfcache(&qctx);
5639 if (result != ISC_R_COMPLETE) {
5640 goto cleanup;
5641 }
5642
5643 (void)ns__query_start(&qctx);
5644
5645 cleanup:
5646 qctx_destroy(&qctx);
5647 }
5648
5649 static bool
5650 get_root_key_sentinel_id(query_ctx_t *qctx, const char *ndata) {
5651 unsigned int v = 0;
5652 int i;
5653
5654 for (i = 0; i < 5; i++) {
5655 if (!isdigit((unsigned char)ndata[i])) {
5656 return false;
5657 }
5658 v *= 10;
5659 v += ndata[i] - '0';
5660 }
5661 if (v > 65535U) {
5662 return false;
5663 }
5664 qctx->client->query.root_key_sentinel_keyid = v;
5665 return true;
5666 }
5667
5668 /*%
5669 * Find out if the query is for a root key sentinel and if so, record the type
5670 * of root key sentinel query and the key id that is being checked for.
5671 *
5672 * The code is assuming a zero padded decimal field of width 5.
5673 */
5674 static void
5675 root_key_sentinel_detect(query_ctx_t *qctx) {
5676 const char *ndata = (const char *)qctx->client->query.qname->ndata;
5677
5678 if (qctx->client->query.qname->length > 30 && ndata[0] == 29 &&
5679 strncasecmp(ndata + 1, "root-key-sentinel-is-ta-", 24) == 0)
5680 {
5681 if (!get_root_key_sentinel_id(qctx, ndata + 25)) {
5682 return;
5683 }
5684 qctx->client->query.root_key_sentinel_is_ta = true;
5685 /*
5686 * Simplify processing by disabling aggressive
5687 * negative caching.
5688 */
5689 qctx->findcoveringnsec = false;
5690 ns_client_log(qctx->client, NS_LOGCATEGORY_TAT,
5691 NS_LOGMODULE_QUERY, ISC_LOG_INFO,
5692 "root-key-sentinel-is-ta query label found");
5693 } else if (qctx->client->query.qname->length > 31 && ndata[0] == 30 &&
5694 strncasecmp(ndata + 1, "root-key-sentinel-not-ta-", 25) == 0)
5695 {
5696 if (!get_root_key_sentinel_id(qctx, ndata + 26)) {
5697 return;
5698 }
5699 qctx->client->query.root_key_sentinel_not_ta = true;
5700 /*
5701 * Simplify processing by disabling aggressive
5702 * negative caching.
5703 */
5704 qctx->findcoveringnsec = false;
5705 ns_client_log(qctx->client, NS_LOGCATEGORY_TAT,
5706 NS_LOGMODULE_QUERY, ISC_LOG_INFO,
5707 "root-key-sentinel-not-ta query label found");
5708 }
5709 }
5710
5711 /*%
5712 * Starting point for a client query or a chaining query.
5713 *
5714 * Called first by query_setup(), and then again as often as needed to
5715 * follow a CNAME chain. Determines which authoritative database to
5716 * search, then hands off processing to query_lookup().
5717 */
5718 isc_result_t
5719 ns__query_start(query_ctx_t *qctx) {
5720 isc_result_t result = ISC_R_UNSET;
5721 CCTRACE(ISC_LOG_DEBUG(3), "ns__query_start");
5722 qctx->want_restart = false;
5723 qctx->authoritative = false;
5724 qctx->version = NULL;
5725 qctx->zversion = NULL;
5726 qctx->need_wildcardproof = false;
5727 qctx->rpz = false;
5728
5729 CALL_HOOK(NS_QUERY_START_BEGIN, qctx);
5730
5731 /*
5732 * If we require a server cookie or the presented server
5733 * cookie was bad then send back BADCOOKIE before we have
5734 * done too much work.
5735 */
5736 if (!TCP(qctx->client) &&
5737 (BADCOOKIE(qctx->client) ||
5738 (qctx->view->requireservercookie && WANTCOOKIE(qctx->client) &&
5739 !HAVECOOKIE(qctx->client))))
5740 {
5741 qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AA;
5742 qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD;
5743 qctx->client->message->rcode = dns_rcode_badcookie;
5744 return ns_query_done(qctx);
5745 }
5746
5747 if (qctx->view->checknames &&
5748 !dns_rdata_checkowner(qctx->client->query.qname,
5749 qctx->client->message->rdclass, qctx->qtype,
5750 false))
5751 {
5752 char namebuf[DNS_NAME_FORMATSIZE];
5753 char typebuf[DNS_RDATATYPE_FORMATSIZE];
5754 char classbuf[DNS_RDATACLASS_FORMATSIZE];
5755
5756 dns_name_format(qctx->client->query.qname, namebuf,
5757 sizeof(namebuf));
5758 dns_rdatatype_format(qctx->qtype, typebuf, sizeof(typebuf));
5759 dns_rdataclass_format(qctx->client->message->rdclass, classbuf,
5760 sizeof(classbuf));
5761 ns_client_log(qctx->client, DNS_LOGCATEGORY_SECURITY,
5762 NS_LOGMODULE_QUERY, ISC_LOG_ERROR,
5763 "check-names failure %s/%s/%s", namebuf, typebuf,
5764 classbuf);
5765 QUERY_ERROR(qctx, DNS_R_REFUSED);
5766 return ns_query_done(qctx);
5767 }
5768
5769 /*
5770 * Setup for root key sentinel processing.
5771 */
5772 if (qctx->view->root_key_sentinel &&
5773 qctx->client->query.restarts == 0 &&
5774 (qctx->qtype == dns_rdatatype_a ||
5775 qctx->qtype == dns_rdatatype_aaaa) &&
5776 (qctx->client->message->flags & DNS_MESSAGEFLAG_CD) == 0)
5777 {
5778 root_key_sentinel_detect(qctx);
5779 }
5780
5781 /*
5782 * First we must find the right database. Reset the options but preserve
5783 * the 'nolog' flag.
5784 */
5785 qctx->options = (dns_getdb_options_t){ .nolog = qctx->options.nolog };
5786 if (dns_rdatatype_atparent(qctx->qtype) &&
5787 !dns_name_equal(qctx->client->query.qname, dns_rootname))
5788 {
5789 /*
5790 * If authoritative data for this QTYPE is supposed to live in
5791 * the parent zone, do not look for an exact match for QNAME,
5792 * but rather for its containing zone (unless the QNAME is
5793 * root).
5794 */
5795 qctx->options.noexact = true;
5796 }
5797
5798 result = query_getdb(qctx->client, qctx->client->query.qname,
5799 qctx->qtype, qctx->options, &qctx->zone, &qctx->db,
5800 &qctx->version, &qctx->is_zone);
5801 if ((result != ISC_R_SUCCESS || !qctx->is_zone) &&
5802 qctx->qtype == dns_rdatatype_ds && !RECURSIONOK(qctx->client) &&
5803 qctx->options.noexact)
5804 {
5805 /*
5806 * This is a non-recursive QTYPE=DS query with QNAME whose
5807 * parent we are not authoritative for. Check whether we are
5808 * authoritative for QNAME, because if so, we need to send a
5809 * "no data" response as required by RFC 4035, section 3.1.4.1.
5810 */
5811 dns_db_t *tdb = NULL;
5812 dns_zone_t *tzone = NULL;
5813 dns_dbversion_t *tversion = NULL;
5814 isc_result_t tresult;
5815
5816 dns_getdb_options_t options = { .partial = true };
5817 tresult = query_getzonedb(
5818 qctx->client, qctx->client->query.qname, qctx->qtype,
5819 options, &tzone, &tdb, &tversion);
5820 if (tresult == ISC_R_SUCCESS) {
5821 /*
5822 * We are authoritative for QNAME. Attach the relevant
5823 * zone to query context, set result to ISC_R_SUCCESS.
5824 */
5825 qctx->options.noexact = false;
5826 ns_client_putrdataset(qctx->client, &qctx->rdataset);
5827 if (qctx->db != NULL) {
5828 dns_db_detach(&qctx->db);
5829 }
5830 if (qctx->zone != NULL) {
5831 dns_zone_detach(&qctx->zone);
5832 }
5833 qctx->version = NULL;
5834 RESTORE(qctx->version, tversion);
5835 RESTORE(qctx->db, tdb);
5836 RESTORE(qctx->zone, tzone);
5837 qctx->is_zone = true;
5838 result = ISC_R_SUCCESS;
5839 } else {
5840 /*
5841 * We are not authoritative for QNAME. Clean up and
5842 * leave result as it was.
5843 */
5844 if (tdb != NULL) {
5845 dns_db_detach(&tdb);
5846 }
5847 if (tzone != NULL) {
5848 dns_zone_detach(&tzone);
5849 }
5850 }
5851 }
5852 /*
5853 * If we did not find a database from which we can answer the query,
5854 * respond with either REFUSED or SERVFAIL, depending on what the
5855 * result of query_getdb() was.
5856 */
5857 if (result != ISC_R_SUCCESS) {
5858 if (result == DNS_R_REFUSED) {
5859 if (WANTRECURSION(qctx->client)) {
5860 dns_ede_add(&qctx->client->edectx,
5861 DNS_EDE_NOTAUTH,
5862 "recursion disabled");
5863 inc_stats(qctx->client,
5864 ns_statscounter_recurserej);
5865 } else {
5866 inc_stats(qctx->client,
5867 ns_statscounter_authrej);
5868 }
5869 if (!PARTIALANSWER(qctx->client)) {
5870 QUERY_ERROR(qctx, DNS_R_REFUSED);
5871 }
5872 } else {
5873 CCTRACE(ISC_LOG_ERROR, "ns__query_start: query_getdb "
5874 "failed");
5875 QUERY_ERROR(qctx, result);
5876 }
5877 return ns_query_done(qctx);
5878 }
5879
5880 /*
5881 * We found a database from which we can answer the query. Update
5882 * relevant query context flags if the answer is to be prepared using
5883 * authoritative data.
5884 */
5885 qctx->is_staticstub_zone = false;
5886 if (qctx->is_zone) {
5887 qctx->authoritative = true;
5888 if (qctx->zone != NULL) {
5889 if (dns_zone_gettype(qctx->zone) == dns_zone_mirror) {
5890 qctx->authoritative = false;
5891 }
5892 if (dns_zone_gettype(qctx->zone) == dns_zone_staticstub)
5893 {
5894 qctx->is_staticstub_zone = true;
5895 }
5896 }
5897 }
5898
5899 /*
5900 * Attach to the database which will be used to prepare the answer.
5901 * Update query statistics.
5902 */
5903 if (qctx->fresp == NULL && qctx->client->query.restarts == 0) {
5904 if (qctx->is_zone) {
5905 if (qctx->zone != NULL) {
5906 /*
5907 * if is_zone = true, zone = NULL then this is
5908 * a DLZ zone. Don't attempt to attach zone.
5909 */
5910 dns_zone_attach(qctx->zone,
5911 &qctx->client->query.authzone);
5912 }
5913 dns_db_attach(qctx->db, &qctx->client->query.authdb);
5914 }
5915 qctx->client->query.authdbset = true;
5916
5917 /* Track TCP vs UDP stats per zone */
5918 if (TCP(qctx->client)) {
5919 inc_stats(qctx->client, ns_statscounter_tcp);
5920 } else {
5921 inc_stats(qctx->client, ns_statscounter_udp);
5922 }
5923 }
5924
5925 /*
5926 * If stale answers are enabled and stale-answer-client-timeout is zero,
5927 * then we can promptly answer with a stale RRset if one is available in
5928 * cache.
5929 */
5930 qctx->options.stalefirst = (!qctx->is_zone &&
5931 qctx->view->staleanswerclienttimeout == 0 &&
5932 dns_view_staleanswerenabled(qctx->view));
5933
5934 result = query_lookup(qctx);
5935
5936 /*
5937 * Clear "look-also-for-stale-data" flag.
5938 * If a fetch is created to resolve this query, then,
5939 * when it completes, this option is not expected to be set.
5940 */
5941 qctx->options.stalefirst = false;
5942
5943 cleanup:
5944 return result;
5945 }
5946
5947 static void
5948 async_restart(void *arg) {
5949 query_ctx_t *qctx = arg;
5950 ns_client_t *client = qctx->client;
5951 isc_nmhandle_t *handle = client->restarthandle;
5952
5953 client->restarthandle = NULL;
5954
5955 ns__query_start(qctx);
5956
5957 qctx_clean(qctx);
5958 qctx_freedata(qctx);
5959 qctx_destroy(qctx);
5960 isc_mem_put(client->manager->mctx, qctx, sizeof(*qctx));
5961 isc_nmhandle_detach(&handle);
5962 }
5963
5964 /*
5965 * Allocate buffers in 'qctx' used to store query results.
5966 *
5967 * 'buffer' must be a pointer to an object whose lifetime
5968 * doesn't expire while 'qctx' is in use.
5969 */
5970 static isc_result_t
5971 qctx_prepare_buffers(query_ctx_t *qctx, isc_buffer_t *buffer) {
5972 REQUIRE(qctx != NULL);
5973 REQUIRE(qctx->client != NULL);
5974 REQUIRE(buffer != NULL);
5975
5976 qctx->dbuf = ns_client_getnamebuf(qctx->client);
5977 qctx->fname = ns_client_newname(qctx->client, qctx->dbuf, buffer);
5978 qctx->rdataset = ns_client_newrdataset(qctx->client);
5979
5980 if ((WANTDNSSEC(qctx->client) || qctx->findcoveringnsec) &&
5981 (!qctx->is_zone || dns_db_issecure(qctx->db)))
5982 {
5983 qctx->sigrdataset = ns_client_newrdataset(qctx->client);
5984 }
5985
5986 return ISC_R_SUCCESS;
5987 }
5988
5989 /*%
5990 * Depending on the db lookup result, we can respond to the
5991 * client this stale answer.
5992 */
5993 static bool
5994 stale_client_answer(isc_result_t result) {
5995 switch (result) {
5996 case ISC_R_SUCCESS:
5997 case DNS_R_EMPTYNAME:
5998 case DNS_R_NXRRSET:
5999 case DNS_R_NCACHENXRRSET:
6000 case DNS_R_CNAME:
6001 case DNS_R_DNAME:
6002 return true;
6003 default:
6004 return false;
6005 }
6006
6007 UNREACHABLE();
6008 }
6009
6010 /*%
6011 * Perform a local database lookup, in either an authoritative or
6012 * cache database. If unable to answer, call ns_query_done(); otherwise
6013 * hand off processing to query_gotanswer().
6014 */
6015 static isc_result_t
6016 query_lookup(query_ctx_t *qctx) {
6017 isc_buffer_t buffer;
6018 isc_result_t result = ISC_R_UNSET;
6019 dns_clientinfomethods_t cm;
6020 dns_clientinfo_t ci;
6021 dns_name_t *rpzqname = NULL;
6022 char namebuf[DNS_NAME_FORMATSIZE];
6023 char typebuf[DNS_RDATATYPE_FORMATSIZE];
6024 unsigned int dboptions;
6025 dns_ttl_t stale_refresh = 0;
6026 bool dbfind_stale = false;
6027 bool stale_timeout = false;
6028 bool answer_found = false;
6029 bool stale_found = false;
6030 bool stale_refresh_window = false;
6031 uint16_t ede = 0;
6032
6033 CCTRACE(ISC_LOG_DEBUG(3), "query_lookup");
6034
6035 CALL_HOOK(NS_QUERY_LOOKUP_BEGIN, qctx);
6036
6037 dns_clientinfomethods_init(&cm, ns_client_sourceip);
6038 dns_clientinfo_init(&ci, qctx->client, NULL);
6039 if (HAVEECS(qctx->client)) {
6040 dns_clientinfo_setecs(&ci, &qctx->client->ecs);
6041 }
6042
6043 /*
6044 * We'll need some resources...
6045 */
6046 result = qctx_prepare_buffers(qctx, &buffer);
6047 if (result != ISC_R_SUCCESS) {
6048 QUERY_ERROR(qctx, result);
6049 return ns_query_done(qctx);
6050 }
6051
6052 /*
6053 * Now look for an answer in the database.
6054 */
6055 if (qctx->dns64 && qctx->rpz) {
6056 rpzqname = qctx->client->query.rpz_st->p_name;
6057 } else {
6058 rpzqname = qctx->client->query.qname;
6059 }
6060
6061 qctx->client->query.dboptions &= ~DNS_DBFIND_STALETIMEOUT;
6062
6063 if (qctx->options.stalefirst && !qctx->is_zone) {
6064 /*
6065 * If the 'stalefirst' flag is set, it means that a stale
6066 * RRset may be returned as part of this lookup. An attempt
6067 * to refresh the RRset will still take place if an
6068 * active RRset is not available.
6069 */
6070 qctx->client->query.dboptions |= DNS_DBFIND_STALETIMEOUT;
6071 }
6072
6073 dboptions = qctx->client->query.dboptions;
6074 if (!qctx->is_zone && qctx->findcoveringnsec &&
6075 (qctx->type != dns_rdatatype_null || !dns_name_istat(rpzqname)))
6076 {
6077 dboptions |= DNS_DBFIND_COVERINGNSEC;
6078 }
6079
6080 (void)dns_db_getservestalerefresh(qctx->client->view->cachedb,
6081 &stale_refresh);
6082 if (stale_refresh > 0 &&
6083 dns_view_staleanswerenabled(qctx->client->view))
6084 {
6085 dboptions |= DNS_DBFIND_STALEENABLED;
6086 }
6087
6088 result = dns_db_findext(qctx->db, rpzqname, qctx->version, qctx->type,
6089 dboptions, qctx->client->now, &qctx->node,
6090 qctx->fname, &cm, &ci, qctx->rdataset,
6091 qctx->sigrdataset);
6092
6093 /*
6094 * Fixup fname and sigrdataset.
6095 */
6096 if (qctx->dns64 && qctx->rpz) {
6097 dns_name_copy(qctx->client->query.qname, qctx->fname);
6098 if (qctx->sigrdataset != NULL &&
6099 dns_rdataset_isassociated(qctx->sigrdataset))
6100 {
6101 dns_rdataset_disassociate(qctx->sigrdataset);
6102 }
6103 }
6104
6105 if (!qctx->is_zone) {
6106 dns_cache_updatestats(qctx->view->cache, result);
6107 }
6108
6109 /*
6110 * If DNS_DBFIND_STALEOK is set this means we are dealing with a
6111 * lookup following a failed lookup and it is okay to serve a stale
6112 * answer. This will (re)start the 'stale-refresh-time' window in
6113 * rbtdb, tracking the last time the RRset lookup failed.
6114 */
6115 dbfind_stale = ((dboptions & DNS_DBFIND_STALEOK) != 0);
6116
6117 /*
6118 * If DNS_DBFIND_STALEENABLED is set, this may be a normal lookup, but
6119 * we are allowed to immediately respond with a stale answer if the
6120 * request is within the 'stale-refresh-time' window.
6121 */
6122 stale_refresh_window = (STALE_WINDOW(qctx->rdataset) &&
6123 (dboptions & DNS_DBFIND_STALEENABLED) != 0);
6124
6125 /*
6126 * If DNS_DBFIND_STALETIMEOUT is set, a stale answer is requested.
6127 * This can happen if 'stale-answer-client-timeout' is enabled.
6128 *
6129 * If a stale answer is found, send it to the client, and try to refresh
6130 * the RRset.
6131 */
6132 stale_timeout = ((dboptions & DNS_DBFIND_STALETIMEOUT) != 0);
6133
6134 if (dns_rdataset_isassociated(qctx->rdataset) &&
6135 dns_rdataset_count(qctx->rdataset) > 0 && !STALE(qctx->rdataset))
6136 {
6137 /* Found non-stale usable rdataset. */
6138 answer_found = true;
6139 }
6140
6141 if (dbfind_stale || stale_refresh_window || stale_timeout) {
6142 dns_name_format(qctx->client->query.qname, namebuf,
6143 sizeof(namebuf));
6144 dns_rdatatype_format(qctx->qtype, typebuf, sizeof(typebuf));
6145
6146 inc_stats(qctx->client, ns_statscounter_trystale);
6147
6148 if (dns_rdataset_isassociated(qctx->rdataset) &&
6149 dns_rdataset_count(qctx->rdataset) > 0 &&
6150 STALE(qctx->rdataset))
6151 {
6152 stale_found = true;
6153 if (result == DNS_R_NCACHENXDOMAIN ||
6154 result == DNS_R_NXDOMAIN)
6155 {
6156 ede = DNS_EDE_STALENXANSWER;
6157 } else {
6158 ede = DNS_EDE_STALEANSWER;
6159 }
6160 qctx->rdataset->ttl = qctx->view->staleanswerttl;
6161 inc_stats(qctx->client, ns_statscounter_usedstale);
6162 } else {
6163 stale_found = false;
6164 }
6165 }
6166
6167 if (dbfind_stale) {
6168 isc_log_write(ns_lctx, NS_LOGCATEGORY_SERVE_STALE,
6169 NS_LOGMODULE_QUERY, ISC_LOG_INFO,
6170 "%s %s resolver failure, stale answer %s (%s)",
6171 namebuf, typebuf,
6172 stale_found ? "used" : "unavailable",
6173 isc_result_totext(result));
6174 if (stale_found) {
6175 dns_ede_add(&qctx->client->edectx, ede,
6176 "resolver failure");
6177 } else if (!answer_found) {
6178 /*
6179 * Resolver failure, no stale data, nothing more we
6180 * can do, return SERVFAIL.
6181 */
6182 QUERY_ERROR(qctx, DNS_R_SERVFAIL);
6183 return ns_query_done(qctx);
6184 }
6185 } else if (stale_refresh_window) {
6186 /*
6187 * A recent lookup failed, so during this time window we are
6188 * allowed to return stale data immediately.
6189 */
6190 isc_log_write(ns_lctx, NS_LOGCATEGORY_SERVE_STALE,
6191 NS_LOGMODULE_QUERY, ISC_LOG_INFO,
6192 "%s %s query within stale refresh time, stale "
6193 "answer %s (%s)",
6194 namebuf, typebuf,
6195 stale_found ? "used" : "unavailable",
6196 isc_result_totext(result));
6197
6198 if (stale_found) {
6199 dns_ede_add(&qctx->client->edectx, ede,
6200 "query within stale refresh time window");
6201 } else if (!answer_found) {
6202 /*
6203 * During the stale refresh window explicitly do not try
6204 * to refresh the data, because a recent lookup failed.
6205 */
6206 QUERY_ERROR(qctx, DNS_R_SERVFAIL);
6207 return ns_query_done(qctx);
6208 }
6209 } else if (stale_timeout) {
6210 if (qctx->options.stalefirst) {
6211 /*
6212 * If 'qctx->zdb' is set, this was a cache lookup after
6213 * an authoritative lookup returned a delegation (in
6214 * order to find a better answer). But we still can
6215 * return without getting any usable answer here, as
6216 * query_notfound() should handle it from here.
6217 * Otherwise, if nothing useful was found in cache then
6218 * recursively call query_lookup() again without the
6219 * 'stalefirst' option set.
6220 */
6221 if (!stale_found && !answer_found && qctx->zdb == NULL)
6222 {
6223 qctx_clean(qctx);
6224 qctx_freedata(qctx);
6225 dns_db_attach(qctx->client->view->cachedb,
6226 &qctx->db);
6227 qctx->options.stalefirst = false;
6228 if (FETCH_RECTYPE_NORMAL(qctx->client) != NULL)
6229 {
6230 dns_resolver_destroyfetch(
6231 &FETCH_RECTYPE_NORMAL(
6232 qctx->client));
6233 }
6234 return query_lookup(qctx);
6235 } else if (stale_client_answer(result)) {
6236 /*
6237 * Immediately return the stale answer, start a
6238 * resolver fetch to refresh the data in cache.
6239 */
6240 isc_log_write(
6241 ns_lctx, NS_LOGCATEGORY_SERVE_STALE,
6242 NS_LOGMODULE_QUERY, ISC_LOG_INFO,
6243 "%s %s stale answer used, an attempt "
6244 "to refresh the RRset will still be "
6245 "made",
6246 namebuf, typebuf);
6247 qctx->refresh_rrset = STALE(qctx->rdataset);
6248 if (stale_found) {
6249 dns_ede_add(
6250 &qctx->client->edectx, ede,
6251 "stale data prioritized over "
6252 "lookup");
6253 }
6254 }
6255 } else {
6256 UNREACHABLE();
6257 }
6258 }
6259
6260 if (stale_timeout && (answer_found || stale_found)) {
6261 /*
6262 * Mark RRsets that we are adding to the client message on a
6263 * lookup during 'stale-answer-client-timeout', so we can
6264 * clean it up if needed when we resume from recursion.
6265 */
6266 qctx->client->query.attributes |= NS_QUERYATTR_STALEOK;
6267 qctx->rdataset->attributes |= DNS_RDATASETATTR_STALE_ADDED;
6268 }
6269
6270 result = query_gotanswer(qctx, result);
6271
6272 cleanup:
6273 return result;
6274 }
6275
6276 /*
6277 * Clear all rdatasets from the message that are in the given section and
6278 * that have the 'attr' attribute set.
6279 */
6280 static void
6281 message_clearrdataset(dns_message_t *msg, unsigned int attr) {
6282 unsigned int i;
6283 dns_name_t *name, *next_name;
6284 dns_rdataset_t *rds, *next_rds;
6285
6286 /*
6287 * Clean up name lists by calling the rdataset disassociate function.
6288 */
6289 for (i = DNS_SECTION_ANSWER; i < DNS_SECTION_MAX; i++) {
6290 name = ISC_LIST_HEAD(msg->sections[i]);
6291 while (name != NULL) {
6292 next_name = ISC_LIST_NEXT(name, link);
6293
6294 rds = ISC_LIST_HEAD(name->list);
6295 while (rds != NULL) {
6296 next_rds = ISC_LIST_NEXT(rds, link);
6297 if ((rds->attributes & attr) != attr) {
6298 rds = next_rds;
6299 continue;
6300 }
6301 ISC_LIST_UNLINK(name->list, rds, link);
6302 INSIST(dns_rdataset_isassociated(rds));
6303 dns_rdataset_disassociate(rds);
6304 isc_mempool_put(msg->rdspool, rds);
6305 rds = next_rds;
6306 }
6307
6308 if (ISC_LIST_EMPTY(name->list)) {
6309 ISC_LIST_UNLINK(msg->sections[i], name, link);
6310 if (dns_name_dynamic(name)) {
6311 dns_name_free(name, msg->mctx);
6312 }
6313 isc_mempool_put(msg->namepool, name);
6314 }
6315
6316 name = next_name;
6317 }
6318 }
6319 }
6320
6321 /*
6322 * Clear any rdatasets from the client's message that were added on a lookup
6323 * due to a client timeout.
6324 */
6325 static void
6326 query_clear_stale(ns_client_t *client) {
6327 message_clearrdataset(client->message, DNS_RDATASETATTR_STALE_ADDED);
6328 }
6329
6330 /*
6331 * Event handler to resume processing a query after recursion, or when a
6332 * client timeout is triggered. If the query has timed out or been cancelled
6333 * or the system is shutting down, clean up and exit. If a client timeout is
6334 * triggered, see if we can respond with a stale answer from cache. Otherwise,
6335 * call query_resume() to continue the ongoing work.
6336 */
6337 static void
6338 fetch_callback(void *arg) {
6339 dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
6340 ns_client_t *client = resp->arg;
6341 dns_fetch_t *fetch = NULL;
6342 bool fetch_canceled = false;
6343 isc_logcategory_t *logcategory = NS_LOGCATEGORY_QUERY_ERRORS;
6344 isc_result_t result;
6345 int errorloglevel;
6346 query_ctx_t qctx;
6347
6348 REQUIRE(NS_CLIENT_VALID(client));
6349 REQUIRE(RECURSING(client));
6350
6351 CTRACE(ISC_LOG_DEBUG(3), "fetch_callback");
6352
6353 /*
6354 * We are resuming from recursion. Reset any attributes, options
6355 * that a lookup due to stale-answer-client-timeout may have set.
6356 */
6357 if (client->view->cachedb != NULL && client->view->recursion) {
6358 client->query.attributes |= NS_QUERYATTR_RECURSIONOK;
6359 }
6360 client->query.dboptions &= ~DNS_DBFIND_STALETIMEOUT;
6361
6362 LOCK(&client->query.fetchlock);
6363 INSIST(FETCH_RECTYPE_NORMAL(client) == resp->fetch ||
6364 FETCH_RECTYPE_NORMAL(client) == NULL);
6365 if (FETCH_RECTYPE_NORMAL(client) != NULL) {
6366 /*
6367 * This is the fetch we've been waiting for.
6368 */
6369 INSIST(FETCH_RECTYPE_NORMAL(client) == resp->fetch);
6370 FETCH_RECTYPE_NORMAL(client) = NULL;
6371
6372 /*
6373 * Update client->now.
6374 */
6375 client->now = isc_stdtime_now();
6376 } else {
6377 /*
6378 * This is a fetch completion event for a canceled fetch.
6379 * Clean up and don't resume the find.
6380 */
6381 fetch_canceled = true;
6382 }
6383 UNLOCK(&client->query.fetchlock);
6384
6385 SAVE(fetch, resp->fetch);
6386
6387 /*
6388 * We're done recursing, detach from quota and unlink from
6389 * the manager's recursing-clients list.
6390 */
6391 release_recursionquota(client);
6392
6393 isc_nmhandle_detach(&HANDLE_RECTYPE_NORMAL(client));
6394
6395 client->query.attributes &= ~NS_QUERYATTR_RECURSING;
6396 client->state = NS_CLIENTSTATE_WORKING;
6397
6398 /*
6399 * Initialize a new qctx and use it to either resume from
6400 * recursion or clean up after cancelation. Transfer
6401 * ownership of resp to the new qctx in the process.
6402 */
6403 qctx_init(client, &resp, 0, &qctx);
6404
6405 if (fetch_canceled) {
6406 /*
6407 * We've timed out or are shutting down. We can now
6408 * free the event and other resources held by qctx, but
6409 * don't call qctx_destroy() yet: it might destroy the
6410 * client, which we still need for a moment.
6411 */
6412 qctx_freedata(&qctx);
6413
6414 /*
6415 * Return an error to the client.
6416 */
6417 CTRACE(ISC_LOG_ERROR, "fetch cancelled");
6418 query_error(client, DNS_R_SERVFAIL, __LINE__);
6419
6420 /*
6421 * Free any persistent plugin data that was allocated to
6422 * service the client, then detach the client object.
6423 */
6424 qctx.detach_client = true;
6425 qctx_destroy(&qctx);
6426 } else {
6427 /*
6428 * Resume the find process.
6429 */
6430 query_trace(&qctx);
6431
6432 result = query_resume(&qctx);
6433 if (result != ISC_R_SUCCESS) {
6434 if (result == DNS_R_SERVFAIL) {
6435 errorloglevel = ISC_LOG_DEBUG(2);
6436 } else {
6437 errorloglevel = ISC_LOG_DEBUG(4);
6438 }
6439 if (isc_log_wouldlog(ns_lctx, errorloglevel)) {
6440 dns_resolver_logfetch(fetch, ns_lctx,
6441 logcategory,
6442 NS_LOGMODULE_QUERY,
6443 errorloglevel, false);
6444 }
6445 }
6446
6447 qctx_destroy(&qctx);
6448 }
6449
6450 dns_resolver_destroyfetch(&fetch);
6451 }
6452
6453 /*%
6454 * Check whether the recursion parameters in 'param' match the current query's
6455 * recursion parameters provided in 'qtype', 'qname', and 'qdomain'.
6456 */
6457 static bool
6458 recparam_match(const ns_query_recparam_t *param, dns_rdatatype_t qtype,
6459 const dns_name_t *qname, const dns_name_t *qdomain) {
6460 REQUIRE(param != NULL);
6461
6462 return param->qtype == qtype && param->qname != NULL && qname != NULL &&
6463 param->qdomain != NULL && qdomain != NULL &&
6464 dns_name_equal(param->qname, qname) &&
6465 dns_name_equal(param->qdomain, qdomain);
6466 }
6467
6468 /*%
6469 * Update 'param' with current query's recursion parameters provided in
6470 * 'qtype', 'qname', and 'qdomain'.
6471 */
6472 static void
6473 recparam_update(ns_query_recparam_t *param, dns_rdatatype_t qtype,
6474 const dns_name_t *qname, const dns_name_t *qdomain) {
6475 REQUIRE(param != NULL);
6476
6477 param->qtype = qtype;
6478
6479 if (qname == NULL) {
6480 param->qname = NULL;
6481 } else {
6482 param->qname = dns_fixedname_initname(¶m->fqname);
6483 dns_name_copy(qname, param->qname);
6484 }
6485
6486 if (qdomain == NULL) {
6487 param->qdomain = NULL;
6488 } else {
6489 param->qdomain = dns_fixedname_initname(¶m->fqdomain);
6490 dns_name_copy(qdomain, param->qdomain);
6491 }
6492 }
6493
6494 static void
6495 recursionquota_log(ns_client_t *client, atomic_uint_fast32_t *last_log_time,
6496 const char *format, isc_quota_t *quota) {
6497 isc_stdtime_t now = isc_stdtime_now();
6498 if (now == atomic_load_relaxed(last_log_time)) {
6499 return;
6500 }
6501
6502 atomic_store_relaxed(last_log_time, now);
6503 ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY,
6504 ISC_LOG_WARNING, format, isc_quota_getused(quota),
6505 isc_quota_getsoft(quota), isc_quota_getmax(quota));
6506 }
6507
6508 static atomic_uint_fast32_t last_soft, last_hard;
6509
6510 /*%
6511 * Acquire recursion quota before making the current client "recursing".
6512 */
6513 static isc_result_t
6514 acquire_recursionquota(ns_client_t *client) {
6515 isc_result_t result;
6516
6517 result = recursionquotatype_attach_soft(client);
6518 switch (result) {
6519 case ISC_R_SOFTQUOTA:
6520 recursionquota_log(client, &last_soft,
6521 "recursive-clients soft limit exceeded "
6522 "(%u/%u/%u), aborting oldest query",
6523 &client->manager->sctx->recursionquota);
6524 ns_client_killoldestquery(client);
6525 FALLTHROUGH;
6526 case ISC_R_SUCCESS:
6527 break;
6528 case ISC_R_QUOTA:
6529 recursionquota_log(client, &last_hard,
6530 "no more recursive clients (%u/%u/%u)",
6531 &client->manager->sctx->recursionquota);
6532 ns_client_killoldestquery(client);
6533 return result;
6534 default:
6535 UNREACHABLE();
6536 }
6537
6538 dns_message_clonebuffer(client->message);
6539 ns_client_recursing(client);
6540
6541 return ISC_R_SUCCESS;
6542 }
6543
6544 /*%
6545 * Release recursion quota and remove the client from the "recursing" list.
6546 */
6547 static void
6548 release_recursionquota(ns_client_t *client) {
6549 recursionquotatype_detach(client);
6550
6551 LOCK(&client->manager->reclock);
6552 if (ISC_LINK_LINKED(client, rlink)) {
6553 ISC_LIST_UNLINK(client->manager->recursing, client, rlink);
6554 }
6555 UNLOCK(&client->manager->reclock);
6556 }
6557
6558 isc_result_t
6559 ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
6560 dns_name_t *qdomain, dns_rdataset_t *nameservers,
6561 bool resuming) {
6562 isc_result_t result;
6563 dns_rdataset_t *rdataset, *sigrdataset;
6564 isc_sockaddr_t *peeraddr = NULL;
6565
6566 CTRACE(ISC_LOG_DEBUG(3), "ns_query_recurse");
6567
6568 /*
6569 * Check recursion parameters from the previous query to see if they
6570 * match. If not, update recursion parameters and proceed.
6571 */
6572 if (recparam_match(&client->query.recparam, qtype, qname, qdomain)) {
6573 ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY,
6574 ISC_LOG_INFO, "recursion loop detected");
6575 return ISC_R_FAILURE;
6576 }
6577
6578 recparam_update(&client->query.recparam, qtype, qname, qdomain);
6579
6580 if (!resuming) {
6581 inc_stats(client, ns_statscounter_recursion);
6582 }
6583
6584 result = acquire_recursionquota(client);
6585 if (result != ISC_R_SUCCESS) {
6586 return result;
6587 }
6588
6589 /*
6590 * Invoke the resolver.
6591 */
6592 REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns);
6593 REQUIRE(FETCH_RECTYPE_NORMAL(client) == NULL);
6594
6595 rdataset = ns_client_newrdataset(client);
6596
6597 if (WANTDNSSEC(client)) {
6598 sigrdataset = ns_client_newrdataset(client);
6599 } else {
6600 sigrdataset = NULL;
6601 }
6602
6603 if (!client->query.timerset) {
6604 ns_client_settimeout(client, 60);
6605 }
6606
6607 if (!TCP(client)) {
6608 peeraddr = &client->peeraddr;
6609 }
6610
6611 isc_nmhandle_attach(client->handle, &HANDLE_RECTYPE_NORMAL(client));
6612 result = dns_resolver_createfetch(
6613 client->view->resolver, qname, qtype, qdomain, nameservers,
6614 NULL, peeraddr, client->message->id, client->query.fetchoptions,
6615 0, NULL, client->query.qc, client->manager->loop,
6616 fetch_callback, client, &client->edectx, rdataset, sigrdataset,
6617 &FETCH_RECTYPE_NORMAL(client));
6618 if (result != ISC_R_SUCCESS) {
6619 release_recursionquota(client);
6620
6621 ns_client_putrdataset(client, &rdataset);
6622 if (sigrdataset != NULL) {
6623 ns_client_putrdataset(client, &sigrdataset);
6624 }
6625
6626 isc_nmhandle_detach(&HANDLE_RECTYPE_NORMAL(client));
6627 }
6628
6629 /*
6630 * We're now waiting for a fetch event. A client which is
6631 * shutting down will not be destroyed until all the events
6632 * have been received.
6633 */
6634
6635 return result;
6636 }
6637
6638 /*%
6639 * Restores the query context after resuming from recursion, and
6640 * continues the query processing if needed.
6641 */
6642 static isc_result_t
6643 query_resume(query_ctx_t *qctx) {
6644 isc_result_t result = ISC_R_UNSET;
6645 dns_name_t *tname;
6646 isc_buffer_t b;
6647 #ifdef WANT_QUERYTRACE
6648 char mbuf[4 * DNS_NAME_FORMATSIZE];
6649 char qbuf[DNS_NAME_FORMATSIZE];
6650 char tbuf[DNS_RDATATYPE_FORMATSIZE];
6651 #endif /* ifdef WANT_QUERYTRACE */
6652
6653 CCTRACE(ISC_LOG_DEBUG(3), "query_resume");
6654
6655 CALL_HOOK(NS_QUERY_RESUME_BEGIN, qctx);
6656
6657 qctx->want_restart = false;
6658
6659 qctx->rpz_st = qctx->client->query.rpz_st;
6660 if (qctx->rpz_st != NULL &&
6661 (qctx->rpz_st->state & DNS_RPZ_RECURSING) != 0)
6662 {
6663 CCTRACE(ISC_LOG_DEBUG(3), "resume from RPZ recursion");
6664 #ifdef WANT_QUERYTRACE
6665 {
6666 char pbuf[DNS_NAME_FORMATSIZE] = "<unset>";
6667 char fbuf[DNS_NAME_FORMATSIZE] = "<unset>";
6668 if (qctx->rpz_st->r_name != NULL) {
6669 dns_name_format(qctx->rpz_st->r_name, qbuf,
6670 sizeof(qbuf));
6671 } else {
6672 snprintf(qbuf, sizeof(qbuf), "<unset>");
6673 }
6674 if (qctx->rpz_st->p_name != NULL) {
6675 dns_name_format(qctx->rpz_st->p_name, pbuf,
6676 sizeof(pbuf));
6677 }
6678 if (qctx->rpz_st->fname != NULL) {
6679 dns_name_format(qctx->rpz_st->fname, fbuf,
6680 sizeof(fbuf));
6681 }
6682
6683 snprintf(mbuf, sizeof(mbuf) - 1,
6684 "rpz rname:%s, pname:%s, qctx->fname:%s", qbuf,
6685 pbuf, fbuf);
6686 CCTRACE(ISC_LOG_DEBUG(3), mbuf);
6687 }
6688 #endif /* ifdef WANT_QUERYTRACE */
6689
6690 qctx->is_zone = qctx->rpz_st->q.is_zone;
6691 qctx->authoritative = qctx->rpz_st->q.authoritative;
6692 RESTORE(qctx->zone, qctx->rpz_st->q.zone);
6693 RESTORE(qctx->node, qctx->rpz_st->q.node);
6694 RESTORE(qctx->db, qctx->rpz_st->q.db);
6695 RESTORE(qctx->rdataset, qctx->rpz_st->q.rdataset);
6696 RESTORE(qctx->sigrdataset, qctx->rpz_st->q.sigrdataset);
6697 qctx->qtype = qctx->rpz_st->q.qtype;
6698
6699 if (qctx->fresp->node != NULL) {
6700 dns_db_detachnode(qctx->fresp->db, &qctx->fresp->node);
6701 }
6702 SAVE(qctx->rpz_st->r.db, qctx->fresp->db);
6703 qctx->rpz_st->r.r_type = qctx->fresp->qtype;
6704 SAVE(qctx->rpz_st->r.r_rdataset, qctx->fresp->rdataset);
6705 ns_client_putrdataset(qctx->client, &qctx->fresp->sigrdataset);
6706 } else if (REDIRECT(qctx->client)) {
6707 /*
6708 * Restore saved state.
6709 */
6710 CCTRACE(ISC_LOG_DEBUG(3), "resume from redirect recursion");
6711 #ifdef WANT_QUERYTRACE
6712 dns_name_format(qctx->client->query.redirect.fname, qbuf,
6713 sizeof(qbuf));
6714 dns_rdatatype_format(qctx->client->query.redirect.qtype, tbuf,
6715 sizeof(tbuf));
6716 snprintf(mbuf, sizeof(mbuf) - 1,
6717 "redirect qctx->fname:%s, qtype:%s, auth:%d", qbuf,
6718 tbuf, qctx->client->query.redirect.authoritative);
6719 CCTRACE(ISC_LOG_DEBUG(3), mbuf);
6720 #endif /* ifdef WANT_QUERYTRACE */
6721 qctx->qtype = qctx->client->query.redirect.qtype;
6722 INSIST(qctx->client->query.redirect.rdataset != NULL);
6723 RESTORE(qctx->rdataset, qctx->client->query.redirect.rdataset);
6724 RESTORE(qctx->sigrdataset,
6725 qctx->client->query.redirect.sigrdataset);
6726 RESTORE(qctx->db, qctx->client->query.redirect.db);
6727 RESTORE(qctx->node, qctx->client->query.redirect.node);
6728 RESTORE(qctx->zone, qctx->client->query.redirect.zone);
6729 qctx->authoritative =
6730 qctx->client->query.redirect.authoritative;
6731
6732 /*
6733 * Free resources used while recursing.
6734 */
6735 ns_client_putrdataset(qctx->client, &qctx->fresp->rdataset);
6736 ns_client_putrdataset(qctx->client, &qctx->fresp->sigrdataset);
6737 if (qctx->fresp->node != NULL) {
6738 dns_db_detachnode(qctx->fresp->db, &qctx->fresp->node);
6739 }
6740 if (qctx->fresp->db != NULL) {
6741 dns_db_detach(&qctx->fresp->db);
6742 }
6743 } else {
6744 CCTRACE(ISC_LOG_DEBUG(3), "resume from normal recursion");
6745 qctx->authoritative = false;
6746
6747 qctx->qtype = qctx->fresp->qtype;
6748 SAVE(qctx->db, qctx->fresp->db);
6749 SAVE(qctx->node, qctx->fresp->node);
6750 SAVE(qctx->rdataset, qctx->fresp->rdataset);
6751 SAVE(qctx->sigrdataset, qctx->fresp->sigrdataset);
6752 }
6753 INSIST(qctx->rdataset != NULL);
6754
6755 if (qctx->qtype == dns_rdatatype_rrsig ||
6756 qctx->qtype == dns_rdatatype_sig)
6757 {
6758 qctx->type = dns_rdatatype_any;
6759 } else {
6760 qctx->type = qctx->qtype;
6761 }
6762
6763 CALL_HOOK(NS_QUERY_RESUME_RESTORED, qctx);
6764
6765 if (DNS64(qctx->client)) {
6766 qctx->client->query.attributes &= ~NS_QUERYATTR_DNS64;
6767 qctx->dns64 = true;
6768 }
6769
6770 if (DNS64EXCLUDE(qctx->client)) {
6771 qctx->client->query.attributes &= ~NS_QUERYATTR_DNS64EXCLUDE;
6772 qctx->dns64_exclude = true;
6773 }
6774
6775 if (qctx->rpz_st != NULL &&
6776 (qctx->rpz_st->state & DNS_RPZ_RECURSING) != 0)
6777 {
6778 /*
6779 * Has response policy changed out from under us?
6780 */
6781 if (qctx->view->rpzs == NULL ||
6782 qctx->rpz_st->rpz_ver != qctx->view->rpzs->rpz_ver)
6783 {
6784 ns_client_log(qctx->client, NS_LOGCATEGORY_CLIENT,
6785 NS_LOGMODULE_QUERY, DNS_RPZ_INFO_LEVEL,
6786 "query_resume: RPZ settings out of date "
6787 "after of a reconfiguration");
6788 QUERY_ERROR(qctx, DNS_R_SERVFAIL);
6789 return ns_query_done(qctx);
6790 }
6791 }
6792
6793 /*
6794 * We'll need some resources...
6795 */
6796 qctx->dbuf = ns_client_getnamebuf(qctx->client);
6797 qctx->fname = ns_client_newname(qctx->client, qctx->dbuf, &b);
6798
6799 if (qctx->rpz_st != NULL &&
6800 (qctx->rpz_st->state & DNS_RPZ_RECURSING) != 0)
6801 {
6802 tname = qctx->rpz_st->fname;
6803 } else if (REDIRECT(qctx->client)) {
6804 tname = qctx->client->query.redirect.fname;
6805 } else {
6806 tname = qctx->fresp->foundname;
6807 }
6808
6809 dns_name_copy(tname, qctx->fname);
6810
6811 if (qctx->rpz_st != NULL &&
6812 (qctx->rpz_st->state & DNS_RPZ_RECURSING) != 0)
6813 {
6814 qctx->rpz_st->r.r_result = qctx->fresp->result;
6815 result = qctx->rpz_st->q.result;
6816 free_fresp(qctx->client, &qctx->fresp);
6817 } else if (REDIRECT(qctx->client)) {
6818 result = qctx->client->query.redirect.result;
6819 } else {
6820 result = qctx->fresp->result;
6821 }
6822
6823 qctx->resuming = true;
6824
6825 return query_gotanswer(qctx, result);
6826
6827 cleanup:
6828 return result;
6829 }
6830
6831 static void
6832 query_hookresume(void *arg) {
6833 ns_hook_resume_t *rev = (ns_hook_resume_t *)arg;
6834 ns_hookasync_t *hctx = NULL;
6835 ns_client_t *client = rev->arg;
6836 query_ctx_t *qctx = rev->saved_qctx;
6837 bool canceled;
6838
6839 CTRACE(ISC_LOG_DEBUG(3), "query_hookresume");
6840
6841 REQUIRE(NS_CLIENT_VALID(client));
6842
6843 LOCK(&client->query.fetchlock);
6844 if (client->query.hookactx != NULL) {
6845 INSIST(rev->ctx == client->query.hookactx);
6846 client->query.hookactx = NULL;
6847 canceled = false;
6848 client->now = isc_stdtime_now();
6849 } else {
6850 canceled = true;
6851 }
6852 UNLOCK(&client->query.fetchlock);
6853 SAVE(hctx, rev->ctx);
6854
6855 release_recursionquota(client);
6856
6857 /*
6858 * The fetch handle should be detached before resuming query processing
6859 * below, since that may trigger another recursion or asynchronous hook
6860 * event.
6861 */
6862 isc_nmhandle_detach(&HANDLE_RECTYPE_HOOK(client));
6863
6864 client->state = NS_CLIENTSTATE_WORKING;
6865
6866 if (canceled) {
6867 /*
6868 * Note: unlike fetch_callback, this function doesn't bother
6869 * to check the 'shutdown' condition, as that doesn't seem to
6870 * happen in the latest implementation.
6871 */
6872 query_error(client, DNS_R_SERVFAIL, __LINE__);
6873
6874 /*
6875 * There's no other place to free/release any data maintained
6876 * in qctx. We need to do it here to prevent leak.
6877 */
6878 qctx_clean(qctx);
6879 qctx_freedata(qctx);
6880
6881 /*
6882 * As we're almost done with this client, make sure any internal
6883 * resource for hooks will be released (if necessary) via the
6884 * QCTX_DESTROYED hook.
6885 */
6886 qctx->detach_client = true;
6887 } else {
6888 switch (rev->hookpoint) {
6889 case NS_QUERY_SETUP:
6890 query_setup(client, qctx->qtype);
6891 break;
6892 case NS_QUERY_START_BEGIN:
6893 (void)ns__query_start(qctx);
6894 break;
6895 case NS_QUERY_LOOKUP_BEGIN:
6896 (void)query_lookup(qctx);
6897 break;
6898 case NS_QUERY_RESUME_BEGIN:
6899 case NS_QUERY_RESUME_RESTORED:
6900 (void)query_resume(qctx);
6901 break;
6902 case NS_QUERY_GOT_ANSWER_BEGIN:
6903 (void)query_gotanswer(qctx, rev->origresult);
6904 break;
6905 case NS_QUERY_RESPOND_ANY_BEGIN:
6906 (void)query_respond_any(qctx);
6907 break;
6908 case NS_QUERY_ADDANSWER_BEGIN:
6909 (void)query_addanswer(qctx);
6910 break;
6911 case NS_QUERY_NOTFOUND_BEGIN:
6912 (void)query_notfound(qctx);
6913 break;
6914 case NS_QUERY_PREP_DELEGATION_BEGIN:
6915 (void)query_prepare_delegation_response(qctx);
6916 break;
6917 case NS_QUERY_ZONE_DELEGATION_BEGIN:
6918 (void)query_zone_delegation(qctx);
6919 break;
6920 case NS_QUERY_DELEGATION_BEGIN:
6921 (void)query_delegation(qctx);
6922 break;
6923 case NS_QUERY_DELEGATION_RECURSE_BEGIN:
6924 (void)query_delegation_recurse(qctx);
6925 break;
6926 case NS_QUERY_NODATA_BEGIN:
6927 (void)query_nodata(qctx, rev->origresult);
6928 break;
6929 case NS_QUERY_NXDOMAIN_BEGIN:
6930 (void)query_nxdomain(qctx, rev->origresult);
6931 break;
6932 case NS_QUERY_NCACHE_BEGIN:
6933 (void)query_ncache(qctx, rev->origresult);
6934 break;
6935 case NS_QUERY_CNAME_BEGIN:
6936 (void)query_cname(qctx);
6937 break;
6938 case NS_QUERY_DNAME_BEGIN:
6939 (void)query_dname(qctx);
6940 break;
6941 case NS_QUERY_RESPOND_BEGIN:
6942 (void)query_respond(qctx);
6943 break;
6944 case NS_QUERY_PREP_RESPONSE_BEGIN:
6945 (void)query_prepresponse(qctx);
6946 break;
6947 case NS_QUERY_DONE_BEGIN:
6948 case NS_QUERY_DONE_SEND:
6949 (void)ns_query_done(qctx);
6950 break;
6951
6952 /* Not all hookpoints can use recursion. Catch violations */
6953 case NS_QUERY_RESPOND_ANY_FOUND: /* due to side effect */
6954 case NS_QUERY_NOTFOUND_RECURSE: /* in recursion */
6955 case NS_QUERY_ZEROTTL_RECURSE: /* in recursion */
6956 default: /* catch-all just in case */
6957 INSIST(false);
6958 }
6959 }
6960
6961 isc_mem_put(hctx->mctx, rev, sizeof(*rev));
6962 hctx->destroy(&hctx);
6963 qctx_destroy(qctx);
6964 isc_mem_put(client->manager->mctx, qctx, sizeof(*qctx));
6965 }
6966
6967 isc_result_t
6968 ns_query_hookasync(query_ctx_t *qctx, ns_query_starthookasync_t runasync,
6969 void *arg) {
6970 isc_result_t result;
6971 ns_client_t *client = qctx->client;
6972 query_ctx_t *saved_qctx = NULL;
6973
6974 CTRACE(ISC_LOG_DEBUG(3), "ns_query_hookasync");
6975
6976 REQUIRE(NS_CLIENT_VALID(client));
6977 REQUIRE(client->query.hookactx == NULL);
6978 REQUIRE(FETCH_RECTYPE_NORMAL(client) == NULL);
6979
6980 result = acquire_recursionquota(client);
6981 if (result != ISC_R_SUCCESS) {
6982 goto cleanup;
6983 }
6984
6985 saved_qctx = isc_mem_get(client->manager->mctx, sizeof(*saved_qctx));
6986 qctx_save(qctx, saved_qctx);
6987 result = runasync(saved_qctx, client->manager->mctx, arg,
6988 client->manager->loop, query_hookresume, client,
6989 &client->query.hookactx);
6990 if (result != ISC_R_SUCCESS) {
6991 goto cleanup_and_detach_from_quota;
6992 }
6993
6994 /* Record that an asynchronous copy of the qctx has been started */
6995 qctx->async = true;
6996
6997 /*
6998 * Typically the runasync() function will trigger recursion, but
6999 * there is no need to set NS_QUERYATTR_RECURSING. The calling hook
7000 * is expected to return NS_HOOK_RETURN, and the RECURSING
7001 * attribute won't be checked anywhere.
7002 *
7003 * Hook-based asynchronous processing cannot coincide with normal
7004 * recursion. Unlike in ns_query_recurse(), we attach to the handle
7005 * only if 'runasync' succeeds. It should be safe since we're either in
7006 * the client task or pausing it.
7007 */
7008 isc_nmhandle_attach(client->handle, &HANDLE_RECTYPE_HOOK(client));
7009 return ISC_R_SUCCESS;
7010
7011 cleanup_and_detach_from_quota:
7012 release_recursionquota(client);
7013 cleanup:
7014 /*
7015 * If we fail, send SERVFAIL now. It may be better to let the caller
7016 * decide what to do on failure of this function, but hooks don't have
7017 * access to query_error().
7018 */
7019 query_error(client, DNS_R_SERVFAIL, __LINE__);
7020
7021 /*
7022 * Free all resource related to the query and set detach_client,
7023 * similar to the cancel case of query_hookresume; the callers will
7024 * simply return on failure of this function, so there's no other
7025 * place for this to prevent leak.
7026 */
7027 if (saved_qctx != NULL) {
7028 qctx_clean(saved_qctx);
7029 qctx_freedata(saved_qctx);
7030 qctx_destroy(saved_qctx);
7031 isc_mem_put(client->manager->mctx, saved_qctx,
7032 sizeof(*saved_qctx));
7033 }
7034 qctx->detach_client = true;
7035 return result;
7036 }
7037
7038 /*%
7039 * If the query is recursive, check the SERVFAIL cache to see whether
7040 * identical queries have failed recently. If we find a match, and it was
7041 * from a query with CD=1, *or* if the current query has CD=0, then we just
7042 * return SERVFAIL again. This prevents a validation failure from eliciting a
7043 * SERVFAIL response to a CD=1 query.
7044 */
7045 isc_result_t
7046 ns__query_sfcache(query_ctx_t *qctx) {
7047 isc_result_t failcache;
7048 uint32_t flags;
7049
7050 /*
7051 * The SERVFAIL cache doesn't apply to authoritative queries.
7052 */
7053 if (!RECURSIONOK(qctx->client)) {
7054 return ISC_R_COMPLETE;
7055 }
7056
7057 flags = 0;
7058 #ifdef ENABLE_AFL
7059 if (qctx->client->manager->sctx->fuzztype == isc_fuzz_resolver) {
7060 failcache = ISC_R_NOTFOUND;
7061 } else
7062 #endif /* ifdef ENABLE_AFL */
7063 {
7064 failcache = dns_badcache_find(
7065 qctx->view->failcache, qctx->client->query.qname,
7066 qctx->qtype, &flags,
7067 isc_time_seconds(&qctx->client->tnow));
7068 }
7069
7070 if (failcache != ISC_R_SUCCESS) {
7071 return ISC_R_COMPLETE;
7072 }
7073
7074 if (((flags & NS_FAILCACHE_CD) != 0) ||
7075 ((qctx->client->message->flags & DNS_MESSAGEFLAG_CD) == 0))
7076 {
7077 if (isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(1))) {
7078 char namebuf[DNS_NAME_FORMATSIZE];
7079 char typebuf[DNS_RDATATYPE_FORMATSIZE];
7080
7081 dns_name_format(qctx->client->query.qname, namebuf,
7082 sizeof(namebuf));
7083 dns_rdatatype_format(qctx->qtype, typebuf,
7084 sizeof(typebuf));
7085 ns_client_log(qctx->client, NS_LOGCATEGORY_CLIENT,
7086 NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(1),
7087 "servfail cache hit %s/%s (%s)", namebuf,
7088 typebuf,
7089 ((flags & NS_FAILCACHE_CD) != 0) ? "CD=1"
7090 : "CD="
7091 "0");
7092 }
7093
7094 qctx->client->attributes |= NS_CLIENTATTR_NOSETFC;
7095 QUERY_ERROR(qctx, DNS_R_SERVFAIL);
7096 return ns_query_done(qctx);
7097 }
7098
7099 return ISC_R_COMPLETE;
7100 }
7101
7102 static void
7103 query_trace_rrldrop(query_ctx_t *qctx,
7104 dns_rrl_result_t rrl_result ISC_ATTR_UNUSED) {
7105 if (!LIBNS_RRL_DROP_ENABLED()) {
7106 return;
7107 }
7108
7109 char peerbuf[ISC_SOCKADDR_FORMATSIZE];
7110 isc_netaddr_t peer;
7111 isc_netaddr_fromsockaddr(&peer, &qctx->client->peeraddr);
7112 isc_netaddr_format(&peer, peerbuf, sizeof(peerbuf));
7113
7114 char qnamebuf[DNS_NAME_FORMATSIZE];
7115 char fnamebuf[DNS_NAME_FORMATSIZE];
7116 dns_name_format(qctx->client->query.qname, qnamebuf, sizeof(qnamebuf));
7117 dns_name_format(qctx->fname, fnamebuf, sizeof(fnamebuf));
7118 LIBNS_RRL_DROP(peerbuf, qnamebuf, fnamebuf, rrl_result);
7119 }
7120
7121 /*%
7122 * Handle response rate limiting (RRL).
7123 */
7124 static isc_result_t
7125 query_checkrrl(query_ctx_t *qctx, isc_result_t result) {
7126 /*
7127 * Rate limit these responses to this client.
7128 * Do not delay counting and handling obvious referrals,
7129 * since those won't come here again.
7130 * Delay handling delegations for which we are certain to recurse and
7131 * return here (DNS_R_DELEGATION, not a child of one of our
7132 * own zones, and recursion enabled)
7133 * Don't mess with responses rewritten by RPZ
7134 * Count each response at most once.
7135 */
7136
7137 /*
7138 * XXXMPA the rrl system tests fails sometimes and RRL_CHECKED
7139 * is set when we are called the second time preventing the
7140 * response being dropped.
7141 */
7142 ns_client_log(
7143 qctx->client, DNS_LOGCATEGORY_RRL, NS_LOGMODULE_QUERY,
7144 ISC_LOG_DEBUG(99),
7145 "rrl=%p, HAVECOOKIE=%u, result=%s, "
7146 "fname=%p(%u), is_zone=%u, RECURSIONOK=%u, "
7147 "query.rpz_st=%p(%u), RRL_CHECKED=%u",
7148 qctx->client->view->rrl, HAVECOOKIE(qctx->client),
7149 isc_result_toid(result), qctx->fname,
7150 qctx->fname != NULL ? dns_name_isabsolute(qctx->fname) : 0,
7151 qctx->is_zone, RECURSIONOK(qctx->client),
7152 qctx->client->query.rpz_st,
7153 qctx->client->query.rpz_st != NULL
7154 ? ((qctx->client->query.rpz_st->state &
7155 DNS_RPZ_REWRITTEN) != 0)
7156 : 0,
7157 (qctx->client->query.attributes & NS_QUERYATTR_RRL_CHECKED) !=
7158 0);
7159
7160 if (qctx->view->rrl != NULL && !HAVECOOKIE(qctx->client) &&
7161 ((qctx->fname != NULL && dns_name_isabsolute(qctx->fname)) ||
7162 (result == ISC_R_NOTFOUND && !RECURSIONOK(qctx->client))) &&
7163 !(result == DNS_R_DELEGATION && !qctx->is_zone &&
7164 RECURSIONOK(qctx->client)) &&
7165 (qctx->client->query.rpz_st == NULL ||
7166 (qctx->client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0) &&
7167 (qctx->client->query.attributes & NS_QUERYATTR_RRL_CHECKED) == 0)
7168 {
7169 dns_rdataset_t nc_rdataset;
7170 bool wouldlog;
7171 dns_fixedname_t fixed;
7172 const dns_name_t *constname;
7173 char log_buf[DNS_RRL_LOG_BUF_LEN];
7174 isc_result_t nc_result, resp_result;
7175 dns_rrl_result_t rrl_result;
7176
7177 qctx->client->query.attributes |= NS_QUERYATTR_RRL_CHECKED;
7178
7179 wouldlog = isc_log_wouldlog(ns_lctx, DNS_RRL_LOG_DROP);
7180 constname = qctx->fname;
7181 if (result == DNS_R_NXDOMAIN) {
7182 /*
7183 * Use the database origin name to rate limit NXDOMAIN
7184 */
7185 if (qctx->db != NULL) {
7186 constname = dns_db_origin(qctx->db);
7187 }
7188 resp_result = result;
7189 } else if (result == DNS_R_NCACHENXDOMAIN &&
7190 qctx->rdataset != NULL &&
7191 dns_rdataset_isassociated(qctx->rdataset) &&
7192 (qctx->rdataset->attributes &
7193 DNS_RDATASETATTR_NEGATIVE) != 0)
7194 {
7195 /*
7196 * Try to use owner name in the negative cache SOA.
7197 */
7198 dns_fixedname_init(&fixed);
7199 dns_rdataset_init(&nc_rdataset);
7200 for (nc_result = dns_rdataset_first(qctx->rdataset);
7201 nc_result == ISC_R_SUCCESS;
7202 nc_result = dns_rdataset_next(qctx->rdataset))
7203 {
7204 dns_ncache_current(qctx->rdataset,
7205 dns_fixedname_name(&fixed),
7206 &nc_rdataset);
7207 if (nc_rdataset.type == dns_rdatatype_soa) {
7208 dns_rdataset_disassociate(&nc_rdataset);
7209 constname = dns_fixedname_name(&fixed);
7210 break;
7211 }
7212 dns_rdataset_disassociate(&nc_rdataset);
7213 }
7214 resp_result = DNS_R_NXDOMAIN;
7215 } else if (result == DNS_R_NXRRSET || result == DNS_R_EMPTYNAME)
7216 {
7217 resp_result = DNS_R_NXRRSET;
7218 } else if (result == DNS_R_DELEGATION) {
7219 resp_result = result;
7220 } else if (result == ISC_R_NOTFOUND) {
7221 /*
7222 * Handle referral to ".", including when recursion
7223 * is off or not requested and the hints have not
7224 * been loaded.
7225 */
7226 constname = dns_rootname;
7227 resp_result = DNS_R_DELEGATION;
7228 } else {
7229 resp_result = ISC_R_SUCCESS;
7230 }
7231
7232 rrl_result = dns_rrl(
7233 qctx->view, qctx->zone, &qctx->client->peeraddr,
7234 TCP(qctx->client), qctx->client->message->rdclass,
7235 qctx->qtype, constname, resp_result, qctx->client->now,
7236 wouldlog, log_buf, sizeof(log_buf));
7237 if (rrl_result != DNS_RRL_RESULT_OK) {
7238 /*
7239 * Log dropped or slipped responses in the query
7240 * category so that requests are not silently lost.
7241 * Starts of rate-limited bursts are logged in
7242 * DNS_LOGCATEGORY_RRL.
7243 *
7244 * Dropped responses are counted with dropped queries
7245 * in QryDropped while slipped responses are counted
7246 * with other truncated responses in RespTruncated.
7247 */
7248 if (wouldlog) {
7249 ns_client_log(qctx->client, DNS_LOGCATEGORY_RRL,
7250 NS_LOGMODULE_QUERY,
7251 DNS_RRL_LOG_DROP, "%s", log_buf);
7252 }
7253
7254 /*
7255 * If tracing is enabled, format some extra information
7256 * to pass along.
7257 */
7258 query_trace_rrldrop(qctx, rrl_result);
7259
7260 if (!qctx->view->rrl->log_only) {
7261 if (rrl_result == DNS_RRL_RESULT_DROP) {
7262 /*
7263 * These will also be counted in
7264 * ns_statscounter_dropped
7265 */
7266 inc_stats(qctx->client,
7267 ns_statscounter_ratedropped);
7268 QUERY_ERROR(qctx, DNS_R_DROP);
7269 } else {
7270 /*
7271 * These will also be counted in
7272 * ns_statscounter_truncatedresp
7273 */
7274 inc_stats(qctx->client,
7275 ns_statscounter_rateslipped);
7276 if (WANTCOOKIE(qctx->client)) {
7277 qctx->client->message->flags &=
7278 ~DNS_MESSAGEFLAG_AA;
7279 qctx->client->message->flags &=
7280 ~DNS_MESSAGEFLAG_AD;
7281 qctx->client->message->rcode =
7282 dns_rcode_badcookie;
7283 } else {
7284 qctx->client->message->flags |=
7285 DNS_MESSAGEFLAG_TC;
7286 if (resp_result ==
7287 DNS_R_NXDOMAIN)
7288 {
7289 qctx->client->message
7290 ->rcode =
7291 dns_rcode_nxdomain;
7292 }
7293 }
7294 }
7295 return DNS_R_DROP;
7296 }
7297 }
7298 }
7299
7300 return ISC_R_SUCCESS;
7301 }
7302
7303 /*%
7304 * Do any RPZ rewriting that may be needed for this query.
7305 */
7306 static isc_result_t
7307 query_checkrpz(query_ctx_t *qctx, isc_result_t result) {
7308 isc_result_t rresult;
7309
7310 CCTRACE(ISC_LOG_DEBUG(3), "query_checkrpz");
7311
7312 rresult = rpz_rewrite(qctx->client, qctx->qtype, result, qctx->resuming,
7313 qctx->rdataset, qctx->sigrdataset);
7314 qctx->rpz_st = qctx->client->query.rpz_st;
7315 switch (rresult) {
7316 case ISC_R_SUCCESS:
7317 break;
7318 case ISC_R_NOTFOUND:
7319 case DNS_R_DISALLOWED:
7320 return result;
7321 case DNS_R_DELEGATION:
7322 /*
7323 * recursing for NS names or addresses,
7324 * so save the main query state
7325 */
7326 INSIST(!RECURSING(qctx->client));
7327 qctx->rpz_st->q.qtype = qctx->qtype;
7328 qctx->rpz_st->q.is_zone = qctx->is_zone;
7329 qctx->rpz_st->q.authoritative = qctx->authoritative;
7330 SAVE(qctx->rpz_st->q.zone, qctx->zone);
7331 SAVE(qctx->rpz_st->q.db, qctx->db);
7332 SAVE(qctx->rpz_st->q.node, qctx->node);
7333 SAVE(qctx->rpz_st->q.rdataset, qctx->rdataset);
7334 SAVE(qctx->rpz_st->q.sigrdataset, qctx->sigrdataset);
7335 dns_name_copy(qctx->fname, qctx->rpz_st->fname);
7336 qctx->rpz_st->q.result = result;
7337 qctx->client->query.attributes |= NS_QUERYATTR_RECURSING;
7338 return ISC_R_COMPLETE;
7339 default:
7340 QUERY_ERROR(qctx, rresult);
7341 return ISC_R_COMPLETE;
7342 }
7343
7344 if (qctx->rpz_st->m.policy != DNS_RPZ_POLICY_MISS) {
7345 qctx->rpz_st->state |= DNS_RPZ_REWRITTEN;
7346 }
7347
7348 if (qctx->rpz_st->m.policy != DNS_RPZ_POLICY_MISS &&
7349 qctx->rpz_st->m.policy != DNS_RPZ_POLICY_PASSTHRU &&
7350 (qctx->rpz_st->m.policy != DNS_RPZ_POLICY_TCP_ONLY ||
7351 !TCP(qctx->client)) &&
7352 qctx->rpz_st->m.policy != DNS_RPZ_POLICY_ERROR)
7353 {
7354 /*
7355 * We got a hit and are going to answer with our
7356 * fiction. Ensure that we answer with the name
7357 * we looked up even if we were stopped short
7358 * in recursion or for a deferral.
7359 */
7360 dns_name_copy(qctx->client->query.qname, qctx->fname);
7361 rpz_clean(&qctx->zone, &qctx->db, &qctx->node, NULL);
7362 if (qctx->rpz_st->m.rdataset != NULL) {
7363 ns_client_putrdataset(qctx->client, &qctx->rdataset);
7364 RESTORE(qctx->rdataset, qctx->rpz_st->m.rdataset);
7365 } else {
7366 qctx_clean(qctx);
7367 }
7368 qctx->version = NULL;
7369
7370 RESTORE(qctx->node, qctx->rpz_st->m.node);
7371 RESTORE(qctx->db, qctx->rpz_st->m.db);
7372 RESTORE(qctx->version, qctx->rpz_st->m.version);
7373 RESTORE(qctx->zone, qctx->rpz_st->m.zone);
7374
7375 /*
7376 * Add SOA record to additional section
7377 */
7378 if (qctx->rpz_st->m.rpz->addsoa) {
7379 rresult = query_addsoa(qctx, UINT32_MAX,
7380 DNS_SECTION_ADDITIONAL);
7381 if (rresult != ISC_R_SUCCESS) {
7382 QUERY_ERROR(qctx, result);
7383 return ISC_R_COMPLETE;
7384 }
7385 }
7386
7387 switch (qctx->rpz_st->m.policy) {
7388 case DNS_RPZ_POLICY_TCP_ONLY:
7389 qctx->client->message->flags |= DNS_MESSAGEFLAG_TC;
7390 if (result == DNS_R_NXDOMAIN ||
7391 result == DNS_R_NCACHENXDOMAIN)
7392 {
7393 qctx->client->message->rcode =
7394 dns_rcode_nxdomain;
7395 }
7396 rpz_log_rewrite(qctx->client, false,
7397 qctx->rpz_st->m.policy,
7398 qctx->rpz_st->m.type, qctx->zone,
7399 qctx->rpz_st->p_name, NULL,
7400 qctx->rpz_st->m.rpz->num);
7401 return ISC_R_COMPLETE;
7402 case DNS_RPZ_POLICY_DROP:
7403 QUERY_ERROR(qctx, DNS_R_DROP);
7404 rpz_log_rewrite(qctx->client, false,
7405 qctx->rpz_st->m.policy,
7406 qctx->rpz_st->m.type, qctx->zone,
7407 qctx->rpz_st->p_name, NULL,
7408 qctx->rpz_st->m.rpz->num);
7409 return ISC_R_COMPLETE;
7410 case DNS_RPZ_POLICY_NXDOMAIN:
7411 result = DNS_R_NXDOMAIN;
7412 qctx->nxrewrite = true;
7413 qctx->rpz = true;
7414 break;
7415 case DNS_RPZ_POLICY_NODATA:
7416 qctx->nxrewrite = true;
7417 FALLTHROUGH;
7418 case DNS_RPZ_POLICY_DNS64:
7419 result = DNS_R_NXRRSET;
7420 qctx->rpz = true;
7421 break;
7422 case DNS_RPZ_POLICY_RECORD:
7423 result = qctx->rpz_st->m.result;
7424 if (qctx->qtype == dns_rdatatype_any &&
7425 result != DNS_R_CNAME)
7426 {
7427 /*
7428 * We will add all of the rdatasets of
7429 * the node by iterating later,
7430 * and set the TTL then.
7431 */
7432 if (dns_rdataset_isassociated(qctx->rdataset)) {
7433 dns_rdataset_disassociate(
7434 qctx->rdataset);
7435 }
7436 } else {
7437 /*
7438 * We will add this rdataset.
7439 */
7440 qctx->rdataset->ttl =
7441 ISC_MIN(qctx->rdataset->ttl,
7442 qctx->rpz_st->m.ttl);
7443 }
7444 qctx->rpz = true;
7445 break;
7446 case DNS_RPZ_POLICY_WILDCNAME: {
7447 dns_rdata_t rdata = DNS_RDATA_INIT;
7448 dns_rdata_cname_t cname;
7449 result = dns_rdataset_first(qctx->rdataset);
7450 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7451 dns_rdataset_current(qctx->rdataset, &rdata);
7452 result = dns_rdata_tostruct(&rdata, &cname, NULL);
7453 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7454 dns_rdata_reset(&rdata);
7455 result = query_rpzcname(qctx, &cname.cname);
7456 if (result != ISC_R_SUCCESS) {
7457 return ISC_R_COMPLETE;
7458 }
7459 qctx->fname = NULL;
7460 qctx->want_restart = true;
7461 return ISC_R_COMPLETE;
7462 }
7463 case DNS_RPZ_POLICY_CNAME:
7464 /*
7465 * Add overriding CNAME from a named.conf
7466 * response-policy statement
7467 */
7468 result = query_rpzcname(qctx,
7469 &qctx->rpz_st->m.rpz->cname);
7470 if (result != ISC_R_SUCCESS) {
7471 return ISC_R_COMPLETE;
7472 }
7473 qctx->fname = NULL;
7474 qctx->want_restart = true;
7475 return ISC_R_COMPLETE;
7476 default:
7477 UNREACHABLE();
7478 }
7479
7480 if (qctx->rpz_st->m.rpz->ede != 0 &&
7481 qctx->rpz_st->m.rpz->ede != UINT16_MAX)
7482 {
7483 dns_ede_add(&qctx->client->edectx,
7484 qctx->rpz_st->m.rpz->ede, NULL);
7485 }
7486
7487 /*
7488 * Turn off DNSSEC because the results of a
7489 * response policy zone cannot verify.
7490 */
7491 qctx->client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
7492 NS_CLIENTATTR_WANTAD);
7493 qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD;
7494 ns_client_putrdataset(qctx->client, &qctx->sigrdataset);
7495 qctx->rpz_st->q.is_zone = qctx->is_zone;
7496 qctx->is_zone = true;
7497 rpz_log_rewrite(qctx->client, false, qctx->rpz_st->m.policy,
7498 qctx->rpz_st->m.type, qctx->zone,
7499 qctx->rpz_st->p_name, NULL,
7500 qctx->rpz_st->m.rpz->num);
7501 }
7502
7503 return result;
7504 }
7505
7506 /*%
7507 * Add a CNAME to a query response, including translating foo.evil.com and
7508 * *.evil.com CNAME *.example.com
7509 * to
7510 * foo.evil.com CNAME foo.evil.com.example.com
7511 */
7512 static isc_result_t
7513 query_rpzcname(query_ctx_t *qctx, dns_name_t *cname) {
7514 ns_client_t *client;
7515 dns_fixedname_t prefix, suffix;
7516 unsigned int labels;
7517 isc_result_t result;
7518
7519 REQUIRE(qctx != NULL && qctx->client != NULL);
7520
7521 client = qctx->client;
7522
7523 CTRACE(ISC_LOG_DEBUG(3), "query_rpzcname");
7524
7525 labels = dns_name_countlabels(cname);
7526 if (labels > 2 && dns_name_iswildcard(cname)) {
7527 dns_fixedname_init(&prefix);
7528 dns_name_split(client->query.qname, 1,
7529 dns_fixedname_name(&prefix), NULL);
7530 dns_fixedname_init(&suffix);
7531 dns_name_split(cname, labels - 1, NULL,
7532 dns_fixedname_name(&suffix));
7533 result = dns_name_concatenate(dns_fixedname_name(&prefix),
7534 dns_fixedname_name(&suffix),
7535 qctx->fname, NULL);
7536 if (result == DNS_R_NAMETOOLONG) {
7537 client->message->rcode = dns_rcode_yxdomain;
7538 } else if (result != ISC_R_SUCCESS) {
7539 return result;
7540 }
7541 } else {
7542 dns_name_copy(cname, qctx->fname);
7543 }
7544
7545 ns_client_keepname(client, qctx->fname, qctx->dbuf);
7546 query_addcname(qctx, dns_trust_authanswer, qctx->rpz_st->m.ttl);
7547
7548 rpz_log_rewrite(client, false, qctx->rpz_st->m.policy,
7549 qctx->rpz_st->m.type, qctx->rpz_st->m.zone,
7550 qctx->rpz_st->p_name, qctx->fname,
7551 qctx->rpz_st->m.rpz->num);
7552
7553 ns_client_qnamereplace(client, qctx->fname);
7554
7555 /*
7556 * Turn off DNSSEC because the results of a
7557 * response policy zone cannot verify.
7558 */
7559 client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
7560 NS_CLIENTATTR_WANTAD);
7561
7562 return ISC_R_SUCCESS;
7563 }
7564
7565 /*%
7566 * Check the configured trust anchors for a root zone trust anchor
7567 * with a key id that matches qctx->client->query.root_key_sentinel_keyid.
7568 *
7569 * Return true when found, otherwise return false.
7570 */
7571 static bool
7572 has_ta(query_ctx_t *qctx) {
7573 dns_keytable_t *keytable = NULL;
7574 dns_keynode_t *keynode = NULL;
7575 dns_rdataset_t dsset;
7576 dns_keytag_t sentinel = qctx->client->query.root_key_sentinel_keyid;
7577 isc_result_t result;
7578
7579 result = dns_view_getsecroots(qctx->view, &keytable);
7580 if (result != ISC_R_SUCCESS) {
7581 return false;
7582 }
7583
7584 result = dns_keytable_find(keytable, dns_rootname, &keynode);
7585 if (result != ISC_R_SUCCESS) {
7586 if (keynode != NULL) {
7587 dns_keynode_detach(&keynode);
7588 }
7589 dns_keytable_detach(&keytable);
7590 return false;
7591 }
7592
7593 dns_rdataset_init(&dsset);
7594 if (dns_keynode_dsset(keynode, &dsset)) {
7595 for (result = dns_rdataset_first(&dsset);
7596 result == ISC_R_SUCCESS;
7597 result = dns_rdataset_next(&dsset))
7598 {
7599 dns_rdata_t rdata = DNS_RDATA_INIT;
7600 dns_rdata_ds_t ds;
7601
7602 dns_rdata_reset(&rdata);
7603 dns_rdataset_current(&dsset, &rdata);
7604 result = dns_rdata_tostruct(&rdata, &ds, NULL);
7605 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7606 if (ds.key_tag == sentinel) {
7607 dns_keynode_detach(&keynode);
7608 dns_keytable_detach(&keytable);
7609 dns_rdataset_disassociate(&dsset);
7610 return true;
7611 }
7612 }
7613 dns_rdataset_disassociate(&dsset);
7614 }
7615
7616 if (keynode != NULL) {
7617 dns_keynode_detach(&keynode);
7618 }
7619
7620 dns_keytable_detach(&keytable);
7621
7622 return false;
7623 }
7624
7625 /*%
7626 * Check if a root key sentinel SERVFAIL should be returned.
7627 */
7628 static bool
7629 root_key_sentinel_return_servfail(query_ctx_t *qctx, isc_result_t result) {
7630 /*
7631 * Are we looking at a "root-key-sentinel" query?
7632 */
7633 if (!qctx->client->query.root_key_sentinel_is_ta &&
7634 !qctx->client->query.root_key_sentinel_not_ta)
7635 {
7636 return false;
7637 }
7638
7639 /*
7640 * We only care about the query if 'result' indicates we have a cached
7641 * answer.
7642 */
7643 switch (result) {
7644 case ISC_R_SUCCESS:
7645 case DNS_R_CNAME:
7646 case DNS_R_DNAME:
7647 case DNS_R_NCACHENXDOMAIN:
7648 case DNS_R_NCACHENXRRSET:
7649 break;
7650 default:
7651 return false;
7652 }
7653
7654 /*
7655 * Do we meet the specified conditions to return SERVFAIL?
7656 */
7657 if (!qctx->is_zone && qctx->rdataset->trust == dns_trust_secure &&
7658 ((qctx->client->query.root_key_sentinel_is_ta && !has_ta(qctx)) ||
7659 (qctx->client->query.root_key_sentinel_not_ta && has_ta(qctx))))
7660 {
7661 return true;
7662 }
7663
7664 /*
7665 * As special processing may only be triggered by the original QNAME,
7666 * disable it after following a CNAME/DNAME.
7667 */
7668 qctx->client->query.root_key_sentinel_is_ta = false;
7669 qctx->client->query.root_key_sentinel_not_ta = false;
7670
7671 return false;
7672 }
7673
7674 /*%
7675 * If serving stale answers is allowed, set up 'qctx' to look for one and
7676 * return true; otherwise, return false.
7677 */
7678 static bool
7679 query_usestale(query_ctx_t *qctx, isc_result_t result) {
7680 if ((qctx->client->query.dboptions & DNS_DBFIND_STALEOK) != 0) {
7681 /*
7682 * Query was already using stale, if that didn't work the
7683 * last time, it won't work this time either.
7684 */
7685 return false;
7686 }
7687
7688 if (result == DNS_R_DUPLICATE || result == DNS_R_DROP) {
7689 /*
7690 * Don't enable serve-stale if the result signals a duplicate
7691 * query or query that is being dropped.
7692 */
7693 return false;
7694 }
7695
7696 qctx_clean(qctx);
7697 qctx_freedata(qctx);
7698
7699 if (dns_view_staleanswerenabled(qctx->client->view)) {
7700 isc_result_t ret;
7701 ret = query_getdb(qctx->client, qctx->client->query.qname,
7702 qctx->client->query.qtype, qctx->options,
7703 &qctx->zone, &qctx->db, &qctx->version,
7704 &qctx->is_zone);
7705 if (ret != ISC_R_SUCCESS) {
7706 /*
7707 * Failed to get the database, unexpected, but let us
7708 * at least abandon serve-stale.
7709 */
7710 return false;
7711 }
7712
7713 qctx->client->query.dboptions |= DNS_DBFIND_STALEOK;
7714 if (FETCH_RECTYPE_NORMAL(qctx->client) != NULL) {
7715 dns_resolver_destroyfetch(
7716 &FETCH_RECTYPE_NORMAL(qctx->client));
7717 }
7718
7719 /*
7720 * Start the stale-refresh-time window in case there was a
7721 * resolver query timeout.
7722 */
7723 if (qctx->resuming && result == ISC_R_TIMEDOUT) {
7724 qctx->client->query.dboptions |= DNS_DBFIND_STALESTART;
7725 }
7726 return true;
7727 }
7728
7729 return false;
7730 }
7731
7732 /*%
7733 * Continue after doing a database lookup or returning from
7734 * recursion, and call out to the next function depending on the
7735 * result from the search.
7736 */
7737 static isc_result_t
7738 query_gotanswer(query_ctx_t *qctx, isc_result_t result) {
7739 char errmsg[256];
7740
7741 CCTRACE(ISC_LOG_DEBUG(3), "query_gotanswer");
7742
7743 CALL_HOOK(NS_QUERY_GOT_ANSWER_BEGIN, qctx);
7744
7745 if (query_checkrrl(qctx, result) != ISC_R_SUCCESS) {
7746 return ns_query_done(qctx);
7747 }
7748
7749 if (!dns_name_equal(qctx->client->query.qname, dns_rootname)) {
7750 result = query_checkrpz(qctx, result);
7751 if (result == ISC_R_NOTFOUND) {
7752 /*
7753 * RPZ not configured for this view.
7754 */
7755 goto root_key_sentinel;
7756 }
7757 if (RECURSING(qctx->client) && result == DNS_R_DISALLOWED) {
7758 /*
7759 * We are recursing, and thus RPZ processing is not
7760 * allowed at the moment. This could happen on a
7761 * "stale-answer-client-timeout" lookup. In this case,
7762 * bail out and wait for recursion to complete, as we
7763 * we can't perform the RPZ rewrite rules.
7764 */
7765 return result;
7766 }
7767 if (result == ISC_R_COMPLETE) {
7768 return ns_query_done(qctx);
7769 }
7770 }
7771
7772 root_key_sentinel:
7773 /*
7774 * If required, handle special "root-key-sentinel-is-ta-<keyid>" and
7775 * "root-key-sentinel-not-ta-<keyid>" labels by returning SERVFAIL.
7776 */
7777 if (root_key_sentinel_return_servfail(qctx, result)) {
7778 /*
7779 * Don't record this response in the SERVFAIL cache.
7780 */
7781 qctx->client->attributes |= NS_CLIENTATTR_NOSETFC;
7782 QUERY_ERROR(qctx, DNS_R_SERVFAIL);
7783 return ns_query_done(qctx);
7784 }
7785
7786 switch (result) {
7787 case ISC_R_SUCCESS:
7788 return query_prepresponse(qctx);
7789
7790 case DNS_R_GLUE:
7791 case DNS_R_ZONECUT:
7792 INSIST(qctx->is_zone);
7793 qctx->authoritative = false;
7794 return query_prepresponse(qctx);
7795
7796 case ISC_R_NOTFOUND:
7797 return query_notfound(qctx);
7798
7799 case DNS_R_DELEGATION:
7800 return query_delegation(qctx);
7801
7802 case DNS_R_EMPTYNAME:
7803 case DNS_R_NXRRSET:
7804 return query_nodata(qctx, result);
7805
7806 case DNS_R_EMPTYWILD:
7807 case DNS_R_NXDOMAIN:
7808 return query_nxdomain(qctx, result);
7809
7810 case DNS_R_COVERINGNSEC:
7811 return query_coveringnsec(qctx);
7812
7813 case DNS_R_NCACHENXDOMAIN:
7814 result = query_redirect(qctx, result);
7815 if (result != ISC_R_COMPLETE) {
7816 return result;
7817 }
7818 return query_ncache(qctx, DNS_R_NCACHENXDOMAIN);
7819
7820 case DNS_R_NCACHENXRRSET:
7821 return query_ncache(qctx, DNS_R_NCACHENXRRSET);
7822
7823 case DNS_R_CNAME:
7824 return query_cname(qctx);
7825
7826 case DNS_R_DNAME:
7827 return query_dname(qctx);
7828
7829 default:
7830 /*
7831 * Something has gone wrong.
7832 */
7833 snprintf(errmsg, sizeof(errmsg) - 1,
7834 "query_gotanswer: unexpected error: %s",
7835 isc_result_totext(result));
7836 CCTRACE(ISC_LOG_ERROR, errmsg);
7837 if (query_usestale(qctx, result)) {
7838 /*
7839 * If serve-stale is enabled, query_usestale() already
7840 * set up 'qctx' for looking up a stale response.
7841 */
7842 return query_lookup(qctx);
7843 }
7844
7845 /*
7846 * Regardless of the triggering result, we definitely
7847 * want to return SERVFAIL from here.
7848 */
7849 qctx->client->rcode_override = dns_rcode_servfail;
7850
7851 QUERY_ERROR(qctx, result);
7852 return ns_query_done(qctx);
7853 }
7854
7855 cleanup:
7856 return result;
7857 }
7858
7859 static void
7860 query_addnoqnameproof(query_ctx_t *qctx) {
7861 ns_client_t *client = qctx->client;
7862 isc_buffer_t *dbuf, b;
7863 dns_name_t *fname = NULL;
7864 dns_rdataset_t *neg = NULL, *negsig = NULL;
7865 isc_result_t result = ISC_R_NOMEMORY;
7866
7867 CTRACE(ISC_LOG_DEBUG(3), "query_addnoqnameproof");
7868
7869 if (qctx->noqname == NULL) {
7870 return;
7871 }
7872
7873 dbuf = ns_client_getnamebuf(client);
7874 fname = ns_client_newname(client, dbuf, &b);
7875 neg = ns_client_newrdataset(client);
7876 negsig = ns_client_newrdataset(client);
7877
7878 result = dns_rdataset_getnoqname(qctx->noqname, fname, neg, negsig);
7879 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7880
7881 query_addrrset(qctx, &fname, &neg, &negsig, dbuf,
7882 DNS_SECTION_AUTHORITY);
7883
7884 if ((qctx->noqname->attributes & DNS_RDATASETATTR_CLOSEST) == 0) {
7885 goto cleanup;
7886 }
7887
7888 if (fname == NULL) {
7889 dbuf = ns_client_getnamebuf(client);
7890 fname = ns_client_newname(client, dbuf, &b);
7891 }
7892
7893 if (neg == NULL) {
7894 neg = ns_client_newrdataset(client);
7895 } else if (dns_rdataset_isassociated(neg)) {
7896 dns_rdataset_disassociate(neg);
7897 }
7898
7899 if (negsig == NULL) {
7900 negsig = ns_client_newrdataset(client);
7901 } else if (dns_rdataset_isassociated(negsig)) {
7902 dns_rdataset_disassociate(negsig);
7903 }
7904
7905 result = dns_rdataset_getclosest(qctx->noqname, fname, neg, negsig);
7906 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7907
7908 query_addrrset(qctx, &fname, &neg, &negsig, dbuf,
7909 DNS_SECTION_AUTHORITY);
7910
7911 cleanup:
7912 if (neg != NULL) {
7913 ns_client_putrdataset(client, &neg);
7914 }
7915 if (negsig != NULL) {
7916 ns_client_putrdataset(client, &negsig);
7917 }
7918 if (fname != NULL) {
7919 ns_client_releasename(client, &fname);
7920 }
7921 }
7922
7923 /*%
7924 * Build the response for a query for type ANY.
7925 */
7926 static isc_result_t
7927 query_respond_any(query_ctx_t *qctx) {
7928 bool found = false, hidden = false;
7929 dns_rdatasetiter_t *rdsiter = NULL;
7930 isc_result_t result = ISC_R_UNSET;
7931 dns_rdatatype_t onetype = 0; /* type to use for minimal-any */
7932 isc_buffer_t b;
7933
7934 CCTRACE(ISC_LOG_DEBUG(3), "query_respond_any");
7935
7936 CALL_HOOK(NS_QUERY_RESPOND_ANY_BEGIN, qctx);
7937
7938 result = dns_db_allrdatasets(qctx->db, qctx->node, qctx->version, 0, 0,
7939 &rdsiter);
7940 if (result != ISC_R_SUCCESS) {
7941 CCTRACE(ISC_LOG_ERROR, "query_respond_any: allrdatasets "
7942 "failed");
7943 QUERY_ERROR(qctx, result);
7944 return ns_query_done(qctx);
7945 }
7946
7947 /*
7948 * Calling query_addrrset() with a non-NULL dbuf is going
7949 * to either keep or release the name. We don't want it to
7950 * release fname, since we may have to call query_addrrset()
7951 * more than once. That means we have to call ns_client_keepname()
7952 * now, and pass a NULL dbuf to query_addrrset().
7953 *
7954 * If we do a query_addrrset() below, we must set qctx->fname to
7955 * NULL before leaving this block, otherwise we might try to
7956 * cleanup qctx->fname even though we're using it!
7957 */
7958 ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
7959 qctx->tname = qctx->fname;
7960
7961 result = dns_rdatasetiter_first(rdsiter);
7962 while (result == ISC_R_SUCCESS) {
7963 dns_rdatasetiter_current(rdsiter, qctx->rdataset);
7964
7965 /*
7966 * We found an NS RRset; no need to add one later.
7967 */
7968 if (qctx->qtype == dns_rdatatype_any &&
7969 qctx->rdataset->type == dns_rdatatype_ns)
7970 {
7971 qctx->answer_has_ns = true;
7972 }
7973
7974 /*
7975 * Note: if we're in this function, then qctx->type
7976 * is guaranteed to be ANY, but qctx->qtype (i.e. the
7977 * original type requested) might have been RRSIG or
7978 * SIG; we need to check for that.
7979 */
7980 if (qctx->is_zone && qctx->qtype == dns_rdatatype_any &&
7981 !dns_db_issecure(qctx->db) &&
7982 dns_rdatatype_isdnssec(qctx->rdataset->type))
7983 {
7984 /*
7985 * The zone may be transitioning from insecure
7986 * to secure. Hide DNSSEC records from ANY queries.
7987 */
7988 dns_rdataset_disassociate(qctx->rdataset);
7989 hidden = true;
7990 } else if (qctx->view->minimal_any && !TCP(qctx->client) &&
7991 !WANTDNSSEC(qctx->client) &&
7992 qctx->qtype == dns_rdatatype_any &&
7993 (qctx->rdataset->type == dns_rdatatype_sig ||
7994 qctx->rdataset->type == dns_rdatatype_rrsig))
7995 {
7996 CCTRACE(ISC_LOG_DEBUG(5), "query_respond_any: "
7997 "minimal-any skip signature");
7998 dns_rdataset_disassociate(qctx->rdataset);
7999 } else if (qctx->view->minimal_any && !TCP(qctx->client) &&
8000 onetype != 0 && qctx->rdataset->type != onetype &&
8001 qctx->rdataset->covers != onetype)
8002 {
8003 CCTRACE(ISC_LOG_DEBUG(5), "query_respond_any: "
8004 "minimal-any skip rdataset");
8005 dns_rdataset_disassociate(qctx->rdataset);
8006 } else if ((qctx->qtype == dns_rdatatype_any ||
8007 qctx->rdataset->type == qctx->qtype) &&
8008 qctx->rdataset->type != 0)
8009 {
8010 if (NOQNAME(qctx->rdataset) && WANTDNSSEC(qctx->client))
8011 {
8012 qctx->noqname = qctx->rdataset;
8013 } else {
8014 qctx->noqname = NULL;
8015 }
8016
8017 qctx->rpz_st = qctx->client->query.rpz_st;
8018 if (qctx->rpz_st != NULL &&
8019 qctx->rpz_st->m.policy != DNS_RPZ_POLICY_MISS &&
8020 qctx->rpz_st->m.policy != DNS_RPZ_POLICY_PASSTHRU)
8021 {
8022 qctx->rdataset->ttl =
8023 ISC_MIN(qctx->rdataset->ttl,
8024 qctx->rpz_st->m.ttl);
8025 }
8026
8027 if (!qctx->is_zone && RECURSIONOK(qctx->client)) {
8028 dns_name_t *name;
8029 name = (qctx->fname != NULL) ? qctx->fname
8030 : qctx->tname;
8031 query_prefetch(qctx->client, name,
8032 qctx->rdataset);
8033 }
8034
8035 /*
8036 * Remember the first RRtype we find so we
8037 * can skip others with minimal-any.
8038 */
8039 if (qctx->rdataset->type == dns_rdatatype_sig ||
8040 qctx->rdataset->type == dns_rdatatype_rrsig)
8041 {
8042 onetype = qctx->rdataset->covers;
8043 } else {
8044 onetype = qctx->rdataset->type;
8045 }
8046
8047 query_addrrset(qctx,
8048 (qctx->fname != NULL) ? &qctx->fname
8049 : &qctx->tname,
8050 &qctx->rdataset, NULL, NULL,
8051 DNS_SECTION_ANSWER);
8052
8053 query_addnoqnameproof(qctx);
8054
8055 found = true;
8056 INSIST(qctx->tname != NULL);
8057
8058 /*
8059 * rdataset is non-NULL only in certain
8060 * pathological cases involving DNAMEs.
8061 */
8062 if (qctx->rdataset != NULL) {
8063 ns_client_putrdataset(qctx->client,
8064 &qctx->rdataset);
8065 }
8066
8067 qctx->rdataset = ns_client_newrdataset(qctx->client);
8068 } else {
8069 /*
8070 * We're not interested in this rdataset.
8071 */
8072 dns_rdataset_disassociate(qctx->rdataset);
8073 }
8074
8075 result = dns_rdatasetiter_next(rdsiter);
8076 }
8077
8078 dns_rdatasetiter_destroy(&rdsiter);
8079
8080 if (result != ISC_R_NOMORE) {
8081 CCTRACE(ISC_LOG_ERROR, "query_respond_any: rdataset iterator "
8082 "failed");
8083 QUERY_ERROR(qctx, DNS_R_SERVFAIL);
8084 return ns_query_done(qctx);
8085 }
8086
8087 if (found) {
8088 /*
8089 * Call hook if any answers were found.
8090 * Do this before releasing qctx->fname, in case
8091 * the hook function needs it.
8092 */
8093 CALL_HOOK(NS_QUERY_RESPOND_ANY_FOUND, qctx);
8094 }
8095
8096 if (qctx->fname != NULL) {
8097 dns_message_puttempname(qctx->client->message, &qctx->fname);
8098 }
8099
8100 if (found) {
8101 /*
8102 * At least one matching rdataset was found
8103 */
8104 query_addauth(qctx);
8105 } else if (qctx->qtype == dns_rdatatype_rrsig ||
8106 qctx->qtype == dns_rdatatype_sig)
8107 {
8108 /*
8109 * No matching rdatasets were found, but we got
8110 * here on a search for RRSIG/SIG, so that's okay.
8111 */
8112 if (!qctx->is_zone) {
8113 qctx->authoritative = false;
8114 qctx->client->attributes &= ~NS_CLIENTATTR_RA;
8115 query_addauth(qctx);
8116 return ns_query_done(qctx);
8117 }
8118
8119 if (qctx->qtype == dns_rdatatype_rrsig &&
8120 dns_db_issecure(qctx->db))
8121 {
8122 char namebuf[DNS_NAME_FORMATSIZE];
8123 dns_name_format(qctx->client->query.qname, namebuf,
8124 sizeof(namebuf));
8125 ns_client_log(qctx->client, DNS_LOGCATEGORY_DNSSEC,
8126 NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
8127 "missing signature for %s", namebuf);
8128 }
8129
8130 qctx->fname = ns_client_newname(qctx->client, qctx->dbuf, &b);
8131 return query_sign_nodata(qctx);
8132 } else if (!hidden) {
8133 /*
8134 * No matching rdatasets were found and nothing was
8135 * deliberately hidden: something must have gone wrong.
8136 */
8137 QUERY_ERROR(qctx, DNS_R_SERVFAIL);
8138 }
8139
8140 return ns_query_done(qctx);
8141
8142 cleanup:
8143 return result;
8144 }
8145
8146 /*
8147 * Set the expire time, if requested, when answering from a secondary,
8148 * mirror, or primary zone.
8149 */
8150 static void
8151 query_getexpire(query_ctx_t *qctx) {
8152 dns_zone_t *raw = NULL, *mayberaw;
8153
8154 CCTRACE(ISC_LOG_DEBUG(3), "query_getexpire");
8155
8156 if (qctx->zone == NULL || !qctx->is_zone ||
8157 qctx->qtype != dns_rdatatype_soa ||
8158 qctx->client->query.restarts != 0 ||
8159 (qctx->client->attributes & NS_CLIENTATTR_WANTEXPIRE) == 0)
8160 {
8161 return;
8162 }
8163
8164 dns_zone_getraw(qctx->zone, &raw);
8165 mayberaw = (raw != NULL) ? raw : qctx->zone;
8166
8167 if (dns_zone_gettype(mayberaw) == dns_zone_secondary ||
8168 dns_zone_gettype(mayberaw) == dns_zone_mirror)
8169 {
8170 isc_time_t expiretime;
8171 uint32_t secs;
8172 dns_zone_getexpiretime(qctx->zone, &expiretime);
8173 secs = isc_time_seconds(&expiretime);
8174 if (secs >= qctx->client->now && qctx->result == ISC_R_SUCCESS)
8175 {
8176 qctx->client->attributes |= NS_CLIENTATTR_HAVEEXPIRE;
8177 qctx->client->expire = secs - qctx->client->now;
8178 }
8179 } else if (dns_zone_gettype(mayberaw) == dns_zone_primary) {
8180 isc_result_t result;
8181 dns_rdata_t rdata = DNS_RDATA_INIT;
8182 dns_rdata_soa_t soa;
8183
8184 result = dns_rdataset_first(qctx->rdataset);
8185 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8186
8187 dns_rdataset_current(qctx->rdataset, &rdata);
8188 result = dns_rdata_tostruct(&rdata, &soa, NULL);
8189 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8190
8191 qctx->client->expire = soa.expire;
8192 qctx->client->attributes |= NS_CLIENTATTR_HAVEEXPIRE;
8193 }
8194
8195 if (raw != NULL) {
8196 dns_zone_detach(&raw);
8197 }
8198 }
8199
8200 /*%
8201 * Fill the ANSWER section of a positive response.
8202 */
8203 static isc_result_t
8204 query_addanswer(query_ctx_t *qctx) {
8205 dns_rdataset_t **sigrdatasetp = NULL;
8206 isc_result_t result = ISC_R_UNSET;
8207
8208 CCTRACE(ISC_LOG_DEBUG(3), "query_addanswer");
8209
8210 CALL_HOOK(NS_QUERY_ADDANSWER_BEGIN, qctx);
8211
8212 /*
8213 * On normal lookups, clear any rdatasets that were added on a
8214 * lookup due to stale-answer-client-timeout. Do not clear if we
8215 * are going to refresh the RRset, because the stale contents are
8216 * prioritized.
8217 */
8218 if (QUERY_STALEOK(&qctx->client->query) &&
8219 !QUERY_STALETIMEOUT(&qctx->client->query) && !qctx->refresh_rrset)
8220 {
8221 CCTRACE(ISC_LOG_DEBUG(3), "query_clear_stale");
8222 query_clear_stale(qctx->client);
8223 /*
8224 * We can clear the attribute to prevent redundant clearing
8225 * in subsequent lookups.
8226 */
8227 qctx->client->query.attributes &= ~NS_QUERYATTR_STALEOK;
8228 }
8229
8230 if (qctx->dns64) {
8231 result = query_dns64(qctx);
8232 qctx->noqname = NULL;
8233 dns_rdataset_disassociate(qctx->rdataset);
8234 dns_message_puttemprdataset(qctx->client->message,
8235 &qctx->rdataset);
8236 if (result == ISC_R_NOMORE) {
8237 #ifndef dns64_bis_return_excluded_addresses
8238 if (qctx->dns64_exclude) {
8239 if (!qctx->is_zone) {
8240 return ns_query_done(qctx);
8241 }
8242 /*
8243 * Add a fake SOA record.
8244 */
8245 (void)query_addsoa(qctx, 600,
8246 DNS_SECTION_AUTHORITY);
8247 return ns_query_done(qctx);
8248 }
8249 #endif /* ifndef dns64_bis_return_excluded_addresses */
8250 if (qctx->is_zone) {
8251 return query_nodata(qctx, DNS_R_NXDOMAIN);
8252 } else {
8253 return query_ncache(qctx, DNS_R_NXDOMAIN);
8254 }
8255 } else if (result != ISC_R_SUCCESS) {
8256 qctx->result = result;
8257 return ns_query_done(qctx);
8258 }
8259 } else if (qctx->client->query.dns64_aaaaok != NULL) {
8260 query_filter64(qctx);
8261 ns_client_putrdataset(qctx->client, &qctx->rdataset);
8262 } else {
8263 if (!qctx->is_zone && RECURSIONOK(qctx->client) &&
8264 !QUERY_STALETIMEOUT(&qctx->client->query))
8265 {
8266 query_prefetch(qctx->client, qctx->fname,
8267 qctx->rdataset);
8268 }
8269 if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL) {
8270 sigrdatasetp = &qctx->sigrdataset;
8271 }
8272 query_addrrset(qctx, &qctx->fname, &qctx->rdataset,
8273 sigrdatasetp, qctx->dbuf, DNS_SECTION_ANSWER);
8274 }
8275
8276 return ISC_R_COMPLETE;
8277
8278 cleanup:
8279 return result;
8280 }
8281
8282 /*%
8283 * Build a response for a "normal" query, for a type other than ANY,
8284 * for which we have an answer (either positive or negative).
8285 */
8286 static isc_result_t
8287 query_respond(query_ctx_t *qctx) {
8288 isc_result_t result = ISC_R_UNSET;
8289
8290 CCTRACE(ISC_LOG_DEBUG(3), "query_respond");
8291
8292 /*
8293 * Check to see if the AAAA RRset has non-excluded addresses
8294 * in it. If not look for a A RRset.
8295 */
8296 INSIST(qctx->client->query.dns64_aaaaok == NULL);
8297
8298 if (qctx->qtype == dns_rdatatype_aaaa && !qctx->dns64_exclude &&
8299 !ISC_LIST_EMPTY(qctx->view->dns64) &&
8300 qctx->client->message->rdclass == dns_rdataclass_in &&
8301 !dns64_aaaaok(qctx->client, qctx->rdataset, qctx->sigrdataset))
8302 {
8303 /*
8304 * Look to see if there are A records for this name.
8305 */
8306 qctx->client->query.dns64_ttl = qctx->rdataset->ttl;
8307 SAVE(qctx->client->query.dns64_aaaa, qctx->rdataset);
8308 SAVE(qctx->client->query.dns64_sigaaaa, qctx->sigrdataset);
8309 ns_client_releasename(qctx->client, &qctx->fname);
8310 dns_db_detachnode(qctx->db, &qctx->node);
8311 qctx->type = qctx->qtype = dns_rdatatype_a;
8312 qctx->dns64_exclude = qctx->dns64 = true;
8313
8314 return query_lookup(qctx);
8315 }
8316
8317 /*
8318 * XXX: This hook is meant to be at the top of this function,
8319 * but is postponed until after DNS64 in order to avoid an
8320 * assertion if the hook causes recursion. (When DNS64 also
8321 * becomes a plugin, it will be necessary to find some
8322 * other way to prevent that assertion, since the order in
8323 * which plugins are configured can't be enforced.)
8324 */
8325 CALL_HOOK(NS_QUERY_RESPOND_BEGIN, qctx);
8326
8327 if (NOQNAME(qctx->rdataset) && WANTDNSSEC(qctx->client)) {
8328 qctx->noqname = qctx->rdataset;
8329 } else {
8330 qctx->noqname = NULL;
8331 }
8332
8333 /*
8334 * Special case NS handling
8335 */
8336 if (qctx->is_zone && qctx->qtype == dns_rdatatype_ns) {
8337 /*
8338 * We've already got an NS, no need to add one in
8339 * the authority section
8340 */
8341 if (dns_name_equal(qctx->client->query.qname,
8342 dns_db_origin(qctx->db)))
8343 {
8344 qctx->answer_has_ns = true;
8345 }
8346
8347 /*
8348 * Always add glue for root priming queries, regardless
8349 * of "minimal-responses" setting.
8350 */
8351 if (dns_name_equal(qctx->client->query.qname, dns_rootname)) {
8352 qctx->client->query.attributes &=
8353 ~NS_QUERYATTR_NOADDITIONAL;
8354 dns_db_attach(qctx->db, &qctx->client->query.gluedb);
8355 }
8356 }
8357
8358 /*
8359 * Set expire time
8360 */
8361 query_getexpire(qctx);
8362
8363 result = query_addanswer(qctx);
8364 if (result != ISC_R_COMPLETE) {
8365 return result;
8366 }
8367
8368 query_addnoqnameproof(qctx);
8369
8370 /*
8371 * 'qctx->rdataset' will only be non-NULL here if the ANSWER section of
8372 * the message to be sent to the client already contains an RRset with
8373 * the same owner name and the same type as 'qctx->rdataset'. This
8374 * should never happen, with one exception: when chasing DNAME records,
8375 * one of the DNAME records placed in the ANSWER section may turn out
8376 * to be the final answer to the client's query, but we have no way of
8377 * knowing that until now. In such a case, 'qctx->rdataset' will be
8378 * freed later, so we do not need to free it here.
8379 */
8380 INSIST(qctx->rdataset == NULL || qctx->qtype == dns_rdatatype_dname);
8381
8382 query_addauth(qctx);
8383
8384 return ns_query_done(qctx);
8385
8386 cleanup:
8387 return result;
8388 }
8389
8390 static isc_result_t
8391 query_dns64(query_ctx_t *qctx) {
8392 ns_client_t *client = qctx->client;
8393 dns_aclenv_t *env = client->manager->aclenv;
8394 dns_name_t *name, *mname;
8395 dns_rdata_t *dns64_rdata;
8396 dns_rdata_t rdata = DNS_RDATA_INIT;
8397 dns_rdatalist_t *dns64_rdatalist;
8398 dns_rdataset_t *dns64_rdataset;
8399 dns_rdataset_t *mrdataset;
8400 isc_buffer_t *buffer;
8401 isc_region_t r;
8402 isc_result_t result;
8403 dns_view_t *view = client->view;
8404 isc_netaddr_t netaddr;
8405 dns_dns64_t *dns64;
8406 unsigned int flags = 0;
8407 const dns_section_t section = DNS_SECTION_ANSWER;
8408
8409 /*%
8410 * To the current response for 'qctx->client', add the answer RRset
8411 * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
8412 * owner name '*namep', to the answer section, unless they are
8413 * already there. Also add any pertinent additional data.
8414 *
8415 * If 'qctx->dbuf' is not NULL, then 'qctx->fname' is the name
8416 * whose data is stored 'qctx->dbuf'. In this case,
8417 * query_addrrset() guarantees that when it returns the name
8418 * will either have been kept or released.
8419 */
8420 CTRACE(ISC_LOG_DEBUG(3), "query_dns64");
8421
8422 qctx->qtype = qctx->type = dns_rdatatype_aaaa;
8423
8424 name = qctx->fname;
8425 mname = NULL;
8426 mrdataset = NULL;
8427 buffer = NULL;
8428 dns64_rdata = NULL;
8429 dns64_rdataset = NULL;
8430 dns64_rdatalist = NULL;
8431 result = dns_message_findname(
8432 client->message, section, name, dns_rdatatype_aaaa,
8433 qctx->rdataset->covers, &mname, &mrdataset);
8434 if (result == ISC_R_SUCCESS) {
8435 /*
8436 * We've already got an RRset of the given name and type.
8437 * There's nothing else to do;
8438 */
8439 CTRACE(ISC_LOG_DEBUG(3), "query_dns64: dns_message_findname "
8440 "succeeded: done");
8441 if (qctx->dbuf != NULL) {
8442 ns_client_releasename(client, &qctx->fname);
8443 }
8444 return ISC_R_SUCCESS;
8445 } else if (result == DNS_R_NXDOMAIN) {
8446 /*
8447 * The name doesn't exist.
8448 */
8449 if (qctx->dbuf != NULL) {
8450 ns_client_keepname(client, name, qctx->dbuf);
8451 }
8452 dns_message_addname(client->message, name, section);
8453 qctx->fname = NULL;
8454 mname = name;
8455 } else {
8456 RUNTIME_CHECK(result == DNS_R_NXRRSET);
8457 if (qctx->dbuf != NULL) {
8458 ns_client_releasename(client, &qctx->fname);
8459 }
8460 }
8461
8462 if (qctx->rdataset->trust != dns_trust_secure) {
8463 client->query.attributes &= ~NS_QUERYATTR_SECURE;
8464 }
8465
8466 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
8467
8468 isc_buffer_allocate(client->manager->mctx, &buffer,
8469 view->dns64cnt * 16 *
8470 dns_rdataset_count(qctx->rdataset));
8471 dns_message_gettemprdataset(client->message, &dns64_rdataset);
8472 dns_message_gettemprdatalist(client->message, &dns64_rdatalist);
8473
8474 dns_rdatalist_init(dns64_rdatalist);
8475 dns64_rdatalist->rdclass = dns_rdataclass_in;
8476 dns64_rdatalist->type = dns_rdatatype_aaaa;
8477 if (client->query.dns64_ttl != UINT32_MAX) {
8478 dns64_rdatalist->ttl = ISC_MIN(qctx->rdataset->ttl,
8479 client->query.dns64_ttl);
8480 } else {
8481 dns64_rdatalist->ttl = ISC_MIN(qctx->rdataset->ttl, 600);
8482 }
8483
8484 if (RECURSIONOK(client)) {
8485 flags |= DNS_DNS64_RECURSIVE;
8486 }
8487
8488 /*
8489 * We use the signatures from the A lookup to set DNS_DNS64_DNSSEC
8490 * as this provides a easy way to see if the answer was signed.
8491 */
8492 if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL &&
8493 dns_rdataset_isassociated(qctx->sigrdataset))
8494 {
8495 flags |= DNS_DNS64_DNSSEC;
8496 }
8497
8498 for (result = dns_rdataset_first(qctx->rdataset);
8499 result == ISC_R_SUCCESS;
8500 result = dns_rdataset_next(qctx->rdataset))
8501 {
8502 for (dns64 = ISC_LIST_HEAD(client->view->dns64); dns64 != NULL;
8503 dns64 = dns_dns64_next(dns64))
8504 {
8505 dns_rdataset_current(qctx->rdataset, &rdata);
8506 isc_buffer_availableregion(buffer, &r);
8507 INSIST(r.length >= 16);
8508 result = dns_dns64_aaaafroma(dns64, &netaddr,
8509 client->signer, env, flags,
8510 rdata.data, r.base);
8511 if (result != ISC_R_SUCCESS) {
8512 dns_rdata_reset(&rdata);
8513 continue;
8514 }
8515 isc_buffer_add(buffer, 16);
8516 isc_buffer_remainingregion(buffer, &r);
8517 isc_buffer_forward(buffer, 16);
8518 dns_message_gettemprdata(client->message, &dns64_rdata);
8519 dns_rdata_init(dns64_rdata);
8520 dns_rdata_fromregion(dns64_rdata, dns_rdataclass_in,
8521 dns_rdatatype_aaaa, &r);
8522 ISC_LIST_APPEND(dns64_rdatalist->rdata, dns64_rdata,
8523 link);
8524 dns64_rdata = NULL;
8525 dns_rdata_reset(&rdata);
8526 }
8527 }
8528 if (result != ISC_R_NOMORE) {
8529 goto cleanup;
8530 }
8531
8532 if (ISC_LIST_EMPTY(dns64_rdatalist->rdata)) {
8533 goto cleanup;
8534 }
8535
8536 dns_rdatalist_tordataset(dns64_rdatalist, dns64_rdataset);
8537 dns_rdataset_setownercase(dns64_rdataset, mname);
8538 client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
8539 dns64_rdataset->trust = qctx->rdataset->trust;
8540
8541 query_addtoname(mname, dns64_rdataset);
8542 query_setorder(qctx, mname, dns64_rdataset);
8543
8544 dns64_rdataset = NULL;
8545 dns64_rdatalist = NULL;
8546 dns_message_takebuffer(client->message, &buffer);
8547 inc_stats(client, ns_statscounter_dns64);
8548 result = ISC_R_SUCCESS;
8549
8550 cleanup:
8551 if (buffer != NULL) {
8552 isc_buffer_free(&buffer);
8553 }
8554
8555 if (dns64_rdataset != NULL) {
8556 dns_message_puttemprdataset(client->message, &dns64_rdataset);
8557 }
8558
8559 if (dns64_rdatalist != NULL) {
8560 for (dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata);
8561 dns64_rdata != NULL;
8562 dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata))
8563 {
8564 ISC_LIST_UNLINK(dns64_rdatalist->rdata, dns64_rdata,
8565 link);
8566 dns_message_puttemprdata(client->message, &dns64_rdata);
8567 }
8568 dns_message_puttemprdatalist(client->message, &dns64_rdatalist);
8569 }
8570
8571 CTRACE(ISC_LOG_DEBUG(3), "query_dns64: done");
8572 return result;
8573 }
8574
8575 static void
8576 query_filter64(query_ctx_t *qctx) {
8577 ns_client_t *client = qctx->client;
8578 dns_name_t *name, *mname;
8579 dns_rdata_t *myrdata;
8580 dns_rdata_t rdata = DNS_RDATA_INIT;
8581 dns_rdatalist_t *myrdatalist;
8582 dns_rdataset_t *myrdataset;
8583 isc_buffer_t *buffer;
8584 isc_region_t r;
8585 isc_result_t result;
8586 unsigned int i;
8587 const dns_section_t section = DNS_SECTION_ANSWER;
8588
8589 CTRACE(ISC_LOG_DEBUG(3), "query_filter64");
8590
8591 INSIST(client->query.dns64_aaaaok != NULL);
8592 INSIST(client->query.dns64_aaaaoklen ==
8593 dns_rdataset_count(qctx->rdataset));
8594
8595 name = qctx->fname;
8596 mname = NULL;
8597 buffer = NULL;
8598 myrdata = NULL;
8599 myrdataset = NULL;
8600 myrdatalist = NULL;
8601 result = dns_message_findname(
8602 client->message, section, name, dns_rdatatype_aaaa,
8603 qctx->rdataset->covers, &mname, &myrdataset);
8604 if (result == ISC_R_SUCCESS) {
8605 /*
8606 * We've already got an RRset of the given name and type.
8607 * There's nothing else to do;
8608 */
8609 CTRACE(ISC_LOG_DEBUG(3), "query_filter64: dns_message_findname "
8610 "succeeded: done");
8611 if (qctx->dbuf != NULL) {
8612 ns_client_releasename(client, &qctx->fname);
8613 }
8614 return;
8615 } else if (result == DNS_R_NXDOMAIN) {
8616 mname = name;
8617 qctx->fname = NULL;
8618 } else {
8619 RUNTIME_CHECK(result == DNS_R_NXRRSET);
8620 if (qctx->dbuf != NULL) {
8621 ns_client_releasename(client, &qctx->fname);
8622 }
8623 qctx->dbuf = NULL;
8624 }
8625
8626 if (qctx->rdataset->trust != dns_trust_secure) {
8627 client->query.attributes &= ~NS_QUERYATTR_SECURE;
8628 }
8629
8630 isc_buffer_allocate(client->manager->mctx, &buffer,
8631 16 * dns_rdataset_count(qctx->rdataset));
8632 dns_message_gettemprdataset(client->message, &myrdataset);
8633 dns_message_gettemprdatalist(client->message, &myrdatalist);
8634
8635 dns_rdatalist_init(myrdatalist);
8636 myrdatalist->rdclass = dns_rdataclass_in;
8637 myrdatalist->type = dns_rdatatype_aaaa;
8638 myrdatalist->ttl = qctx->rdataset->ttl;
8639
8640 i = 0;
8641 for (result = dns_rdataset_first(qctx->rdataset);
8642 result == ISC_R_SUCCESS;
8643 result = dns_rdataset_next(qctx->rdataset))
8644 {
8645 if (!client->query.dns64_aaaaok[i++]) {
8646 continue;
8647 }
8648 dns_rdataset_current(qctx->rdataset, &rdata);
8649 INSIST(rdata.length == 16);
8650 isc_buffer_putmem(buffer, rdata.data, rdata.length);
8651 isc_buffer_remainingregion(buffer, &r);
8652 isc_buffer_forward(buffer, rdata.length);
8653 dns_message_gettemprdata(client->message, &myrdata);
8654 dns_rdata_init(myrdata);
8655 dns_rdata_fromregion(myrdata, dns_rdataclass_in,
8656 dns_rdatatype_aaaa, &r);
8657 ISC_LIST_APPEND(myrdatalist->rdata, myrdata, link);
8658 myrdata = NULL;
8659 dns_rdata_reset(&rdata);
8660 }
8661 if (result != ISC_R_NOMORE) {
8662 goto cleanup;
8663 }
8664
8665 dns_rdatalist_tordataset(myrdatalist, myrdataset);
8666 dns_rdataset_setownercase(myrdataset, name);
8667 client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
8668 if (mname == name) {
8669 if (qctx->dbuf != NULL) {
8670 ns_client_keepname(client, name, qctx->dbuf);
8671 }
8672 dns_message_addname(client->message, name, section);
8673 qctx->dbuf = NULL;
8674 }
8675 myrdataset->trust = qctx->rdataset->trust;
8676
8677 query_addtoname(mname, myrdataset);
8678 query_setorder(qctx, mname, myrdataset);
8679
8680 myrdataset = NULL;
8681 myrdatalist = NULL;
8682 dns_message_takebuffer(client->message, &buffer);
8683
8684 cleanup:
8685 if (buffer != NULL) {
8686 isc_buffer_free(&buffer);
8687 }
8688
8689 if (myrdataset != NULL) {
8690 dns_message_puttemprdataset(client->message, &myrdataset);
8691 }
8692
8693 if (myrdatalist != NULL) {
8694 for (myrdata = ISC_LIST_HEAD(myrdatalist->rdata);
8695 myrdata != NULL;
8696 myrdata = ISC_LIST_HEAD(myrdatalist->rdata))
8697 {
8698 ISC_LIST_UNLINK(myrdatalist->rdata, myrdata, link);
8699 dns_message_puttemprdata(client->message, &myrdata);
8700 }
8701 dns_message_puttemprdatalist(client->message, &myrdatalist);
8702 }
8703
8704 if (qctx->dbuf != NULL) {
8705 ns_client_releasename(client, &name);
8706 }
8707
8708 CTRACE(ISC_LOG_DEBUG(3), "query_filter64: done");
8709 }
8710
8711 /*%
8712 * Handle the case of a name not being found in a database lookup.
8713 * Called from query_gotanswer(). Passes off processing to
8714 * query_delegation() for a root referral if appropriate.
8715 */
8716 static isc_result_t
8717 query_notfound(query_ctx_t *qctx) {
8718 isc_result_t result = ISC_R_UNSET;
8719
8720 CCTRACE(ISC_LOG_DEBUG(3), "query_notfound");
8721
8722 CALL_HOOK(NS_QUERY_NOTFOUND_BEGIN, qctx);
8723
8724 INSIST(!qctx->is_zone);
8725
8726 if (qctx->db != NULL) {
8727 dns_db_detach(&qctx->db);
8728 }
8729
8730 /*
8731 * If the cache doesn't even have the root NS,
8732 * try to get that from the hints DB.
8733 */
8734 if (qctx->view->hints != NULL) {
8735 dns_clientinfomethods_t cm;
8736 dns_clientinfo_t ci;
8737
8738 dns_clientinfomethods_init(&cm, ns_client_sourceip);
8739 dns_clientinfo_init(&ci, qctx->client, NULL);
8740
8741 dns_db_attach(qctx->view->hints, &qctx->db);
8742 result = dns_db_findext(qctx->db, dns_rootname, NULL,
8743 dns_rdatatype_ns, 0, qctx->client->now,
8744 &qctx->node, qctx->fname, &cm, &ci,
8745 qctx->rdataset, qctx->sigrdataset);
8746 } else {
8747 /* We have no hints. */
8748 result = ISC_R_FAILURE;
8749 }
8750 if (result != ISC_R_SUCCESS) {
8751 /*
8752 * Nonsensical root hints may require cleanup.
8753 */
8754 qctx_clean(qctx);
8755
8756 /*
8757 * We don't have any root server hints, but
8758 * we may have working forwarders, so try to
8759 * recurse anyway.
8760 */
8761 if (RECURSIONOK(qctx->client)) {
8762 INSIST(!REDIRECT(qctx->client));
8763 result = ns_query_recurse(qctx->client, qctx->qtype,
8764 qctx->client->query.qname,
8765 NULL, NULL, qctx->resuming);
8766 if (result == ISC_R_SUCCESS) {
8767 CALL_HOOK(NS_QUERY_NOTFOUND_RECURSE, qctx);
8768 qctx->client->query.attributes |=
8769 NS_QUERYATTR_RECURSING;
8770
8771 if (qctx->dns64) {
8772 qctx->client->query.attributes |=
8773 NS_QUERYATTR_DNS64;
8774 }
8775 if (qctx->dns64_exclude) {
8776 qctx->client->query.attributes |=
8777 NS_QUERYATTR_DNS64EXCLUDE;
8778 }
8779 } else if (query_usestale(qctx, result)) {
8780 /*
8781 * If serve-stale is enabled, query_usestale()
8782 * already set up 'qctx' for looking up a
8783 * stale response.
8784 */
8785 return query_lookup(qctx);
8786 } else {
8787 QUERY_ERROR(qctx, result);
8788 }
8789 return ns_query_done(qctx);
8790 } else {
8791 /* Unable to give root server referral. */
8792 CCTRACE(ISC_LOG_ERROR, "unable to give root server "
8793 "referral");
8794 QUERY_ERROR(qctx, result);
8795 return ns_query_done(qctx);
8796 }
8797 }
8798
8799 return query_delegation(qctx);
8800
8801 cleanup:
8802 return result;
8803 }
8804
8805 /*%
8806 * We have a delegation but recursion is not allowed, so return the delegation
8807 * to the client.
8808 */
8809 static isc_result_t
8810 query_prepare_delegation_response(query_ctx_t *qctx) {
8811 isc_result_t result = ISC_R_UNSET;
8812 dns_rdataset_t **sigrdatasetp = NULL;
8813 bool detach = false;
8814
8815 CALL_HOOK(NS_QUERY_PREP_DELEGATION_BEGIN, qctx);
8816
8817 /*
8818 * qctx->fname could be released in query_addrrset(), so save a copy of
8819 * it here in case we need it.
8820 */
8821 dns_fixedname_init(&qctx->dsname);
8822 dns_name_copy(qctx->fname, dns_fixedname_name(&qctx->dsname));
8823
8824 /*
8825 * This is the best answer.
8826 */
8827 qctx->client->query.isreferral = true;
8828
8829 if (!dns_db_iscache(qctx->db) && qctx->client->query.gluedb == NULL) {
8830 dns_db_attach(qctx->db, &qctx->client->query.gluedb);
8831 detach = true;
8832 }
8833
8834 /*
8835 * We must ensure NOADDITIONAL is off, because the generation of
8836 * additional data is required in delegations.
8837 */
8838 qctx->client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL;
8839 if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL) {
8840 sigrdatasetp = &qctx->sigrdataset;
8841 }
8842 query_addrrset(qctx, &qctx->fname, &qctx->rdataset, sigrdatasetp,
8843 qctx->dbuf, DNS_SECTION_AUTHORITY);
8844 if (detach) {
8845 dns_db_detach(&qctx->client->query.gluedb);
8846 }
8847
8848 /*
8849 * Add DS/NSEC(3) record(s) if needed.
8850 */
8851 query_addds(qctx);
8852
8853 return ns_query_done(qctx);
8854
8855 cleanup:
8856 return result;
8857 }
8858
8859 /*%
8860 * Handle a delegation response from an authoritative lookup. This
8861 * may trigger additional lookups, e.g. from the cache database to
8862 * see if we have a better answer; if that is not allowed, return the
8863 * delegation to the client and call ns_query_done().
8864 */
8865 static isc_result_t
8866 query_zone_delegation(query_ctx_t *qctx) {
8867 isc_result_t result = ISC_R_UNSET;
8868
8869 CALL_HOOK(NS_QUERY_ZONE_DELEGATION_BEGIN, qctx);
8870
8871 /*
8872 * If the query type is DS, look to see if we are
8873 * authoritative for the child zone
8874 */
8875 if (!RECURSIONOK(qctx->client) &&
8876 (qctx->options.noexact && qctx->qtype == dns_rdatatype_ds))
8877 {
8878 dns_db_t *tdb = NULL;
8879 dns_zone_t *tzone = NULL;
8880 dns_dbversion_t *tversion = NULL;
8881 dns_getdb_options_t options = { .partial = true };
8882 result = query_getzonedb(qctx->client,
8883 qctx->client->query.qname, qctx->qtype,
8884 options, &tzone, &tdb, &tversion);
8885 if (result != ISC_R_SUCCESS) {
8886 if (tdb != NULL) {
8887 dns_db_detach(&tdb);
8888 }
8889 if (tzone != NULL) {
8890 dns_zone_detach(&tzone);
8891 }
8892 } else {
8893 qctx->options.noexact = false;
8894 ns_client_putrdataset(qctx->client, &qctx->rdataset);
8895 if (qctx->sigrdataset != NULL) {
8896 ns_client_putrdataset(qctx->client,
8897 &qctx->sigrdataset);
8898 }
8899 if (qctx->fname != NULL) {
8900 ns_client_releasename(qctx->client,
8901 &qctx->fname);
8902 }
8903 if (qctx->node != NULL) {
8904 dns_db_detachnode(qctx->db, &qctx->node);
8905 }
8906 if (qctx->db != NULL) {
8907 dns_db_detach(&qctx->db);
8908 }
8909 if (qctx->zone != NULL) {
8910 dns_zone_detach(&qctx->zone);
8911 }
8912 qctx->version = NULL;
8913 RESTORE(qctx->version, tversion);
8914 RESTORE(qctx->db, tdb);
8915 RESTORE(qctx->zone, tzone);
8916 qctx->authoritative = true;
8917
8918 return query_lookup(qctx);
8919 }
8920 }
8921
8922 if (USECACHE(qctx->client) &&
8923 (RECURSIONOK(qctx->client) ||
8924 (qctx->zone != NULL &&
8925 dns_zone_gettype(qctx->zone) == dns_zone_mirror)))
8926 {
8927 /*
8928 * We might have a better answer or delegation in the
8929 * cache. We'll remember the current values of fname,
8930 * rdataset, and sigrdataset. We'll then go looking for
8931 * QNAME in the cache. If we find something better, we'll
8932 * use it instead. If not, then query_lookup() calls
8933 * query_notfound() which calls query_delegation(), and
8934 * we'll restore these values there.
8935 */
8936 ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
8937 SAVE(qctx->zdb, qctx->db);
8938 SAVE(qctx->znode, qctx->node);
8939 SAVE(qctx->zfname, qctx->fname);
8940 SAVE(qctx->zversion, qctx->version);
8941 SAVE(qctx->zrdataset, qctx->rdataset);
8942 SAVE(qctx->zsigrdataset, qctx->sigrdataset);
8943 dns_db_attach(qctx->view->cachedb, &qctx->db);
8944 qctx->is_zone = false;
8945
8946 /*
8947 * Since 'qctx->is_zone' is now false, we should reconsider
8948 * setting the 'stalefirst' option, which is usually set in
8949 * the beginning in ns__query_start().
8950 */
8951 qctx->options.stalefirst =
8952 (qctx->view->staleanswerclienttimeout == 0 &&
8953 dns_view_staleanswerenabled(qctx->view));
8954
8955 result = query_lookup(qctx);
8956
8957 /*
8958 * After fetch completes, this option is not expected to be set.
8959 */
8960 qctx->options.stalefirst = false;
8961
8962 return result;
8963 }
8964
8965 return query_prepare_delegation_response(qctx);
8966
8967 cleanup:
8968 return result;
8969 }
8970
8971 /*%
8972 * Handle delegation responses, including root referrals.
8973 *
8974 * If the delegation was returned from authoritative data,
8975 * call query_zone_delgation(). Otherwise, we can start
8976 * recursion if allowed; or else return the delegation to the
8977 * client and call ns_query_done().
8978 */
8979 static isc_result_t
8980 query_delegation(query_ctx_t *qctx) {
8981 isc_result_t result = ISC_R_UNSET;
8982
8983 CCTRACE(ISC_LOG_DEBUG(3), "query_delegation");
8984
8985 CALL_HOOK(NS_QUERY_DELEGATION_BEGIN, qctx);
8986
8987 qctx->authoritative = false;
8988
8989 if (qctx->is_zone) {
8990 return query_zone_delegation(qctx);
8991 }
8992
8993 if (qctx->zfname != NULL &&
8994 (!dns_name_issubdomain(qctx->fname, qctx->zfname) ||
8995 (qctx->is_staticstub_zone &&
8996 dns_name_equal(qctx->fname, qctx->zfname))))
8997 {
8998 /*
8999 * In the following cases use "authoritative"
9000 * data instead of the cache delegation:
9001 * 1. We've already got a delegation from
9002 * authoritative data, and it is better
9003 * than what we found in the cache.
9004 * (See the comment above.)
9005 * 2. The query name matches the origin name
9006 * of a static-stub zone. This needs to be
9007 * considered for the case where the NS of
9008 * the static-stub zone and the cached NS
9009 * are different. We still need to contact
9010 * the nameservers configured in the
9011 * static-stub zone.
9012 */
9013 ns_client_releasename(qctx->client, &qctx->fname);
9014
9015 /*
9016 * We've already done ns_client_keepname() on
9017 * qctx->zfname, so we must set dbuf to NULL to
9018 * prevent query_addrrset() from trying to
9019 * call ns_client_keepname() again.
9020 */
9021 qctx->dbuf = NULL;
9022 ns_client_putrdataset(qctx->client, &qctx->rdataset);
9023 if (qctx->sigrdataset != NULL) {
9024 ns_client_putrdataset(qctx->client, &qctx->sigrdataset);
9025 }
9026 qctx->version = NULL;
9027
9028 dns_db_detachnode(qctx->db, &qctx->node);
9029 dns_db_detach(&qctx->db);
9030 RESTORE(qctx->db, qctx->zdb);
9031 RESTORE(qctx->node, qctx->znode);
9032 RESTORE(qctx->fname, qctx->zfname);
9033 RESTORE(qctx->version, qctx->zversion);
9034 RESTORE(qctx->rdataset, qctx->zrdataset);
9035 RESTORE(qctx->sigrdataset, qctx->zsigrdataset);
9036 }
9037
9038 result = query_delegation_recurse(qctx);
9039 if (result != ISC_R_COMPLETE) {
9040 return result;
9041 }
9042
9043 return query_prepare_delegation_response(qctx);
9044
9045 cleanup:
9046 return result;
9047 }
9048
9049 /*%
9050 * Handle recursive queries that are triggered as part of the
9051 * delegation process.
9052 */
9053 static isc_result_t
9054 query_delegation_recurse(query_ctx_t *qctx) {
9055 isc_result_t result = ISC_R_UNSET;
9056 dns_name_t *qname = qctx->client->query.qname;
9057
9058 CCTRACE(ISC_LOG_DEBUG(3), "query_delegation_recurse");
9059
9060 if (!RECURSIONOK(qctx->client)) {
9061 return ISC_R_COMPLETE;
9062 }
9063
9064 CALL_HOOK(NS_QUERY_DELEGATION_RECURSE_BEGIN, qctx);
9065
9066 /*
9067 * We have a delegation and recursion is allowed,
9068 * so we call ns_query_recurse() to follow it.
9069 * This phase of the query processing is done;
9070 * we'll resume via fetch_callback() and
9071 * query_resume() when the recursion is complete.
9072 */
9073
9074 INSIST(!REDIRECT(qctx->client));
9075
9076 if (dns_rdatatype_atparent(qctx->type)) {
9077 /*
9078 * Parent is authoritative for this RDATA type (i.e. DS).
9079 */
9080 result = ns_query_recurse(qctx->client, qctx->qtype, qname,
9081 NULL, NULL, qctx->resuming);
9082 } else if (qctx->dns64) {
9083 /*
9084 * Look up an A record so we can synthesize DNS64.
9085 */
9086 result = ns_query_recurse(qctx->client, dns_rdatatype_a, qname,
9087 NULL, NULL, qctx->resuming);
9088 } else {
9089 /*
9090 * Any other recursion.
9091 */
9092 result = ns_query_recurse(qctx->client, qctx->qtype, qname,
9093 qctx->fname, qctx->rdataset,
9094 qctx->resuming);
9095 }
9096
9097 if (result == ISC_R_SUCCESS) {
9098 qctx->client->query.attributes |= NS_QUERYATTR_RECURSING;
9099 if (qctx->dns64) {
9100 qctx->client->query.attributes |= NS_QUERYATTR_DNS64;
9101 }
9102 if (qctx->dns64_exclude) {
9103 qctx->client->query.attributes |=
9104 NS_QUERYATTR_DNS64EXCLUDE;
9105 }
9106 } else if (query_usestale(qctx, result)) {
9107 /*
9108 * If serve-stale is enabled, query_usestale() already set up
9109 * 'qctx' for looking up a stale response.
9110 */
9111 return query_lookup(qctx);
9112 } else {
9113 QUERY_ERROR(qctx, result);
9114 }
9115
9116 return ns_query_done(qctx);
9117
9118 cleanup:
9119 return result;
9120 }
9121
9122 /*%
9123 * Add DS/NSEC(3) record(s) if needed.
9124 */
9125 static void
9126 query_addds(query_ctx_t *qctx) {
9127 ns_client_t *client = qctx->client;
9128 dns_fixedname_t fixed;
9129 dns_name_t *fname = NULL;
9130 dns_name_t *rname = NULL;
9131 dns_name_t *name;
9132 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
9133 isc_buffer_t *dbuf, b;
9134 isc_result_t result;
9135 unsigned int count;
9136
9137 CTRACE(ISC_LOG_DEBUG(3), "query_addds");
9138
9139 /*
9140 * DS not needed.
9141 */
9142 if (!WANTDNSSEC(client)) {
9143 return;
9144 }
9145
9146 /*
9147 * We'll need some resources...
9148 */
9149 rdataset = ns_client_newrdataset(client);
9150 sigrdataset = ns_client_newrdataset(client);
9151
9152 /*
9153 * Look for the DS record, which may or may not be present.
9154 */
9155 result = dns_db_findrdataset(qctx->db, qctx->node, qctx->version,
9156 dns_rdatatype_ds, 0, client->now, rdataset,
9157 sigrdataset);
9158 /*
9159 * If we didn't find it, look for an NSEC.
9160 */
9161 if (result == ISC_R_NOTFOUND) {
9162 result = dns_db_findrdataset(
9163 qctx->db, qctx->node, qctx->version, dns_rdatatype_nsec,
9164 0, client->now, rdataset, sigrdataset);
9165 }
9166 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
9167 goto addnsec3;
9168 }
9169 if (!dns_rdataset_isassociated(rdataset) ||
9170 !dns_rdataset_isassociated(sigrdataset))
9171 {
9172 goto addnsec3;
9173 }
9174
9175 /*
9176 * We've already added the NS record, so if the name's not there,
9177 * we have other problems.
9178 */
9179 result = dns_message_firstname(client->message, DNS_SECTION_AUTHORITY);
9180 if (result != ISC_R_SUCCESS) {
9181 goto cleanup;
9182 }
9183
9184 /*
9185 * Find the delegation in the response message - it is not necessarily
9186 * the first name in the AUTHORITY section when wildcard processing is
9187 * involved.
9188 */
9189 while (result == ISC_R_SUCCESS) {
9190 rname = NULL;
9191 dns_message_currentname(client->message, DNS_SECTION_AUTHORITY,
9192 &rname);
9193 result = dns_message_findtype(rname, dns_rdatatype_ns, 0, NULL);
9194 if (result == ISC_R_SUCCESS) {
9195 break;
9196 }
9197 result = dns_message_nextname(client->message,
9198 DNS_SECTION_AUTHORITY);
9199 }
9200
9201 if (result != ISC_R_SUCCESS) {
9202 goto cleanup;
9203 }
9204
9205 /*
9206 * Add the relevant RRset (DS or NSEC) to the delegation.
9207 */
9208 query_addrrset(qctx, &rname, &rdataset, &sigrdataset, NULL,
9209 DNS_SECTION_AUTHORITY);
9210 goto cleanup;
9211
9212 addnsec3:
9213 if (!dns_db_iszone(qctx->db)) {
9214 goto cleanup;
9215 }
9216 /*
9217 * Add the NSEC3 which proves the DS does not exist.
9218 */
9219 dbuf = ns_client_getnamebuf(client);
9220 fname = ns_client_newname(client, dbuf, &b);
9221 dns_fixedname_init(&fixed);
9222 if (dns_rdataset_isassociated(rdataset)) {
9223 dns_rdataset_disassociate(rdataset);
9224 }
9225 if (dns_rdataset_isassociated(sigrdataset)) {
9226 dns_rdataset_disassociate(sigrdataset);
9227 }
9228 name = dns_fixedname_name(&qctx->dsname);
9229 query_findclosestnsec3(name, qctx->db, qctx->version, client, rdataset,
9230 sigrdataset, fname, true,
9231 dns_fixedname_name(&fixed));
9232 if (!dns_rdataset_isassociated(rdataset)) {
9233 goto cleanup;
9234 }
9235 query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf,
9236 DNS_SECTION_AUTHORITY);
9237 /*
9238 * Did we find the closest provable encloser instead?
9239 * If so add the nearest to the closest provable encloser.
9240 */
9241 if (!dns_name_equal(name, dns_fixedname_name(&fixed))) {
9242 count = dns_name_countlabels(dns_fixedname_name(&fixed)) + 1;
9243 dns_name_getlabelsequence(name,
9244 dns_name_countlabels(name) - count,
9245 count, dns_fixedname_name(&fixed));
9246 fixfname(client, &fname, &dbuf, &b);
9247 fixrdataset(client, &rdataset);
9248 fixrdataset(client, &sigrdataset);
9249 if (fname == NULL || rdataset == NULL || sigrdataset == NULL) {
9250 goto cleanup;
9251 }
9252 query_findclosestnsec3(dns_fixedname_name(&fixed), qctx->db,
9253 qctx->version, client, rdataset,
9254 sigrdataset, fname, false, NULL);
9255 if (!dns_rdataset_isassociated(rdataset)) {
9256 goto cleanup;
9257 }
9258 query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf,
9259 DNS_SECTION_AUTHORITY);
9260 }
9261
9262 cleanup:
9263 if (rdataset != NULL) {
9264 ns_client_putrdataset(client, &rdataset);
9265 }
9266 if (sigrdataset != NULL) {
9267 ns_client_putrdataset(client, &sigrdataset);
9268 }
9269 if (fname != NULL) {
9270 ns_client_releasename(client, &fname);
9271 }
9272 }
9273
9274 /*%
9275 * Handle authoritative NOERROR/NODATA responses.
9276 */
9277 static isc_result_t
9278 query_nodata(query_ctx_t *qctx, isc_result_t res) {
9279 isc_result_t result = res;
9280
9281 CCTRACE(ISC_LOG_DEBUG(3), "query_nodata");
9282
9283 CALL_HOOK(NS_QUERY_NODATA_BEGIN, qctx);
9284
9285 #ifdef dns64_bis_return_excluded_addresses
9286 if (qctx->dns64)
9287 #else /* ifdef dns64_bis_return_excluded_addresses */
9288 if (qctx->dns64 && !qctx->dns64_exclude)
9289 #endif /* ifdef dns64_bis_return_excluded_addresses */
9290 {
9291 isc_buffer_t b;
9292 /*
9293 * Restore the answers from the previous AAAA lookup.
9294 */
9295 if (qctx->rdataset != NULL) {
9296 ns_client_putrdataset(qctx->client, &qctx->rdataset);
9297 }
9298 if (qctx->sigrdataset != NULL) {
9299 ns_client_putrdataset(qctx->client, &qctx->sigrdataset);
9300 }
9301 RESTORE(qctx->rdataset, qctx->client->query.dns64_aaaa);
9302 RESTORE(qctx->sigrdataset, qctx->client->query.dns64_sigaaaa);
9303 if (qctx->fname == NULL) {
9304 qctx->dbuf = ns_client_getnamebuf(qctx->client);
9305 qctx->fname = ns_client_newname(qctx->client,
9306 qctx->dbuf, &b);
9307 }
9308 dns_name_copy(qctx->client->query.qname, qctx->fname);
9309 qctx->dns64 = false;
9310 #ifdef dns64_bis_return_excluded_addresses
9311 /*
9312 * Resume the diverted processing of the AAAA response?
9313 */
9314 if (qctx->dns64_exclude) {
9315 return query_prepresponse(qctx);
9316 }
9317 #endif /* ifdef dns64_bis_return_excluded_addresses */
9318 } else if ((result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) &&
9319 !ISC_LIST_EMPTY(qctx->view->dns64) && !qctx->nxrewrite &&
9320 qctx->client->message->rdclass == dns_rdataclass_in &&
9321 qctx->qtype == dns_rdatatype_aaaa)
9322 {
9323 /*
9324 * Look to see if there are A records for this name.
9325 */
9326 switch (result) {
9327 case DNS_R_NCACHENXRRSET:
9328 /*
9329 * This is from the negative cache; if the ttl is
9330 * zero, we need to work out whether we have just
9331 * decremented to zero or there was no negative
9332 * cache ttl in the answer.
9333 */
9334 if (qctx->rdataset->ttl != 0) {
9335 qctx->client->query.dns64_ttl =
9336 qctx->rdataset->ttl;
9337 break;
9338 }
9339 if (dns_rdataset_first(qctx->rdataset) == ISC_R_SUCCESS)
9340 {
9341 qctx->client->query.dns64_ttl = 0;
9342 }
9343 break;
9344 case DNS_R_NXRRSET:
9345 qctx->client->query.dns64_ttl =
9346 dns64_ttl(qctx->db, qctx->version);
9347 break;
9348 default:
9349 UNREACHABLE();
9350 }
9351
9352 SAVE(qctx->client->query.dns64_aaaa, qctx->rdataset);
9353 SAVE(qctx->client->query.dns64_sigaaaa, qctx->sigrdataset);
9354 ns_client_releasename(qctx->client, &qctx->fname);
9355 dns_db_detachnode(qctx->db, &qctx->node);
9356 qctx->type = qctx->qtype = dns_rdatatype_a;
9357 qctx->dns64 = true;
9358 return query_lookup(qctx);
9359 }
9360
9361 if (qctx->is_zone) {
9362 return query_sign_nodata(qctx);
9363 } else {
9364 /*
9365 * We don't call query_addrrset() because we don't need any
9366 * of its extra features (and things would probably break!).
9367 */
9368 if (dns_rdataset_isassociated(qctx->rdataset)) {
9369 ns_client_keepname(qctx->client, qctx->fname,
9370 qctx->dbuf);
9371 dns_message_addname(qctx->client->message, qctx->fname,
9372 DNS_SECTION_AUTHORITY);
9373 ISC_LIST_APPEND(qctx->fname->list, qctx->rdataset,
9374 link);
9375 qctx->fname = NULL;
9376 qctx->rdataset = NULL;
9377 }
9378 }
9379
9380 return ns_query_done(qctx);
9381
9382 cleanup:
9383 return result;
9384 }
9385
9386 /*%
9387 * Add RRSIGs for NOERROR/NODATA responses when answering authoritatively.
9388 */
9389 isc_result_t
9390 query_sign_nodata(query_ctx_t *qctx) {
9391 isc_result_t result;
9392
9393 CCTRACE(ISC_LOG_DEBUG(3), "query_sign_nodata");
9394
9395 /*
9396 * Look for a NSEC3 record if we don't have a NSEC record.
9397 */
9398 if (qctx->redirected) {
9399 return ns_query_done(qctx);
9400 }
9401 if (!dns_rdataset_isassociated(qctx->rdataset) &&
9402 WANTDNSSEC(qctx->client))
9403 {
9404 if (!qctx->fname->attributes.wildcard) {
9405 dns_name_t *found;
9406 dns_name_t *qname;
9407 dns_fixedname_t fixed;
9408 isc_buffer_t b;
9409
9410 found = dns_fixedname_initname(&fixed);
9411 qname = qctx->client->query.qname;
9412
9413 query_findclosestnsec3(qname, qctx->db, qctx->version,
9414 qctx->client, qctx->rdataset,
9415 qctx->sigrdataset, qctx->fname,
9416 true, found);
9417 /*
9418 * Did we find the closest provable encloser
9419 * instead? If so add the nearest to the
9420 * closest provable encloser.
9421 */
9422 if (dns_rdataset_isassociated(qctx->rdataset) &&
9423 !dns_name_equal(qname, found) &&
9424 (((qctx->client->manager->sctx->options &
9425 NS_SERVER_NONEAREST) == 0) ||
9426 qctx->qtype == dns_rdatatype_ds))
9427 {
9428 unsigned int count;
9429 unsigned int skip;
9430
9431 /*
9432 * Add the closest provable encloser.
9433 */
9434 query_addrrset(qctx, &qctx->fname,
9435 &qctx->rdataset,
9436 &qctx->sigrdataset, qctx->dbuf,
9437 DNS_SECTION_AUTHORITY);
9438
9439 count = dns_name_countlabels(found) + 1;
9440 skip = dns_name_countlabels(qname) - count;
9441 dns_name_getlabelsequence(qname, skip, count,
9442 found);
9443
9444 fixfname(qctx->client, &qctx->fname,
9445 &qctx->dbuf, &b);
9446 fixrdataset(qctx->client, &qctx->rdataset);
9447 fixrdataset(qctx->client, &qctx->sigrdataset);
9448 if (qctx->fname == NULL ||
9449 qctx->rdataset == NULL ||
9450 qctx->sigrdataset == NULL)
9451 {
9452 CCTRACE(ISC_LOG_ERROR, "query_sign_"
9453 "nodata: "
9454 "failure "
9455 "getting "
9456 "closest "
9457 "encloser");
9458 QUERY_ERROR(qctx, ISC_R_NOMEMORY);
9459 return ns_query_done(qctx);
9460 }
9461 /*
9462 * 'nearest' doesn't exist so
9463 * 'exist' is set to false.
9464 */
9465 query_findclosestnsec3(
9466 found, qctx->db, qctx->version,
9467 qctx->client, qctx->rdataset,
9468 qctx->sigrdataset, qctx->fname, false,
9469 NULL);
9470 }
9471 } else {
9472 ns_client_releasename(qctx->client, &qctx->fname);
9473 query_addwildcardproof(qctx, false, true);
9474 }
9475 }
9476 if (dns_rdataset_isassociated(qctx->rdataset)) {
9477 /*
9478 * If we've got a NSEC record, we need to save the
9479 * name now because we're going call query_addsoa()
9480 * below, and it needs to use the name buffer.
9481 */
9482 ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
9483 } else if (qctx->fname != NULL) {
9484 /*
9485 * We're not going to use fname, and need to release
9486 * our hold on the name buffer so query_addsoa()
9487 * may use it.
9488 */
9489 ns_client_releasename(qctx->client, &qctx->fname);
9490 }
9491
9492 /*
9493 * The RPZ SOA has already been added to the additional section
9494 * if this was an RPZ rewrite, but if it wasn't, add it now.
9495 */
9496 if (!qctx->nxrewrite) {
9497 result = query_addsoa(qctx, UINT32_MAX, DNS_SECTION_AUTHORITY);
9498 if (result != ISC_R_SUCCESS) {
9499 QUERY_ERROR(qctx, result);
9500 return ns_query_done(qctx);
9501 }
9502 }
9503
9504 /*
9505 * Add NSEC record if we found one.
9506 */
9507 if (WANTDNSSEC(qctx->client) &&
9508 dns_rdataset_isassociated(qctx->rdataset))
9509 {
9510 query_addnxrrsetnsec(qctx);
9511 }
9512
9513 return ns_query_done(qctx);
9514 }
9515
9516 static void
9517 query_addnxrrsetnsec(query_ctx_t *qctx) {
9518 ns_client_t *client = qctx->client;
9519 dns_rdata_t sigrdata;
9520 dns_rdata_rrsig_t sig;
9521 unsigned int labels;
9522 isc_buffer_t *dbuf, b;
9523 dns_name_t *fname;
9524 isc_result_t result;
9525
9526 INSIST(qctx->fname != NULL);
9527
9528 if (!qctx->fname->attributes.wildcard) {
9529 query_addrrset(qctx, &qctx->fname, &qctx->rdataset,
9530 &qctx->sigrdataset, NULL, DNS_SECTION_AUTHORITY);
9531 return;
9532 }
9533
9534 if (qctx->sigrdataset == NULL ||
9535 !dns_rdataset_isassociated(qctx->sigrdataset))
9536 {
9537 return;
9538 }
9539
9540 if (dns_rdataset_first(qctx->sigrdataset) != ISC_R_SUCCESS) {
9541 return;
9542 }
9543
9544 dns_rdata_init(&sigrdata);
9545 dns_rdataset_current(qctx->sigrdataset, &sigrdata);
9546 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
9547 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9548
9549 labels = dns_name_countlabels(qctx->fname);
9550 if ((unsigned int)sig.labels + 1 >= labels) {
9551 return;
9552 }
9553
9554 query_addwildcardproof(qctx, true, false);
9555
9556 /*
9557 * We'll need some resources...
9558 */
9559 dbuf = ns_client_getnamebuf(client);
9560 fname = ns_client_newname(client, dbuf, &b);
9561
9562 dns_name_split(qctx->fname, sig.labels + 1, NULL, fname);
9563 /* This will succeed, since we've stripped labels. */
9564 RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, fname, fname,
9565 NULL) == ISC_R_SUCCESS);
9566 query_addrrset(qctx, &fname, &qctx->rdataset, &qctx->sigrdataset, dbuf,
9567 DNS_SECTION_AUTHORITY);
9568 }
9569
9570 /*%
9571 * Handle NXDOMAIN and empty wildcard responses.
9572 */
9573 static isc_result_t
9574 query_nxdomain(query_ctx_t *qctx, isc_result_t result) {
9575 dns_section_t section;
9576 uint32_t ttl;
9577 bool empty_wild = (result == DNS_R_EMPTYWILD);
9578
9579 CCTRACE(ISC_LOG_DEBUG(3), "query_nxdomain");
9580
9581 CALL_HOOK(NS_QUERY_NXDOMAIN_BEGIN, qctx);
9582
9583 INSIST(qctx->is_zone || REDIRECT(qctx->client));
9584
9585 if (!empty_wild) {
9586 result = query_redirect(qctx, result);
9587 if (result != ISC_R_COMPLETE) {
9588 return result;
9589 }
9590 }
9591
9592 if (dns_rdataset_isassociated(qctx->rdataset)) {
9593 /*
9594 * If we've got a NSEC record, we need to save the
9595 * name now because we're going call query_addsoa()
9596 * below, and it needs to use the name buffer.
9597 */
9598 ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
9599 } else if (qctx->fname != NULL) {
9600 /*
9601 * We're not going to use fname, and need to release
9602 * our hold on the name buffer so query_addsoa()
9603 * may use it.
9604 */
9605 ns_client_releasename(qctx->client, &qctx->fname);
9606 }
9607
9608 /*
9609 * Add SOA to the additional section if generated by a
9610 * RPZ rewrite.
9611 *
9612 * If the query was for a SOA record force the
9613 * ttl to zero so that it is possible for clients to find
9614 * the containing zone of an arbitrary name with a stub
9615 * resolver and not have it cached.
9616 */
9617 section = qctx->nxrewrite ? DNS_SECTION_ADDITIONAL
9618 : DNS_SECTION_AUTHORITY;
9619 ttl = UINT32_MAX;
9620 if (!qctx->nxrewrite && qctx->qtype == dns_rdatatype_soa &&
9621 qctx->zone != NULL && dns_zone_getzeronosoattl(qctx->zone))
9622 {
9623 ttl = 0;
9624 }
9625 if (!qctx->nxrewrite ||
9626 (qctx->rpz_st != NULL && qctx->rpz_st->m.rpz->addsoa))
9627 {
9628 result = query_addsoa(qctx, ttl, section);
9629 if (result != ISC_R_SUCCESS) {
9630 QUERY_ERROR(qctx, result);
9631 return ns_query_done(qctx);
9632 }
9633 }
9634
9635 if (WANTDNSSEC(qctx->client)) {
9636 /*
9637 * Add NSEC record if we found one.
9638 */
9639 if (dns_rdataset_isassociated(qctx->rdataset)) {
9640 query_addrrset(qctx, &qctx->fname, &qctx->rdataset,
9641 &qctx->sigrdataset, NULL,
9642 DNS_SECTION_AUTHORITY);
9643 }
9644 query_addwildcardproof(qctx, false, false);
9645 }
9646
9647 /*
9648 * Set message rcode.
9649 */
9650 if (empty_wild) {
9651 qctx->client->message->rcode = dns_rcode_noerror;
9652 } else {
9653 qctx->client->message->rcode = dns_rcode_nxdomain;
9654 }
9655
9656 return ns_query_done(qctx);
9657
9658 cleanup:
9659 return result;
9660 }
9661
9662 /*
9663 * Handle both types of NXDOMAIN redirection, calling redirect()
9664 * (which implements type redirect zones) and redirect2() (which
9665 * implements recursive nxdomain-redirect lookups).
9666 *
9667 * Any result code other than ISC_R_COMPLETE means redirection was
9668 * successful and the result code should be returned up the call stack.
9669 *
9670 * ISC_R_COMPLETE means we reached the end of this function without
9671 * redirecting, so query processing should continue past it.
9672 */
9673 static isc_result_t
9674 query_redirect(query_ctx_t *qctx, isc_result_t saved_result) {
9675 isc_result_t result;
9676
9677 CCTRACE(ISC_LOG_DEBUG(3), "query_redirect");
9678
9679 result = redirect(qctx->client, qctx->fname, qctx->rdataset,
9680 &qctx->node, &qctx->db, &qctx->version, qctx->type);
9681 switch (result) {
9682 case ISC_R_SUCCESS:
9683 inc_stats(qctx->client, ns_statscounter_nxdomainredirect);
9684 return query_prepresponse(qctx);
9685 case DNS_R_NXRRSET:
9686 qctx->redirected = true;
9687 qctx->is_zone = true;
9688 return query_nodata(qctx, DNS_R_NXRRSET);
9689 case DNS_R_NCACHENXRRSET:
9690 qctx->redirected = true;
9691 qctx->is_zone = false;
9692 return query_ncache(qctx, DNS_R_NCACHENXRRSET);
9693 default:
9694 break;
9695 }
9696
9697 result = redirect2(qctx->client, qctx->fname, qctx->rdataset,
9698 &qctx->node, &qctx->db, &qctx->version, qctx->type,
9699 &qctx->is_zone);
9700 switch (result) {
9701 case ISC_R_SUCCESS:
9702 inc_stats(qctx->client, ns_statscounter_nxdomainredirect);
9703 return query_prepresponse(qctx);
9704 case DNS_R_CONTINUE:
9705 inc_stats(qctx->client,
9706 ns_statscounter_nxdomainredirect_rlookup);
9707 SAVE(qctx->client->query.redirect.db, qctx->db);
9708 SAVE(qctx->client->query.redirect.node, qctx->node);
9709 SAVE(qctx->client->query.redirect.zone, qctx->zone);
9710 qctx->client->query.redirect.qtype = qctx->qtype;
9711 INSIST(qctx->rdataset != NULL);
9712 SAVE(qctx->client->query.redirect.rdataset, qctx->rdataset);
9713 SAVE(qctx->client->query.redirect.sigrdataset,
9714 qctx->sigrdataset);
9715 qctx->client->query.redirect.result = saved_result;
9716 dns_name_copy(qctx->fname, qctx->client->query.redirect.fname);
9717 qctx->client->query.redirect.authoritative =
9718 qctx->authoritative;
9719 qctx->client->query.redirect.is_zone = qctx->is_zone;
9720 return ns_query_done(qctx);
9721 case DNS_R_NXRRSET:
9722 qctx->redirected = true;
9723 qctx->is_zone = true;
9724 return query_nodata(qctx, DNS_R_NXRRSET);
9725 case DNS_R_NCACHENXRRSET:
9726 qctx->redirected = true;
9727 qctx->is_zone = false;
9728 return query_ncache(qctx, DNS_R_NCACHENXRRSET);
9729 default:
9730 break;
9731 }
9732
9733 return ISC_R_COMPLETE;
9734 }
9735
9736 /*%
9737 * Logging function to be passed to dns_nsec_noexistnodata.
9738 */
9739 static void
9740 log_noexistnodata(void *val, int level, const char *fmt, ...) {
9741 query_ctx_t *qctx = val;
9742 va_list ap;
9743
9744 va_start(ap, fmt);
9745 ns_client_logv(qctx->client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY,
9746 level, fmt, ap);
9747 va_end(ap);
9748 }
9749
9750 static dns_ttl_t
9751 query_synthttl(dns_rdataset_t *soardataset, dns_rdataset_t *sigsoardataset,
9752 dns_rdataset_t *p1rdataset, dns_rdataset_t *sigp1rdataset,
9753 dns_rdataset_t *p2rdataset, dns_rdataset_t *sigp2rdataset) {
9754 dns_rdata_soa_t soa;
9755 dns_rdata_t rdata = DNS_RDATA_INIT;
9756 dns_ttl_t ttl;
9757 isc_result_t result;
9758
9759 REQUIRE(soardataset != NULL);
9760 REQUIRE(sigsoardataset != NULL);
9761 REQUIRE(p1rdataset != NULL);
9762 REQUIRE(sigp1rdataset != NULL);
9763
9764 result = dns_rdataset_first(soardataset);
9765 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9766 dns_rdataset_current(soardataset, &rdata);
9767 result = dns_rdata_tostruct(&rdata, &soa, NULL);
9768 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9769
9770 ttl = ISC_MIN(soa.minimum, soardataset->ttl);
9771 ttl = ISC_MIN(ttl, sigsoardataset->ttl);
9772 ttl = ISC_MIN(ttl, p1rdataset->ttl);
9773 ttl = ISC_MIN(ttl, sigp1rdataset->ttl);
9774 if (p2rdataset != NULL) {
9775 ttl = ISC_MIN(ttl, p2rdataset->ttl);
9776 }
9777 if (sigp2rdataset != NULL) {
9778 ttl = ISC_MIN(ttl, sigp2rdataset->ttl);
9779 }
9780
9781 return ttl;
9782 }
9783
9784 /*
9785 * Synthesize a NODATA response from the SOA and covering NSEC in cache.
9786 */
9787 static isc_result_t
9788 query_synthnodata(query_ctx_t *qctx, const dns_name_t *signer,
9789 dns_rdataset_t **soardatasetp,
9790 dns_rdataset_t **sigsoardatasetp) {
9791 dns_name_t *name = NULL;
9792 dns_ttl_t ttl;
9793 isc_buffer_t *dbuf, b;
9794
9795 /*
9796 * Determine the correct TTL to use for the SOA and RRSIG
9797 */
9798 ttl = query_synthttl(*soardatasetp, *sigsoardatasetp, qctx->rdataset,
9799 qctx->sigrdataset, NULL, NULL);
9800 (*soardatasetp)->ttl = (*sigsoardatasetp)->ttl = ttl;
9801
9802 /*
9803 * We want the SOA record to be first, so save the
9804 * NODATA proof's name now or else discard it.
9805 */
9806 if (WANTDNSSEC(qctx->client)) {
9807 ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
9808 } else {
9809 ns_client_releasename(qctx->client, &qctx->fname);
9810 }
9811
9812 dbuf = ns_client_getnamebuf(qctx->client);
9813 name = ns_client_newname(qctx->client, dbuf, &b);
9814 dns_name_copy(signer, name);
9815
9816 /*
9817 * Add SOA record. Omit the RRSIG if DNSSEC was not requested.
9818 */
9819 if (!WANTDNSSEC(qctx->client)) {
9820 sigsoardatasetp = NULL;
9821 }
9822 query_addrrset(qctx, &name, soardatasetp, sigsoardatasetp, dbuf,
9823 DNS_SECTION_AUTHORITY);
9824
9825 if (WANTDNSSEC(qctx->client)) {
9826 /*
9827 * Add NODATA proof.
9828 */
9829 query_addrrset(qctx, &qctx->fname, &qctx->rdataset,
9830 &qctx->sigrdataset, NULL, DNS_SECTION_AUTHORITY);
9831 }
9832
9833 inc_stats(qctx->client, ns_statscounter_nodatasynth);
9834
9835 if (name != NULL) {
9836 ns_client_releasename(qctx->client, &name);
9837 }
9838 return ISC_R_SUCCESS;
9839 }
9840
9841 /*
9842 * Synthesize a wildcard answer using the contents of 'rdataset'.
9843 * qctx contains the NODATA proof.
9844 */
9845 static isc_result_t
9846 query_synthwildcard(query_ctx_t *qctx, dns_rdataset_t *rdataset,
9847 dns_rdataset_t *sigrdataset) {
9848 dns_name_t *name = NULL;
9849 isc_buffer_t *dbuf, b;
9850 dns_rdataset_t *cloneset = NULL, *clonesigset = NULL;
9851 dns_rdataset_t **sigrdatasetp;
9852
9853 CCTRACE(ISC_LOG_DEBUG(3), "query_synthwildcard");
9854
9855 /*
9856 * We want the answer to be first, so save the
9857 * NOQNAME proof's name now or else discard it.
9858 */
9859 if (WANTDNSSEC(qctx->client)) {
9860 ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
9861 } else {
9862 ns_client_releasename(qctx->client, &qctx->fname);
9863 }
9864
9865 dbuf = ns_client_getnamebuf(qctx->client);
9866 name = ns_client_newname(qctx->client, dbuf, &b);
9867 dns_name_copy(qctx->client->query.qname, name);
9868
9869 cloneset = ns_client_newrdataset(qctx->client);
9870 dns_rdataset_clone(rdataset, cloneset);
9871
9872 /*
9873 * Add answer RRset. Omit the RRSIG if DNSSEC was not requested.
9874 */
9875 if (WANTDNSSEC(qctx->client)) {
9876 clonesigset = ns_client_newrdataset(qctx->client);
9877 dns_rdataset_clone(sigrdataset, clonesigset);
9878 sigrdatasetp = &clonesigset;
9879 } else {
9880 sigrdatasetp = NULL;
9881 }
9882
9883 query_addrrset(qctx, &name, &cloneset, sigrdatasetp, dbuf,
9884 DNS_SECTION_ANSWER);
9885
9886 if (WANTDNSSEC(qctx->client)) {
9887 /*
9888 * Add NOQNAME proof.
9889 */
9890 query_addrrset(qctx, &qctx->fname, &qctx->rdataset,
9891 &qctx->sigrdataset, NULL, DNS_SECTION_AUTHORITY);
9892 }
9893
9894 inc_stats(qctx->client, ns_statscounter_wildcardsynth);
9895
9896 if (name != NULL) {
9897 ns_client_releasename(qctx->client, &name);
9898 }
9899 if (cloneset != NULL) {
9900 ns_client_putrdataset(qctx->client, &cloneset);
9901 }
9902 if (clonesigset != NULL) {
9903 ns_client_putrdataset(qctx->client, &clonesigset);
9904 }
9905 return ISC_R_SUCCESS;
9906 }
9907
9908 /*
9909 * Add a synthesized CNAME record from the wildard RRset (rdataset)
9910 * and NODATA proof by calling query_synthwildcard then setup to
9911 * follow the CNAME.
9912 */
9913 static isc_result_t
9914 query_synthcnamewildcard(query_ctx_t *qctx, dns_rdataset_t *rdataset,
9915 dns_rdataset_t *sigrdataset) {
9916 isc_result_t result;
9917 dns_name_t *tname = NULL;
9918 dns_rdata_t rdata = DNS_RDATA_INIT;
9919 dns_rdata_cname_t cname;
9920
9921 result = query_synthwildcard(qctx, rdataset, sigrdataset);
9922 if (result != ISC_R_SUCCESS) {
9923 return result;
9924 }
9925
9926 qctx->client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
9927
9928 /*
9929 * Reset qname to be the target name of the CNAME and restart
9930 * the query.
9931 */
9932 dns_message_gettempname(qctx->client->message, &tname);
9933
9934 result = dns_rdataset_first(rdataset);
9935 if (result != ISC_R_SUCCESS) {
9936 dns_message_puttempname(qctx->client->message, &tname);
9937 return result;
9938 }
9939
9940 dns_rdataset_current(rdataset, &rdata);
9941 result = dns_rdata_tostruct(&rdata, &cname, NULL);
9942 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9943 dns_rdata_reset(&rdata);
9944
9945 if (dns_name_equal(qctx->client->query.qname, &cname.cname)) {
9946 dns_message_puttempname(qctx->client->message, &tname);
9947 dns_rdata_freestruct(&cname);
9948 return ISC_R_SUCCESS;
9949 }
9950
9951 dns_name_copy(&cname.cname, tname);
9952
9953 dns_rdata_freestruct(&cname);
9954 ns_client_qnamereplace(qctx->client, tname);
9955 qctx->want_restart = true;
9956 if (!WANTRECURSION(qctx->client)) {
9957 qctx->options.nolog = true;
9958 }
9959
9960 return result;
9961 }
9962
9963 /*
9964 * Synthesize a NXDOMAIN or NODATA response from qctx (which contains the
9965 * NOQNAME proof), nowild + nowildrdataset + signowildrdataset (which
9966 * contains the NOWILDCARD proof or NODATA at wildcard) and
9967 * signer + soardatasetp + sigsoardatasetp which contain the
9968 * SOA record + RRSIG for the negative answer.
9969 */
9970 static isc_result_t
9971 query_synthnxdomainnodata(query_ctx_t *qctx, bool nodata, dns_name_t *nowild,
9972 dns_rdataset_t *nowildrdataset,
9973 dns_rdataset_t *signowildrdataset, dns_name_t *signer,
9974 dns_rdataset_t **soardatasetp,
9975 dns_rdataset_t **sigsoardatasetp) {
9976 dns_name_t *name = NULL;
9977 dns_ttl_t ttl;
9978 isc_buffer_t *dbuf, b;
9979 dns_rdataset_t *cloneset = NULL, *clonesigset = NULL;
9980
9981 CCTRACE(ISC_LOG_DEBUG(3), "query_synthnxdomain");
9982
9983 /*
9984 * Determine the correct TTL to use for the SOA and RRSIG
9985 */
9986 ttl = query_synthttl(*soardatasetp, *sigsoardatasetp, qctx->rdataset,
9987 qctx->sigrdataset, nowildrdataset,
9988 signowildrdataset);
9989 (*soardatasetp)->ttl = (*sigsoardatasetp)->ttl = ttl;
9990
9991 /*
9992 * We want the SOA record to be first, so save the
9993 * NOQNAME proof's name now or else discard it.
9994 */
9995 if (WANTDNSSEC(qctx->client)) {
9996 ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
9997 } else {
9998 ns_client_releasename(qctx->client, &qctx->fname);
9999 }
10000
10001 dbuf = ns_client_getnamebuf(qctx->client);
10002 name = ns_client_newname(qctx->client, dbuf, &b);
10003 dns_name_copy(signer, name);
10004
10005 /*
10006 * Add SOA record. Omit the RRSIG if DNSSEC was not requested.
10007 */
10008 if (!WANTDNSSEC(qctx->client)) {
10009 sigsoardatasetp = NULL;
10010 }
10011 query_addrrset(qctx, &name, soardatasetp, sigsoardatasetp, dbuf,
10012 DNS_SECTION_AUTHORITY);
10013
10014 if (WANTDNSSEC(qctx->client)) {
10015 /*
10016 * Add NOQNAME proof.
10017 */
10018 query_addrrset(qctx, &qctx->fname, &qctx->rdataset,
10019 &qctx->sigrdataset, NULL, DNS_SECTION_AUTHORITY);
10020
10021 dbuf = ns_client_getnamebuf(qctx->client);
10022 name = ns_client_newname(qctx->client, dbuf, &b);
10023 dns_name_copy(nowild, name);
10024
10025 cloneset = ns_client_newrdataset(qctx->client);
10026 clonesigset = ns_client_newrdataset(qctx->client);
10027
10028 dns_rdataset_clone(nowildrdataset, cloneset);
10029 dns_rdataset_clone(signowildrdataset, clonesigset);
10030
10031 /*
10032 * Add NOWILDCARD proof.
10033 */
10034 query_addrrset(qctx, &name, &cloneset, &clonesigset, dbuf,
10035 DNS_SECTION_AUTHORITY);
10036 }
10037
10038 if (nodata) {
10039 inc_stats(qctx->client, ns_statscounter_nodatasynth);
10040 } else {
10041 qctx->client->message->rcode = dns_rcode_nxdomain;
10042 inc_stats(qctx->client, ns_statscounter_nxdomainsynth);
10043 }
10044
10045 if (name != NULL) {
10046 ns_client_releasename(qctx->client, &name);
10047 }
10048 if (cloneset != NULL) {
10049 ns_client_putrdataset(qctx->client, &cloneset);
10050 }
10051 if (clonesigset != NULL) {
10052 ns_client_putrdataset(qctx->client, &clonesigset);
10053 }
10054 return ISC_R_SUCCESS;
10055 }
10056
10057 /*
10058 * Check that all signer names in sigrdataset match the expected signer.
10059 */
10060 static isc_result_t
10061 checksignames(dns_name_t *signer, dns_rdataset_t *sigrdataset) {
10062 isc_result_t result;
10063
10064 for (result = dns_rdataset_first(sigrdataset); result == ISC_R_SUCCESS;
10065 result = dns_rdataset_next(sigrdataset))
10066 {
10067 dns_rdata_t rdata = DNS_RDATA_INIT;
10068 dns_rdata_rrsig_t rrsig;
10069
10070 dns_rdataset_current(sigrdataset, &rdata);
10071 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
10072 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10073 if (dns_name_countlabels(signer) == 0) {
10074 dns_name_copy(&rrsig.signer, signer);
10075 } else if (!dns_name_equal(signer, &rrsig.signer)) {
10076 return ISC_R_FAILURE;
10077 }
10078 }
10079
10080 return ISC_R_SUCCESS;
10081 }
10082
10083 /*%
10084 * Handle covering NSEC responses.
10085 *
10086 * Verify the NSEC record is appropriate for the QNAME; if not,
10087 * redo the initial query without DNS_DBFIND_COVERINGNSEC.
10088 *
10089 * If the covering NSEC proves that the name exists but not the type,
10090 * synthesize a NODATA response.
10091 *
10092 * If the name doesn't exist, compute the wildcard record and check whether
10093 * the wildcard name exists or not. If we can't determine this, redo the
10094 * initial query without DNS_DBFIND_COVERINGNSEC.
10095 *
10096 * If the wildcard name does not exist, compute the SOA name and look that
10097 * up. If the SOA record does not exist, redo the initial query without
10098 * DNS_DBFIND_COVERINGNSEC. If the SOA record exists, synthesize an
10099 * NXDOMAIN response from the found records.
10100 *
10101 * If the wildcard name does exist, perform a lookup for the requested
10102 * type at the wildcard name.
10103 */
10104 static isc_result_t
10105 query_coveringnsec(query_ctx_t *qctx) {
10106 dns_db_t *db = NULL;
10107 dns_clientinfo_t ci;
10108 dns_clientinfomethods_t cm;
10109 dns_dbnode_t *node = NULL;
10110 dns_fixedname_t fixed;
10111 dns_fixedname_t fnamespace;
10112 dns_fixedname_t fnowild;
10113 dns_fixedname_t fsigner;
10114 dns_fixedname_t fwild;
10115 dns_name_t *fname = NULL;
10116 dns_name_t *namespace = NULL;
10117 dns_name_t *nowild = NULL;
10118 dns_name_t *signer = NULL;
10119 dns_name_t *wild = NULL;
10120 dns_name_t qname;
10121 dns_rdataset_t *soardataset = NULL, *sigsoardataset = NULL;
10122 dns_rdataset_t rdataset, sigrdataset;
10123 bool done = false;
10124 bool exists = true, data = true;
10125 bool redirected = false;
10126 isc_result_t result = ISC_R_SUCCESS;
10127 unsigned int dboptions = qctx->client->query.dboptions;
10128 unsigned int labels;
10129
10130 CCTRACE(ISC_LOG_DEBUG(3), "query_coveringnsec");
10131
10132 dns_name_init(&qname, NULL);
10133 dns_rdataset_init(&rdataset);
10134 dns_rdataset_init(&sigrdataset);
10135 namespace = dns_fixedname_initname(&fnamespace);
10136
10137 /*
10138 * Check that the NSEC record is from the correct namespace.
10139 * For records that belong to the parent zone (i.e. DS),
10140 * remove a label to find the correct namespace.
10141 */
10142 dns_name_clone(qctx->client->query.qname, &qname);
10143 labels = dns_name_countlabels(&qname);
10144 if (dns_rdatatype_atparent(qctx->qtype) && labels > 1) {
10145 dns_name_getlabelsequence(&qname, 1, labels - 1, &qname);
10146 }
10147 dns_view_sfd_find(qctx->view, &qname, namespace);
10148 if (!dns_name_issubdomain(qctx->fname, namespace)) {
10149 goto cleanup;
10150 }
10151
10152 /*
10153 * If we have no signer name, stop immediately.
10154 */
10155 if (!dns_rdataset_isassociated(qctx->sigrdataset)) {
10156 goto cleanup;
10157 }
10158
10159 wild = dns_fixedname_initname(&fwild);
10160 fname = dns_fixedname_initname(&fixed);
10161 signer = dns_fixedname_initname(&fsigner);
10162 nowild = dns_fixedname_initname(&fnowild);
10163
10164 dns_clientinfomethods_init(&cm, ns_client_sourceip);
10165 dns_clientinfo_init(&ci, qctx->client, NULL);
10166
10167 /*
10168 * All signer names must be the same to accept.
10169 */
10170 result = checksignames(signer, qctx->sigrdataset);
10171 if (result != ISC_R_SUCCESS) {
10172 result = ISC_R_SUCCESS;
10173 goto cleanup;
10174 }
10175
10176 /*
10177 * If NSEC or RRSIG are missing from the type map
10178 * reject the NSEC RRset.
10179 */
10180 if (!dns_nsec_requiredtypespresent(qctx->rdataset)) {
10181 goto cleanup;
10182 }
10183
10184 /*
10185 * Check that we have the correct NOQNAME NSEC record.
10186 */
10187 result = dns_nsec_noexistnodata(qctx->qtype, qctx->client->query.qname,
10188 qctx->fname, qctx->rdataset, &exists,
10189 &data, wild, log_noexistnodata, qctx);
10190
10191 if (result != ISC_R_SUCCESS || (exists && data)) {
10192 goto cleanup;
10193 }
10194
10195 if (exists) {
10196 if (qctx->type == dns_rdatatype_any) { /* XXX not yet */
10197 goto cleanup;
10198 }
10199 if (!ISC_LIST_EMPTY(qctx->view->dns64) &&
10200 (qctx->type == dns_rdatatype_a ||
10201 qctx->type == dns_rdatatype_aaaa)) /* XXX not yet */
10202 {
10203 goto cleanup;
10204 }
10205 if (!qctx->resuming && !STALE(qctx->rdataset) &&
10206 qctx->rdataset->ttl == 0 && RECURSIONOK(qctx->client))
10207 {
10208 goto cleanup;
10209 }
10210
10211 soardataset = ns_client_newrdataset(qctx->client);
10212 sigsoardataset = ns_client_newrdataset(qctx->client);
10213
10214 /*
10215 * Look for SOA record to construct NODATA response.
10216 */
10217 dns_db_attach(qctx->db, &db);
10218 result = dns_db_findext(db, signer, qctx->version,
10219 dns_rdatatype_soa, dboptions,
10220 qctx->client->now, &node, fname, &cm,
10221 &ci, soardataset, sigsoardataset);
10222
10223 if (result != ISC_R_SUCCESS) {
10224 goto cleanup;
10225 }
10226 (void)query_synthnodata(qctx, signer, &soardataset,
10227 &sigsoardataset);
10228 done = true;
10229 goto cleanup;
10230 }
10231
10232 /*
10233 * Look up the no-wildcard proof.
10234 */
10235 dns_db_attach(qctx->db, &db);
10236 result = dns_db_findext(db, wild, qctx->version, qctx->type,
10237 dboptions | DNS_DBFIND_COVERINGNSEC,
10238 qctx->client->now, &node, nowild, &cm, &ci,
10239 &rdataset, &sigrdataset);
10240
10241 if (rdataset.trust != dns_trust_secure ||
10242 sigrdataset.trust != dns_trust_secure)
10243 {
10244 goto cleanup;
10245 }
10246
10247 /*
10248 * Zero TTL handling of wildcard record.
10249 *
10250 * We don't yet have code to handle synthesis and type ANY or dns64
10251 * processing so we abort the synthesis here if there would be a
10252 * interaction.
10253 */
10254 switch (result) {
10255 case ISC_R_SUCCESS:
10256 if (qctx->type == dns_rdatatype_any) { /* XXX not yet */
10257 goto cleanup;
10258 }
10259 if (!ISC_LIST_EMPTY(qctx->view->dns64) &&
10260 (qctx->type == dns_rdatatype_a ||
10261 qctx->type == dns_rdatatype_aaaa)) /* XXX not yet */
10262 {
10263 goto cleanup;
10264 }
10265 FALLTHROUGH;
10266 case DNS_R_CNAME:
10267 if (!qctx->resuming && !STALE(&rdataset) && rdataset.ttl == 0 &&
10268 RECURSIONOK(qctx->client))
10269 {
10270 goto cleanup;
10271 }
10272 default:
10273 break;
10274 }
10275
10276 switch (result) {
10277 case DNS_R_COVERINGNSEC:
10278 /*
10279 * Check that the covering NSEC record is from the right
10280 * namespace.
10281 */
10282 if (!dns_name_issubdomain(nowild, namespace)) {
10283 goto cleanup;
10284 }
10285 result = dns_nsec_noexistnodata(qctx->qtype, wild, nowild,
10286 &rdataset, &exists, &data, NULL,
10287 log_noexistnodata, qctx);
10288 if (result != ISC_R_SUCCESS || (exists && data)) {
10289 goto cleanup;
10290 }
10291 break;
10292 case ISC_R_SUCCESS: /* wild card match */
10293 (void)query_synthwildcard(qctx, &rdataset, &sigrdataset);
10294 done = true;
10295 goto cleanup;
10296 case DNS_R_CNAME: /* wild card cname */
10297 (void)query_synthcnamewildcard(qctx, &rdataset, &sigrdataset);
10298 done = true;
10299 goto cleanup;
10300 case DNS_R_NCACHENXRRSET: /* wild card nodata */
10301 case DNS_R_NCACHENXDOMAIN: /* direct nxdomain */
10302 default:
10303 goto cleanup;
10304 }
10305
10306 /*
10307 * We now have the proof that we have an NXDOMAIN. Apply
10308 * NXDOMAIN redirection if configured.
10309 */
10310 result = query_redirect(qctx, DNS_R_COVERINGNSEC);
10311 if (result != ISC_R_COMPLETE) {
10312 redirected = true;
10313 goto cleanup;
10314 }
10315
10316 /*
10317 * Must be signed to accept.
10318 */
10319 if (!dns_rdataset_isassociated(&sigrdataset)) {
10320 goto cleanup;
10321 }
10322
10323 /*
10324 * Check signer signer names again.
10325 */
10326 result = checksignames(signer, &sigrdataset);
10327 if (result != ISC_R_SUCCESS) {
10328 result = ISC_R_SUCCESS;
10329 goto cleanup;
10330 }
10331
10332 if (node != NULL) {
10333 dns_db_detachnode(db, &node);
10334 }
10335
10336 soardataset = ns_client_newrdataset(qctx->client);
10337 sigsoardataset = ns_client_newrdataset(qctx->client);
10338
10339 /*
10340 * Look for SOA record to construct NXDOMAIN response.
10341 */
10342 result = dns_db_findext(db, signer, qctx->version, dns_rdatatype_soa,
10343 dboptions, qctx->client->now, &node, fname, &cm,
10344 &ci, soardataset, sigsoardataset);
10345
10346 if (result != ISC_R_SUCCESS) {
10347 goto cleanup;
10348 }
10349 (void)query_synthnxdomainnodata(qctx, exists, nowild, &rdataset,
10350 &sigrdataset, signer, &soardataset,
10351 &sigsoardataset);
10352 done = true;
10353
10354 cleanup:
10355 if (dns_rdataset_isassociated(&rdataset)) {
10356 dns_rdataset_disassociate(&rdataset);
10357 }
10358 if (dns_rdataset_isassociated(&sigrdataset)) {
10359 dns_rdataset_disassociate(&sigrdataset);
10360 }
10361 if (soardataset != NULL) {
10362 ns_client_putrdataset(qctx->client, &soardataset);
10363 }
10364 if (sigsoardataset != NULL) {
10365 ns_client_putrdataset(qctx->client, &sigsoardataset);
10366 }
10367 if (db != NULL) {
10368 if (node != NULL) {
10369 dns_db_detachnode(db, &node);
10370 }
10371 dns_db_detach(&db);
10372 }
10373
10374 if (redirected) {
10375 return result;
10376 }
10377
10378 if (!done) {
10379 /*
10380 * No covering NSEC was found; proceed with recursion.
10381 */
10382 qctx->findcoveringnsec = false;
10383 if (qctx->fname != NULL) {
10384 ns_client_releasename(qctx->client, &qctx->fname);
10385 }
10386 if (qctx->node != NULL) {
10387 dns_db_detachnode(qctx->db, &qctx->node);
10388 }
10389 ns_client_putrdataset(qctx->client, &qctx->rdataset);
10390 if (qctx->sigrdataset != NULL) {
10391 ns_client_putrdataset(qctx->client, &qctx->sigrdataset);
10392 }
10393 return query_lookup(qctx);
10394 }
10395
10396 return ns_query_done(qctx);
10397 }
10398
10399 /*%
10400 * Handle negative cache responses, DNS_R_NCACHENXRRSET or
10401 * DNS_R_NCACHENXDOMAIN. (Note: may also be called with result
10402 * set to DNS_R_NXDOMAIN when handling DNS64 lookups.)
10403 */
10404 static isc_result_t
10405 query_ncache(query_ctx_t *qctx, isc_result_t result) {
10406 INSIST(!qctx->is_zone);
10407 INSIST(result == DNS_R_NCACHENXDOMAIN ||
10408 result == DNS_R_NCACHENXRRSET || result == DNS_R_NXDOMAIN);
10409
10410 CCTRACE(ISC_LOG_DEBUG(3), "query_ncache");
10411
10412 CALL_HOOK(NS_QUERY_NCACHE_BEGIN, qctx);
10413
10414 qctx->authoritative = false;
10415
10416 if (result == DNS_R_NCACHENXDOMAIN) {
10417 /*
10418 * Set message rcode. (This is not done when
10419 * result == DNS_R_NXDOMAIN because that means we're
10420 * being called after a DNS64 lookup and don't want
10421 * to update the rcode now.)
10422 */
10423 qctx->client->message->rcode = dns_rcode_nxdomain;
10424
10425 /* Look for RFC 1918 leakage from Internet. */
10426 if (qctx->qtype == dns_rdatatype_ptr &&
10427 qctx->client->message->rdclass == dns_rdataclass_in &&
10428 dns_name_countlabels(qctx->fname) == 7)
10429 {
10430 warn_rfc1918(qctx->client, qctx->fname, qctx->rdataset);
10431 }
10432 }
10433
10434 return query_nodata(qctx, result);
10435
10436 cleanup:
10437 return result;
10438 }
10439
10440 /*
10441 * If we have a zero ttl from the cache, refetch.
10442 */
10443 static isc_result_t
10444 query_zerottl_refetch(query_ctx_t *qctx) {
10445 isc_result_t result;
10446
10447 CCTRACE(ISC_LOG_DEBUG(3), "query_zerottl_refetch");
10448
10449 if (qctx->is_zone || qctx->resuming || STALE(qctx->rdataset) ||
10450 qctx->rdataset->ttl != 0 || !RECURSIONOK(qctx->client))
10451 {
10452 return ISC_R_COMPLETE;
10453 }
10454
10455 qctx_clean(qctx);
10456
10457 INSIST(!REDIRECT(qctx->client));
10458
10459 result = ns_query_recurse(qctx->client, qctx->qtype,
10460 qctx->client->query.qname, NULL, NULL,
10461 qctx->resuming);
10462 if (result == ISC_R_SUCCESS) {
10463 CALL_HOOK(NS_QUERY_ZEROTTL_RECURSE, qctx);
10464 qctx->client->query.attributes |= NS_QUERYATTR_RECURSING;
10465
10466 if (qctx->dns64) {
10467 qctx->client->query.attributes |= NS_QUERYATTR_DNS64;
10468 }
10469 if (qctx->dns64_exclude) {
10470 qctx->client->query.attributes |=
10471 NS_QUERYATTR_DNS64EXCLUDE;
10472 }
10473 } else {
10474 /*
10475 * There was a zero ttl from the cache, don't fallback to
10476 * serve-stale lookup.
10477 */
10478 QUERY_ERROR(qctx, result);
10479 }
10480
10481 return ns_query_done(qctx);
10482
10483 cleanup:
10484 return result;
10485 }
10486
10487 /*
10488 * Handle CNAME responses.
10489 */
10490 static isc_result_t
10491 query_cname(query_ctx_t *qctx) {
10492 isc_result_t result = ISC_R_UNSET;
10493 dns_name_t *tname = NULL;
10494 dns_rdataset_t *trdataset = NULL;
10495 dns_rdataset_t **sigrdatasetp = NULL;
10496 dns_rdata_t rdata = DNS_RDATA_INIT;
10497 dns_rdata_cname_t cname;
10498
10499 CCTRACE(ISC_LOG_DEBUG(3), "query_cname");
10500
10501 CALL_HOOK(NS_QUERY_CNAME_BEGIN, qctx);
10502
10503 result = query_zerottl_refetch(qctx);
10504 if (result != ISC_R_COMPLETE) {
10505 goto cleanup;
10506 }
10507
10508 /*
10509 * Keep a copy of the rdataset. We have to do this because
10510 * query_addrrset may clear 'rdataset' (to prevent the
10511 * cleanup code from cleaning it up).
10512 */
10513 trdataset = qctx->rdataset;
10514
10515 /*
10516 * Add the CNAME to the answer section.
10517 */
10518 if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL) {
10519 sigrdatasetp = &qctx->sigrdataset;
10520 }
10521
10522 if (WANTDNSSEC(qctx->client) && qctx->fname->attributes.wildcard) {
10523 dns_fixedname_init(&qctx->wildcardname);
10524 dns_name_copy(qctx->fname,
10525 dns_fixedname_name(&qctx->wildcardname));
10526 qctx->need_wildcardproof = true;
10527 }
10528
10529 if (NOQNAME(qctx->rdataset) && WANTDNSSEC(qctx->client)) {
10530 qctx->noqname = qctx->rdataset;
10531 } else {
10532 qctx->noqname = NULL;
10533 }
10534
10535 if (!qctx->is_zone && RECURSIONOK(qctx->client)) {
10536 query_prefetch(qctx->client, qctx->fname, qctx->rdataset);
10537 }
10538
10539 query_addrrset(qctx, &qctx->fname, &qctx->rdataset, sigrdatasetp,
10540 qctx->dbuf, DNS_SECTION_ANSWER);
10541
10542 query_addnoqnameproof(qctx);
10543
10544 /*
10545 * We set the PARTIALANSWER attribute so that if anything goes
10546 * wrong later on, we'll return what we've got so far.
10547 */
10548 qctx->client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
10549
10550 /*
10551 * Reset qname to be the target name of the CNAME and restart
10552 * the query.
10553 */
10554 dns_message_gettempname(qctx->client->message, &tname);
10555
10556 result = dns_rdataset_first(trdataset);
10557 if (result != ISC_R_SUCCESS) {
10558 dns_message_puttempname(qctx->client->message, &tname);
10559 (void)ns_query_done(qctx);
10560 goto cleanup;
10561 }
10562
10563 dns_rdataset_current(trdataset, &rdata);
10564 result = dns_rdata_tostruct(&rdata, &cname, NULL);
10565 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10566 dns_rdata_reset(&rdata);
10567
10568 dns_name_copy(&cname.cname, tname);
10569
10570 dns_rdata_freestruct(&cname);
10571 ns_client_qnamereplace(qctx->client, tname);
10572 qctx->want_restart = true;
10573 if (!WANTRECURSION(qctx->client)) {
10574 qctx->options.nolog = true;
10575 }
10576
10577 query_addauth(qctx);
10578
10579 return ns_query_done(qctx);
10580
10581 cleanup:
10582 return result;
10583 }
10584
10585 /*
10586 * Handle DNAME responses.
10587 */
10588 static isc_result_t
10589 query_dname(query_ctx_t *qctx) {
10590 dns_name_t *tname, *prefix;
10591 dns_rdata_t rdata = DNS_RDATA_INIT;
10592 dns_rdata_dname_t dname;
10593 dns_fixedname_t fixed;
10594 dns_rdataset_t *trdataset;
10595 dns_rdataset_t **sigrdatasetp = NULL;
10596 dns_namereln_t namereln;
10597 isc_buffer_t b;
10598 int order;
10599 isc_result_t result = ISC_R_UNSET;
10600 unsigned int nlabels;
10601
10602 CCTRACE(ISC_LOG_DEBUG(3), "query_dname");
10603
10604 CALL_HOOK(NS_QUERY_DNAME_BEGIN, qctx);
10605
10606 /*
10607 * Compare the current qname to the found name. We need
10608 * to know how many labels and bits are in common because
10609 * we're going to have to split qname later on.
10610 */
10611 namereln = dns_name_fullcompare(qctx->client->query.qname, qctx->fname,
10612 &order, &nlabels);
10613 INSIST(namereln == dns_namereln_subdomain);
10614
10615 /*
10616 * Keep a copy of the rdataset. We have to do this because
10617 * query_addrrset may clear 'rdataset' (to prevent the
10618 * cleanup code from cleaning it up).
10619 */
10620 trdataset = qctx->rdataset;
10621
10622 /*
10623 * Add the DNAME to the answer section.
10624 */
10625 if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL) {
10626 sigrdatasetp = &qctx->sigrdataset;
10627 }
10628
10629 if (WANTDNSSEC(qctx->client) && qctx->fname->attributes.wildcard) {
10630 dns_fixedname_init(&qctx->wildcardname);
10631 dns_name_copy(qctx->fname,
10632 dns_fixedname_name(&qctx->wildcardname));
10633 qctx->need_wildcardproof = true;
10634 }
10635
10636 if (!qctx->is_zone && RECURSIONOK(qctx->client)) {
10637 query_prefetch(qctx->client, qctx->fname, qctx->rdataset);
10638 }
10639 query_addrrset(qctx, &qctx->fname, &qctx->rdataset, sigrdatasetp,
10640 qctx->dbuf, DNS_SECTION_ANSWER);
10641
10642 /*
10643 * We set the PARTIALANSWER attribute so that if anything goes
10644 * wrong later on, we'll return what we've got so far.
10645 */
10646 qctx->client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
10647
10648 /*
10649 * Get the target name of the DNAME.
10650 */
10651 tname = NULL;
10652 dns_message_gettempname(qctx->client->message, &tname);
10653
10654 result = dns_rdataset_first(trdataset);
10655 if (result != ISC_R_SUCCESS) {
10656 dns_message_puttempname(qctx->client->message, &tname);
10657 (void)ns_query_done(qctx);
10658 goto cleanup;
10659 }
10660
10661 dns_rdataset_current(trdataset, &rdata);
10662 result = dns_rdata_tostruct(&rdata, &dname, NULL);
10663 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10664 dns_rdata_reset(&rdata);
10665
10666 dns_name_copy(&dname.dname, tname);
10667 dns_rdata_freestruct(&dname);
10668
10669 /*
10670 * Construct the new qname consisting of
10671 * <found name prefix>.<dname target>
10672 */
10673 prefix = dns_fixedname_initname(&fixed);
10674 dns_name_split(qctx->client->query.qname, nlabels, prefix, NULL);
10675 INSIST(qctx->fname == NULL);
10676 qctx->dbuf = ns_client_getnamebuf(qctx->client);
10677 qctx->fname = ns_client_newname(qctx->client, qctx->dbuf, &b);
10678 result = dns_name_concatenate(prefix, tname, qctx->fname, NULL);
10679 dns_message_puttempname(qctx->client->message, &tname);
10680
10681 /*
10682 * RFC2672, section 4.1, subsection 3c says
10683 * we should return YXDOMAIN if the constructed
10684 * name would be too long.
10685 */
10686 if (result == DNS_R_NAMETOOLONG) {
10687 qctx->client->message->rcode = dns_rcode_yxdomain;
10688 }
10689 if (result != ISC_R_SUCCESS) {
10690 (void)ns_query_done(qctx);
10691 goto cleanup;
10692 }
10693
10694 ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf);
10695
10696 /*
10697 * Synthesize a CNAME consisting of
10698 * <old qname> <dname ttl> CNAME <new qname>
10699 * with <dname trust value>
10700 *
10701 * Synthesize a CNAME so old old clients that don't understand
10702 * DNAME can chain.
10703 *
10704 * We do not try to synthesize a signature because we hope
10705 * that security aware servers will understand DNAME. Also,
10706 * even if we had an online key, making a signature
10707 * on-the-fly is costly, and not really legitimate anyway
10708 * since the synthesized CNAME is NOT in the zone.
10709 */
10710 query_addcname(qctx, trdataset->trust, trdataset->ttl);
10711
10712 /*
10713 * If the original query was not for a CNAME or ANY then follow the
10714 * CNAME.
10715 */
10716 if (qctx->qtype != dns_rdatatype_cname &&
10717 qctx->qtype != dns_rdatatype_any)
10718 {
10719 /*
10720 * Switch to the new qname and restart.
10721 */
10722 ns_client_qnamereplace(qctx->client, qctx->fname);
10723 qctx->fname = NULL;
10724 qctx->want_restart = true;
10725 if (!WANTRECURSION(qctx->client)) {
10726 qctx->options.nolog = true;
10727 }
10728 }
10729
10730 query_addauth(qctx);
10731
10732 return ns_query_done(qctx);
10733
10734 cleanup:
10735 return result;
10736 }
10737
10738 /*%
10739 * Add CNAME to response.
10740 */
10741 static void
10742 query_addcname(query_ctx_t *qctx, dns_trust_t trust, dns_ttl_t ttl) {
10743 ns_client_t *client = qctx->client;
10744 dns_rdataset_t *rdataset = NULL;
10745 dns_rdatalist_t *rdatalist = NULL;
10746 dns_rdata_t *rdata = NULL;
10747 isc_region_t r;
10748 dns_name_t *aname = NULL;
10749
10750 dns_message_gettempname(client->message, &aname);
10751
10752 dns_name_copy(client->query.qname, aname);
10753
10754 dns_message_gettemprdatalist(client->message, &rdatalist);
10755
10756 dns_message_gettemprdata(client->message, &rdata);
10757
10758 dns_message_gettemprdataset(client->message, &rdataset);
10759
10760 rdatalist->type = dns_rdatatype_cname;
10761 rdatalist->rdclass = client->message->rdclass;
10762 rdatalist->ttl = ttl;
10763
10764 dns_name_toregion(qctx->fname, &r);
10765 rdata->data = r.base;
10766 rdata->length = r.length;
10767 rdata->rdclass = client->message->rdclass;
10768 rdata->type = dns_rdatatype_cname;
10769
10770 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
10771 dns_rdatalist_tordataset(rdatalist, rdataset);
10772 rdataset->trust = trust;
10773 dns_rdataset_setownercase(rdataset, aname);
10774
10775 query_addrrset(qctx, &aname, &rdataset, NULL, NULL, DNS_SECTION_ANSWER);
10776 if (rdataset != NULL) {
10777 if (dns_rdataset_isassociated(rdataset)) {
10778 dns_rdataset_disassociate(rdataset);
10779 }
10780 dns_message_puttemprdataset(client->message, &rdataset);
10781 }
10782 if (aname != NULL) {
10783 dns_message_puttempname(client->message, &aname);
10784 }
10785 }
10786
10787 /*%
10788 * Prepare to respond: determine whether a wildcard proof is needed,
10789 * then hand off to query_respond() or (for type ANY queries)
10790 * query_respond_any().
10791 */
10792 static isc_result_t
10793 query_prepresponse(query_ctx_t *qctx) {
10794 isc_result_t result = ISC_R_UNSET;
10795
10796 CCTRACE(ISC_LOG_DEBUG(3), "query_prepresponse");
10797
10798 CALL_HOOK(NS_QUERY_PREP_RESPONSE_BEGIN, qctx);
10799
10800 if (WANTDNSSEC(qctx->client) && qctx->fname->attributes.wildcard) {
10801 dns_fixedname_init(&qctx->wildcardname);
10802 dns_name_copy(qctx->fname,
10803 dns_fixedname_name(&qctx->wildcardname));
10804 qctx->need_wildcardproof = true;
10805 }
10806
10807 if (qctx->type == dns_rdatatype_any) {
10808 return query_respond_any(qctx);
10809 }
10810
10811 result = query_zerottl_refetch(qctx);
10812 if (result != ISC_R_COMPLETE) {
10813 goto cleanup;
10814 }
10815
10816 return query_respond(qctx);
10817
10818 cleanup:
10819 return result;
10820 }
10821
10822 /*%
10823 * Add SOA to the authority section when sending negative responses
10824 * (or to the additional section if sending negative responses triggered
10825 * by RPZ rewriting.)
10826 */
10827 static isc_result_t
10828 query_addsoa(query_ctx_t *qctx, unsigned int override_ttl,
10829 dns_section_t section) {
10830 ns_client_t *client = qctx->client;
10831 dns_name_t *name = NULL;
10832 dns_dbnode_t *node = NULL;
10833 isc_result_t result, eresult = ISC_R_SUCCESS;
10834 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
10835 dns_rdataset_t **sigrdatasetp = NULL;
10836 dns_clientinfomethods_t cm;
10837 dns_clientinfo_t ci;
10838
10839 CTRACE(ISC_LOG_DEBUG(3), "query_addsoa");
10840
10841 dns_clientinfomethods_init(&cm, ns_client_sourceip);
10842 dns_clientinfo_init(&ci, client, NULL);
10843
10844 /*
10845 * Don't add the SOA record for test which set "-T nosoa".
10846 */
10847 if (((client->manager->sctx->options & NS_SERVER_NOSOA) != 0) &&
10848 (!WANTDNSSEC(client) || !dns_rdataset_isassociated(qctx->rdataset)))
10849 {
10850 return ISC_R_SUCCESS;
10851 }
10852
10853 /*
10854 * Get resources and make 'name' be the database origin.
10855 */
10856 dns_message_gettempname(client->message, &name);
10857
10858 /*
10859 * We'll be releasing 'name' before returning, so it's safe to
10860 * use clone instead of copying here.
10861 */
10862 dns_name_clone(dns_db_origin(qctx->db), name);
10863
10864 rdataset = ns_client_newrdataset(client);
10865 if (WANTDNSSEC(client) && dns_db_issecure(qctx->db)) {
10866 sigrdataset = ns_client_newrdataset(client);
10867 }
10868
10869 /*
10870 * Find the SOA.
10871 */
10872 result = dns_db_getoriginnode(qctx->db, &node);
10873 if (result == ISC_R_SUCCESS) {
10874 result = dns_db_findrdataset(qctx->db, node, qctx->version,
10875 dns_rdatatype_soa, 0, client->now,
10876 rdataset, sigrdataset);
10877 } else {
10878 dns_fixedname_t foundname;
10879 dns_name_t *fname;
10880
10881 fname = dns_fixedname_initname(&foundname);
10882
10883 result = dns_db_findext(qctx->db, name, qctx->version,
10884 dns_rdatatype_soa,
10885 client->query.dboptions, 0, &node,
10886 fname, &cm, &ci, rdataset, sigrdataset);
10887 }
10888 if (result != ISC_R_SUCCESS) {
10889 /*
10890 * This is bad. We tried to get the SOA RR at the zone top
10891 * and it didn't work!
10892 */
10893 CTRACE(ISC_LOG_ERROR, "unable to find SOA RR at zone apex");
10894 eresult = DNS_R_SERVFAIL;
10895 } else {
10896 /*
10897 * Extract the SOA MINIMUM.
10898 */
10899 dns_rdata_soa_t soa;
10900 dns_rdata_t rdata = DNS_RDATA_INIT;
10901 result = dns_rdataset_first(rdataset);
10902 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10903 dns_rdataset_current(rdataset, &rdata);
10904 result = dns_rdata_tostruct(&rdata, &soa, NULL);
10905 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10906
10907 if (override_ttl != UINT32_MAX && override_ttl < rdataset->ttl)
10908 {
10909 rdataset->ttl = override_ttl;
10910 if (sigrdataset != NULL) {
10911 sigrdataset->ttl = override_ttl;
10912 }
10913 }
10914
10915 /*
10916 * Add the SOA and its SIG to the response, with the
10917 * TTLs adjusted per RFC2308 section 3.
10918 */
10919 if (rdataset->ttl > soa.minimum) {
10920 rdataset->ttl = soa.minimum;
10921 }
10922 if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum) {
10923 sigrdataset->ttl = soa.minimum;
10924 }
10925
10926 if (sigrdataset != NULL) {
10927 sigrdatasetp = &sigrdataset;
10928 } else {
10929 sigrdatasetp = NULL;
10930 }
10931
10932 if (section == DNS_SECTION_ADDITIONAL) {
10933 rdataset->attributes |= DNS_RDATASETATTR_REQUIRED;
10934 }
10935 query_addrrset(qctx, &name, &rdataset, sigrdatasetp, NULL,
10936 section);
10937 }
10938
10939 ns_client_putrdataset(client, &rdataset);
10940 if (sigrdataset != NULL) {
10941 ns_client_putrdataset(client, &sigrdataset);
10942 }
10943 if (name != NULL) {
10944 ns_client_releasename(client, &name);
10945 }
10946 if (node != NULL) {
10947 dns_db_detachnode(qctx->db, &node);
10948 }
10949
10950 return eresult;
10951 }
10952
10953 /*%
10954 * Add NS to authority section (used when the zone apex is already known).
10955 */
10956 static isc_result_t
10957 query_addns(query_ctx_t *qctx) {
10958 ns_client_t *client = qctx->client;
10959 isc_result_t result, eresult;
10960 dns_name_t *name = NULL, *fname;
10961 dns_dbnode_t *node = NULL;
10962 dns_fixedname_t foundname;
10963 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
10964 dns_rdataset_t **sigrdatasetp = NULL;
10965 dns_clientinfomethods_t cm;
10966 dns_clientinfo_t ci;
10967
10968 CTRACE(ISC_LOG_DEBUG(3), "query_addns");
10969
10970 /*
10971 * Initialization.
10972 */
10973 eresult = ISC_R_SUCCESS;
10974 fname = dns_fixedname_initname(&foundname);
10975
10976 dns_clientinfomethods_init(&cm, ns_client_sourceip);
10977 dns_clientinfo_init(&ci, client, NULL);
10978
10979 /*
10980 * Get resources and make 'name' be the database origin.
10981 */
10982 dns_message_gettempname(client->message, &name);
10983 dns_name_clone(dns_db_origin(qctx->db), name);
10984 rdataset = ns_client_newrdataset(client);
10985
10986 if (WANTDNSSEC(client) && dns_db_issecure(qctx->db)) {
10987 sigrdataset = ns_client_newrdataset(client);
10988 }
10989
10990 /*
10991 * Find the NS rdataset.
10992 */
10993 result = dns_db_getoriginnode(qctx->db, &node);
10994 if (result == ISC_R_SUCCESS) {
10995 result = dns_db_findrdataset(qctx->db, node, qctx->version,
10996 dns_rdatatype_ns, 0, client->now,
10997 rdataset, sigrdataset);
10998 } else {
10999 CTRACE(ISC_LOG_DEBUG(3), "query_addns: calling dns_db_find");
11000 result = dns_db_findext(qctx->db, name, NULL, dns_rdatatype_ns,
11001 client->query.dboptions, 0, &node,
11002 fname, &cm, &ci, rdataset, sigrdataset);
11003 CTRACE(ISC_LOG_DEBUG(3), "query_addns: dns_db_find complete");
11004 }
11005 if (result != ISC_R_SUCCESS) {
11006 CTRACE(ISC_LOG_ERROR, "query_addns: "
11007 "dns_db_findrdataset or dns_db_find "
11008 "failed");
11009 /*
11010 * This is bad. We tried to get the NS rdataset at the zone
11011 * top and it didn't work!
11012 */
11013 eresult = DNS_R_SERVFAIL;
11014 } else {
11015 if (sigrdataset != NULL) {
11016 sigrdatasetp = &sigrdataset;
11017 }
11018 query_addrrset(qctx, &name, &rdataset, sigrdatasetp, NULL,
11019 DNS_SECTION_AUTHORITY);
11020 }
11021
11022 CTRACE(ISC_LOG_DEBUG(3), "query_addns: cleanup");
11023 ns_client_putrdataset(client, &rdataset);
11024 if (sigrdataset != NULL) {
11025 ns_client_putrdataset(client, &sigrdataset);
11026 }
11027 if (name != NULL) {
11028 ns_client_releasename(client, &name);
11029 }
11030 if (node != NULL) {
11031 dns_db_detachnode(qctx->db, &node);
11032 }
11033
11034 CTRACE(ISC_LOG_DEBUG(3), "query_addns: done");
11035 return eresult;
11036 }
11037
11038 /*%
11039 * Find the zone cut and add the best NS rrset to the authority section.
11040 */
11041 static void
11042 query_addbestns(query_ctx_t *qctx) {
11043 ns_client_t *client = qctx->client;
11044 dns_db_t *db = NULL, *zdb = NULL;
11045 dns_dbnode_t *node = NULL;
11046 dns_name_t *fname = NULL, *zfname = NULL;
11047 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
11048 dns_rdataset_t *zrdataset = NULL, *zsigrdataset = NULL;
11049 bool is_zone = false, use_zone = false;
11050 isc_buffer_t *dbuf = NULL;
11051 isc_result_t result;
11052 dns_dbversion_t *version = NULL;
11053 dns_zone_t *zone = NULL;
11054 isc_buffer_t b;
11055 dns_clientinfomethods_t cm;
11056 dns_clientinfo_t ci;
11057 dns_name_t qname;
11058
11059 CTRACE(ISC_LOG_DEBUG(3), "query_addbestns");
11060
11061 dns_clientinfomethods_init(&cm, ns_client_sourceip);
11062 dns_clientinfo_init(&ci, client, NULL);
11063
11064 dns_name_init(&qname, NULL);
11065 dns_name_clone(client->query.qname, &qname);
11066
11067 /*
11068 * Find the right database.
11069 */
11070 do {
11071 result = query_getdb(client, &qname, dns_rdatatype_ns,
11072 (dns_getdb_options_t){ 0 }, &zone, &db,
11073 &version, &is_zone);
11074 if (result != ISC_R_SUCCESS) {
11075 goto cleanup;
11076 }
11077
11078 /*
11079 * If this is a static stub zone look for a parent zone.
11080 */
11081 if (zone != NULL &&
11082 dns_zone_gettype(zone) == dns_zone_staticstub)
11083 {
11084 unsigned int labels = dns_name_countlabels(&qname);
11085 dns_db_detach(&db);
11086 dns_zone_detach(&zone);
11087 version = NULL;
11088 if (labels != 1) {
11089 dns_name_split(&qname, labels - 1, NULL,
11090 &qname);
11091 continue;
11092 }
11093 if (!USECACHE(client)) {
11094 goto cleanup;
11095 }
11096 dns_db_attach(client->view->cachedb, &db);
11097 is_zone = false;
11098 }
11099 break;
11100 } while (true);
11101
11102 db_find:
11103 /*
11104 * We'll need some resources...
11105 */
11106 dbuf = ns_client_getnamebuf(client);
11107 fname = ns_client_newname(client, dbuf, &b);
11108 rdataset = ns_client_newrdataset(client);
11109
11110 /*
11111 * Get the RRSIGs if the client requested them or if we may
11112 * need to validate answers from the cache.
11113 */
11114 if (WANTDNSSEC(client) || !is_zone) {
11115 sigrdataset = ns_client_newrdataset(client);
11116 }
11117
11118 /*
11119 * Now look for the zonecut.
11120 */
11121 if (is_zone) {
11122 result = dns_db_findext(
11123 db, client->query.qname, version, dns_rdatatype_ns,
11124 client->query.dboptions, client->now, &node, fname, &cm,
11125 &ci, rdataset, sigrdataset);
11126 if (result != DNS_R_DELEGATION) {
11127 goto cleanup;
11128 }
11129 if (USECACHE(client)) {
11130 ns_client_keepname(client, fname, dbuf);
11131 dns_db_detachnode(db, &node);
11132 SAVE(zdb, db);
11133 SAVE(zfname, fname);
11134 SAVE(zrdataset, rdataset);
11135 SAVE(zsigrdataset, sigrdataset);
11136 version = NULL;
11137 dns_db_attach(client->view->cachedb, &db);
11138 is_zone = false;
11139 goto db_find;
11140 }
11141 } else {
11142 result = dns_db_findzonecut(
11143 db, client->query.qname, client->query.dboptions,
11144 client->now, &node, fname, NULL, rdataset, sigrdataset);
11145 if (result == ISC_R_SUCCESS) {
11146 if (zfname != NULL &&
11147 !dns_name_issubdomain(fname, zfname))
11148 {
11149 /*
11150 * We found a zonecut in the cache, but our
11151 * zone delegation is better.
11152 */
11153 use_zone = true;
11154 }
11155 } else if (result == ISC_R_NOTFOUND && zfname != NULL) {
11156 /*
11157 * We didn't find anything in the cache, but we
11158 * have a zone delegation, so use it.
11159 */
11160 use_zone = true;
11161 } else {
11162 goto cleanup;
11163 }
11164 }
11165
11166 if (use_zone) {
11167 ns_client_releasename(client, &fname);
11168 /*
11169 * We've already done ns_client_keepname() on
11170 * zfname, so we must set dbuf to NULL to
11171 * prevent query_addrrset() from trying to
11172 * call ns_client_keepname() again.
11173 */
11174 dbuf = NULL;
11175 ns_client_putrdataset(client, &rdataset);
11176 if (sigrdataset != NULL) {
11177 ns_client_putrdataset(client, &sigrdataset);
11178 }
11179
11180 if (node != NULL) {
11181 dns_db_detachnode(db, &node);
11182 }
11183 dns_db_detach(&db);
11184
11185 RESTORE(db, zdb);
11186 RESTORE(fname, zfname);
11187 RESTORE(rdataset, zrdataset);
11188 RESTORE(sigrdataset, zsigrdataset);
11189 }
11190
11191 /*
11192 * Attempt to validate RRsets that are pending or that are glue.
11193 */
11194 if ((DNS_TRUST_PENDING(rdataset->trust) ||
11195 (sigrdataset != NULL && DNS_TRUST_PENDING(sigrdataset->trust))) &&
11196 !validate(client, db, fname, rdataset, sigrdataset) &&
11197 !PENDINGOK(client->query.dboptions))
11198 {
11199 goto cleanup;
11200 }
11201
11202 if ((DNS_TRUST_GLUE(rdataset->trust) ||
11203 (sigrdataset != NULL && DNS_TRUST_GLUE(sigrdataset->trust))) &&
11204 !validate(client, db, fname, rdataset, sigrdataset) &&
11205 SECURE(client) && WANTDNSSEC(client))
11206 {
11207 goto cleanup;
11208 }
11209
11210 /*
11211 * If the answer is secure only add NS records if they are secure
11212 * when the client may be looking for AD in the response.
11213 */
11214 if (SECURE(client) && (WANTDNSSEC(client) || WANTAD(client)) &&
11215 ((rdataset->trust != dns_trust_secure) ||
11216 (sigrdataset != NULL && sigrdataset->trust != dns_trust_secure)))
11217 {
11218 goto cleanup;
11219 }
11220
11221 /*
11222 * If the client doesn't want DNSSEC we can discard the sigrdataset
11223 * now.
11224 */
11225 if (!WANTDNSSEC(client)) {
11226 ns_client_putrdataset(client, &sigrdataset);
11227 }
11228
11229 query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf,
11230 DNS_SECTION_AUTHORITY);
11231
11232 cleanup:
11233 if (rdataset != NULL) {
11234 ns_client_putrdataset(client, &rdataset);
11235 }
11236 if (sigrdataset != NULL) {
11237 ns_client_putrdataset(client, &sigrdataset);
11238 }
11239 if (fname != NULL) {
11240 ns_client_releasename(client, &fname);
11241 }
11242 if (node != NULL) {
11243 dns_db_detachnode(db, &node);
11244 }
11245 if (db != NULL) {
11246 dns_db_detach(&db);
11247 }
11248 if (zone != NULL) {
11249 dns_zone_detach(&zone);
11250 }
11251 if (zdb != NULL) {
11252 ns_client_putrdataset(client, &zrdataset);
11253 if (zsigrdataset != NULL) {
11254 ns_client_putrdataset(client, &zsigrdataset);
11255 }
11256 if (zfname != NULL) {
11257 ns_client_releasename(client, &zfname);
11258 }
11259 dns_db_detach(&zdb);
11260 }
11261 }
11262
11263 static void
11264 query_addwildcardproof(query_ctx_t *qctx, bool ispositive, bool nodata) {
11265 ns_client_t *client = qctx->client;
11266 isc_buffer_t *dbuf, b;
11267 dns_name_t *name;
11268 dns_name_t *fname = NULL;
11269 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
11270 dns_fixedname_t wfixed;
11271 dns_name_t *wname;
11272 dns_dbnode_t *node = NULL;
11273 unsigned int options;
11274 unsigned int olabels, nlabels, labels;
11275 isc_result_t result;
11276 dns_rdata_t rdata = DNS_RDATA_INIT;
11277 dns_rdata_nsec_t nsec;
11278 bool have_wname;
11279 int order;
11280 dns_fixedname_t cfixed;
11281 dns_name_t *cname;
11282 dns_clientinfomethods_t cm;
11283 dns_clientinfo_t ci;
11284
11285 CTRACE(ISC_LOG_DEBUG(3), "query_addwildcardproof");
11286
11287 dns_clientinfomethods_init(&cm, ns_client_sourceip);
11288 dns_clientinfo_init(&ci, client, NULL);
11289
11290 /*
11291 * If a name has been specifically flagged as needing
11292 * a wildcard proof then it will have been copied to
11293 * qctx->wildcardname. Otherwise we just use the client
11294 * QNAME.
11295 */
11296 if (qctx->need_wildcardproof) {
11297 name = dns_fixedname_name(&qctx->wildcardname);
11298 } else {
11299 name = client->query.qname;
11300 }
11301
11302 /*
11303 * Get the NOQNAME proof then if !ispositive
11304 * get the NOWILDCARD proof.
11305 *
11306 * DNS_DBFIND_NOWILD finds the NSEC records that covers the
11307 * name ignoring any wildcard. From the owner and next names
11308 * of this record you can compute which wildcard (if it exists)
11309 * will match by finding the longest common suffix of the
11310 * owner name and next names with the qname and prefixing that
11311 * with the wildcard label.
11312 *
11313 * e.g.
11314 * Given:
11315 * example SOA
11316 * example NSEC b.example
11317 * b.example A
11318 * b.example NSEC a.d.example
11319 * a.d.example A
11320 * a.d.example NSEC g.f.example
11321 * g.f.example A
11322 * g.f.example NSEC z.i.example
11323 * z.i.example A
11324 * z.i.example NSEC example
11325 *
11326 * QNAME:
11327 * a.example -> example NSEC b.example
11328 * owner common example
11329 * next common example
11330 * wild *.example
11331 * d.b.example -> b.example NSEC a.d.example
11332 * owner common b.example
11333 * next common example
11334 * wild *.b.example
11335 * a.f.example -> a.d.example NSEC g.f.example
11336 * owner common example
11337 * next common f.example
11338 * wild *.f.example
11339 * j.example -> z.i.example NSEC example
11340 * owner common example
11341 * next common example
11342 * wild *.example
11343 */
11344 options = client->query.dboptions | DNS_DBFIND_NOWILD;
11345 wname = dns_fixedname_initname(&wfixed);
11346 again:
11347 have_wname = false;
11348 /*
11349 * We'll need some resources...
11350 */
11351 dbuf = ns_client_getnamebuf(client);
11352 fname = ns_client_newname(client, dbuf, &b);
11353 rdataset = ns_client_newrdataset(client);
11354 sigrdataset = ns_client_newrdataset(client);
11355
11356 result = dns_db_findext(qctx->db, name, qctx->version,
11357 dns_rdatatype_nsec, options, 0, &node, fname,
11358 &cm, &ci, rdataset, sigrdataset);
11359 if (node != NULL) {
11360 dns_db_detachnode(qctx->db, &node);
11361 }
11362
11363 if (!dns_rdataset_isassociated(rdataset)) {
11364 /*
11365 * No NSEC proof available, return NSEC3 proofs instead.
11366 */
11367 cname = dns_fixedname_initname(&cfixed);
11368 /*
11369 * Find the closest encloser.
11370 */
11371 dns_name_copy(name, cname);
11372 while (result == DNS_R_NXDOMAIN) {
11373 labels = dns_name_countlabels(cname) - 1;
11374 /*
11375 * Sanity check.
11376 */
11377 if (labels == 0U) {
11378 goto cleanup;
11379 }
11380 dns_name_split(cname, labels, NULL, cname);
11381 result = dns_db_findext(qctx->db, cname, qctx->version,
11382 dns_rdatatype_nsec, options, 0,
11383 NULL, fname, &cm, &ci, NULL,
11384 NULL);
11385 }
11386 /*
11387 * Add closest (provable) encloser NSEC3.
11388 */
11389 query_findclosestnsec3(cname, qctx->db, qctx->version, client,
11390 rdataset, sigrdataset, fname, true,
11391 cname);
11392 if (!dns_rdataset_isassociated(rdataset)) {
11393 goto cleanup;
11394 }
11395 if (!ispositive) {
11396 query_addrrset(qctx, &fname, &rdataset, &sigrdataset,
11397 dbuf, DNS_SECTION_AUTHORITY);
11398 }
11399
11400 /*
11401 * Replace resources which were consumed by query_addrrset.
11402 */
11403 if (fname == NULL) {
11404 dbuf = ns_client_getnamebuf(client);
11405 fname = ns_client_newname(client, dbuf, &b);
11406 }
11407
11408 if (rdataset == NULL) {
11409 rdataset = ns_client_newrdataset(client);
11410 } else if (dns_rdataset_isassociated(rdataset)) {
11411 dns_rdataset_disassociate(rdataset);
11412 }
11413
11414 if (sigrdataset == NULL) {
11415 sigrdataset = ns_client_newrdataset(client);
11416 } else if (dns_rdataset_isassociated(sigrdataset)) {
11417 dns_rdataset_disassociate(sigrdataset);
11418 }
11419
11420 /*
11421 * Add no qname proof.
11422 */
11423 labels = dns_name_countlabels(cname) + 1;
11424 if (dns_name_countlabels(name) == labels) {
11425 dns_name_copy(name, wname);
11426 } else {
11427 dns_name_split(name, labels, NULL, wname);
11428 }
11429
11430 query_findclosestnsec3(wname, qctx->db, qctx->version, client,
11431 rdataset, sigrdataset, fname, false,
11432 NULL);
11433 if (!dns_rdataset_isassociated(rdataset)) {
11434 goto cleanup;
11435 }
11436 query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf,
11437 DNS_SECTION_AUTHORITY);
11438
11439 if (ispositive) {
11440 goto cleanup;
11441 }
11442
11443 /*
11444 * Replace resources which were consumed by query_addrrset.
11445 */
11446 if (fname == NULL) {
11447 dbuf = ns_client_getnamebuf(client);
11448 fname = ns_client_newname(client, dbuf, &b);
11449 }
11450
11451 if (rdataset == NULL) {
11452 rdataset = ns_client_newrdataset(client);
11453 } else if (dns_rdataset_isassociated(rdataset)) {
11454 dns_rdataset_disassociate(rdataset);
11455 }
11456
11457 if (sigrdataset == NULL) {
11458 sigrdataset = ns_client_newrdataset(client);
11459 } else if (dns_rdataset_isassociated(sigrdataset)) {
11460 dns_rdataset_disassociate(sigrdataset);
11461 }
11462
11463 /*
11464 * Add the no wildcard proof.
11465 */
11466 result = dns_name_concatenate(dns_wildcardname, cname, wname,
11467 NULL);
11468 if (result != ISC_R_SUCCESS) {
11469 goto cleanup;
11470 }
11471
11472 query_findclosestnsec3(wname, qctx->db, qctx->version, client,
11473 rdataset, sigrdataset, fname, nodata,
11474 NULL);
11475 if (!dns_rdataset_isassociated(rdataset)) {
11476 goto cleanup;
11477 }
11478 query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf,
11479 DNS_SECTION_AUTHORITY);
11480
11481 goto cleanup;
11482 } else if (result == DNS_R_NXDOMAIN) {
11483 if (!ispositive) {
11484 result = dns_rdataset_first(rdataset);
11485 }
11486 if (result == ISC_R_SUCCESS) {
11487 dns_rdataset_current(rdataset, &rdata);
11488 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
11489 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11490 (void)dns_name_fullcompare(name, fname, &order,
11491 &olabels);
11492 (void)dns_name_fullcompare(name, &nsec.next, &order,
11493 &nlabels);
11494 /*
11495 * Check for a pathological condition created when
11496 * serving some malformed signed zones and bail out.
11497 */
11498 if (dns_name_countlabels(name) == nlabels) {
11499 goto cleanup;
11500 }
11501
11502 if (olabels > nlabels) {
11503 dns_name_split(name, olabels, NULL, wname);
11504 } else {
11505 dns_name_split(name, nlabels, NULL, wname);
11506 }
11507 result = dns_name_concatenate(dns_wildcardname, wname,
11508 wname, NULL);
11509 if (result == ISC_R_SUCCESS) {
11510 have_wname = true;
11511 }
11512 dns_rdata_freestruct(&nsec);
11513 }
11514 query_addrrset(qctx, &fname, &rdataset, &sigrdataset, dbuf,
11515 DNS_SECTION_AUTHORITY);
11516 }
11517 if (rdataset != NULL) {
11518 ns_client_putrdataset(client, &rdataset);
11519 }
11520 if (sigrdataset != NULL) {
11521 ns_client_putrdataset(client, &sigrdataset);
11522 }
11523 if (fname != NULL) {
11524 ns_client_releasename(client, &fname);
11525 }
11526 if (have_wname) {
11527 ispositive = true; /* prevent loop */
11528 if (!dns_name_equal(name, wname)) {
11529 name = wname;
11530 goto again;
11531 }
11532 }
11533 cleanup:
11534 if (rdataset != NULL) {
11535 ns_client_putrdataset(client, &rdataset);
11536 }
11537 if (sigrdataset != NULL) {
11538 ns_client_putrdataset(client, &sigrdataset);
11539 }
11540 if (fname != NULL) {
11541 ns_client_releasename(client, &fname);
11542 }
11543 }
11544
11545 /*%
11546 * Add NS records, and NSEC/NSEC3 wildcard proof records if needed,
11547 * to the authority section.
11548 */
11549 static void
11550 query_addauth(query_ctx_t *qctx) {
11551 CCTRACE(ISC_LOG_DEBUG(3), "query_addauth");
11552 /*
11553 * Add NS records to the authority section (if we haven't already
11554 * added them to the answer section).
11555 */
11556 if (!qctx->want_restart && !NOAUTHORITY(qctx->client)) {
11557 if (qctx->is_zone) {
11558 if (!qctx->answer_has_ns) {
11559 (void)query_addns(qctx);
11560 }
11561 } else if (!qctx->answer_has_ns &&
11562 qctx->qtype != dns_rdatatype_ns)
11563 {
11564 if (qctx->fname != NULL) {
11565 ns_client_releasename(qctx->client,
11566 &qctx->fname);
11567 }
11568 query_addbestns(qctx);
11569 }
11570 }
11571
11572 /*
11573 * Add NSEC records to the authority section if they're needed for
11574 * DNSSEC wildcard proofs.
11575 */
11576 if (qctx->need_wildcardproof && dns_db_issecure(qctx->db)) {
11577 query_addwildcardproof(qctx, true, false);
11578 }
11579 }
11580
11581 /*
11582 * Find the sort order of 'rdata' in the topology-like
11583 * ACL forming the second element in a 2-element top-level
11584 * sortlist statement.
11585 */
11586 static int
11587 query_sortlist_order_2element(const dns_rdata_t *rdata, const void *arg) {
11588 isc_netaddr_t netaddr;
11589
11590 if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS) {
11591 return INT_MAX;
11592 }
11593 return ns_sortlist_addrorder2(&netaddr, arg);
11594 }
11595
11596 /*
11597 * Find the sort order of 'rdata' in the matching element
11598 * of a 1-element top-level sortlist statement.
11599 */
11600 static int
11601 query_sortlist_order_1element(const dns_rdata_t *rdata, const void *arg) {
11602 isc_netaddr_t netaddr;
11603
11604 if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS) {
11605 return INT_MAX;
11606 }
11607 return ns_sortlist_addrorder1(&netaddr, arg);
11608 }
11609
11610 /*
11611 * Find the sortlist statement that applies to 'client' and set up
11612 * the sortlist info in in client->message appropriately.
11613 */
11614 static void
11615 query_setup_sortlist(query_ctx_t *qctx) {
11616 isc_netaddr_t netaddr;
11617 ns_client_t *client = qctx->client;
11618 dns_aclenv_t *env = client->manager->aclenv;
11619 dns_acl_t *acl = NULL;
11620 dns_aclelement_t *elt = NULL;
11621 void *order_arg = NULL;
11622
11623 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
11624 switch (ns_sortlist_setup(client->view->sortlist, env, &netaddr,
11625 &order_arg))
11626 {
11627 case NS_SORTLISTTYPE_1ELEMENT:
11628 elt = order_arg;
11629 dns_message_setsortorder(client->message,
11630 query_sortlist_order_1element, env,
11631 NULL, elt);
11632 break;
11633 case NS_SORTLISTTYPE_2ELEMENT:
11634 acl = order_arg;
11635 dns_message_setsortorder(client->message,
11636 query_sortlist_order_2element, env,
11637 acl, NULL);
11638 dns_acl_detach(&acl);
11639 break;
11640 case NS_SORTLISTTYPE_NONE:
11641 break;
11642 default:
11643 UNREACHABLE();
11644 }
11645 }
11646
11647 /*
11648 * When sending a referral, if the answer to the question is
11649 * in the glue, sort it to the start of the additional section.
11650 */
11651 static void
11652 query_glueanswer(query_ctx_t *qctx) {
11653 const dns_namelist_t *secs = qctx->client->message->sections;
11654 const dns_section_t section = DNS_SECTION_ADDITIONAL;
11655 dns_name_t *name;
11656 dns_message_t *msg;
11657 dns_rdataset_t *rdataset = NULL;
11658
11659 if (!ISC_LIST_EMPTY(secs[DNS_SECTION_ANSWER]) ||
11660 qctx->client->message->rcode != dns_rcode_noerror ||
11661 (qctx->qtype != dns_rdatatype_a &&
11662 qctx->qtype != dns_rdatatype_aaaa))
11663 {
11664 return;
11665 }
11666
11667 msg = qctx->client->message;
11668 for (name = ISC_LIST_HEAD(msg->sections[section]); name != NULL;
11669 name = ISC_LIST_NEXT(name, link))
11670 {
11671 if (dns_name_equal(name, qctx->client->query.qname)) {
11672 for (rdataset = ISC_LIST_HEAD(name->list);
11673 rdataset != NULL;
11674 rdataset = ISC_LIST_NEXT(rdataset, link))
11675 {
11676 if (rdataset->type == qctx->qtype) {
11677 break;
11678 }
11679 }
11680 break;
11681 }
11682 }
11683 if (rdataset != NULL) {
11684 ISC_LIST_UNLINK(msg->sections[section], name, link);
11685 ISC_LIST_PREPEND(msg->sections[section], name, link);
11686 ISC_LIST_UNLINK(name->list, rdataset, link);
11687 ISC_LIST_PREPEND(name->list, rdataset, link);
11688 rdataset->attributes |= DNS_RDATASETATTR_REQUIRED;
11689 }
11690 }
11691
11692 isc_result_t
11693 ns_query_done(query_ctx_t *qctx) {
11694 isc_result_t result = ISC_R_UNSET;
11695 const dns_namelist_t *secs = qctx->client->message->sections;
11696 bool partial_result_with_servfail = false;
11697
11698 CCTRACE(ISC_LOG_DEBUG(3), "ns_query_done");
11699
11700 CALL_HOOK(NS_QUERY_DONE_BEGIN, qctx);
11701
11702 /*
11703 * General cleanup.
11704 */
11705 qctx->rpz_st = qctx->client->query.rpz_st;
11706 if (qctx->rpz_st != NULL &&
11707 (qctx->rpz_st->state & DNS_RPZ_RECURSING) == 0)
11708 {
11709 rpz_match_clear(qctx->rpz_st);
11710 qctx->rpz_st->state &= ~DNS_RPZ_DONE_QNAME;
11711 }
11712
11713 qctx_clean(qctx);
11714 qctx_freedata(qctx);
11715
11716 /*
11717 * Clear the AA bit if we're not authoritative.
11718 */
11719 if (qctx->client->query.restarts == 0 && !qctx->authoritative) {
11720 qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AA;
11721 }
11722
11723 /*
11724 * Do we need to restart the query (e.g. for CNAME chaining)?
11725 */
11726 if (qctx->want_restart) {
11727 if (qctx->client->query.restarts <
11728 qctx->client->view->max_restarts)
11729 {
11730 query_ctx_t *saved_qctx = NULL;
11731 qctx->client->query.restarts++;
11732 saved_qctx = isc_mem_get(qctx->client->manager->mctx,
11733 sizeof(*saved_qctx));
11734 qctx_save(qctx, saved_qctx);
11735 isc_nmhandle_attach(qctx->client->handle,
11736 &qctx->client->restarthandle);
11737 isc_async_run(qctx->client->manager->loop,
11738 async_restart, saved_qctx);
11739 return DNS_R_CONTINUE;
11740 } else {
11741 /*
11742 * This is e.g. a long CNAME chain which we cut short.
11743 */
11744 qctx->client->query.attributes |=
11745 NS_QUERYATTR_PARTIALANSWER;
11746 qctx->client->message->rcode = dns_rcode_servfail;
11747 qctx->result = DNS_R_SERVFAIL;
11748
11749 /*
11750 * Send the answer back with a SERVFAIL result even
11751 * if recursion was requested.
11752 */
11753 partial_result_with_servfail = true;
11754
11755 dns_ede_add(&qctx->client->edectx, DNS_EDE_OTHER,
11756 "max. restarts reached");
11757 ns_client_log(qctx->client, NS_LOGCATEGORY_CLIENT,
11758 NS_LOGMODULE_QUERY, ISC_LOG_INFO,
11759 "query iterations limit reached");
11760 }
11761 }
11762
11763 if (qctx->result != ISC_R_SUCCESS &&
11764 (!PARTIALANSWER(qctx->client) ||
11765 (WANTRECURSION(qctx->client) && !partial_result_with_servfail) ||
11766 qctx->result == DNS_R_DROP))
11767 {
11768 if (qctx->result == DNS_R_DUPLICATE ||
11769 qctx->result == DNS_R_DROP)
11770 {
11771 /*
11772 * This was a duplicate query that we are
11773 * recursing on or the result of rate limiting.
11774 * Don't send a response now for a duplicate query,
11775 * because the original will still cause a response.
11776 */
11777 query_next(qctx->client, qctx->result);
11778 } else {
11779 /*
11780 * If we don't have any answer to give the client,
11781 * or if the client requested recursion and thus wanted
11782 * the complete answer, send an error response.
11783 */
11784 INSIST(qctx->line >= 0);
11785 query_error(qctx->client, qctx->result, qctx->line);
11786 }
11787
11788 qctx->detach_client = true;
11789 return qctx->result;
11790 }
11791
11792 /*
11793 * If we're recursing then just return; the query will
11794 * resume when recursion ends.
11795 */
11796 if (RECURSING(qctx->client) &&
11797 (!QUERY_STALETIMEOUT(&qctx->client->query) ||
11798 qctx->options.stalefirst))
11799 {
11800 return qctx->result;
11801 }
11802
11803 /*
11804 * We are done. Set up sortlist data for the message
11805 * rendering code, sort the answer to the front of the
11806 * additional section if necessary, make a final tweak
11807 * to the AA bit if the auth-nxdomain config option
11808 * says so, then render and send the response.
11809 */
11810 query_setup_sortlist(qctx);
11811 query_glueanswer(qctx);
11812
11813 if (qctx->client->message->rcode == dns_rcode_nxdomain &&
11814 qctx->view->auth_nxdomain)
11815 {
11816 qctx->client->message->flags |= DNS_MESSAGEFLAG_AA;
11817 }
11818
11819 /*
11820 * If the response is somehow unexpected for the client and this
11821 * is a result of recursion, return an error to the caller
11822 * to indicate it may need to be logged.
11823 */
11824 if (qctx->resuming &&
11825 (ISC_LIST_EMPTY(secs[DNS_SECTION_ANSWER]) ||
11826 qctx->client->message->rcode != dns_rcode_noerror))
11827 {
11828 qctx->result = ISC_R_FAILURE;
11829 }
11830
11831 CALL_HOOK(NS_QUERY_DONE_SEND, qctx);
11832
11833 query_send(qctx->client);
11834
11835 if (qctx->refresh_rrset) {
11836 /*
11837 * If we reached this point then it means that we have found a
11838 * stale RRset entry in cache and BIND is configured to allow
11839 * queries to be answered with stale data if no active RRset
11840 * is available, i.e. "stale-anwer-client-timeout 0". But, we
11841 * still need to refresh the RRset. To prevent adding duplicate
11842 * RRsets, clear the RRsets from the message before doing the
11843 * refresh.
11844 */
11845 message_clearrdataset(qctx->client->message, 0);
11846 query_stale_refresh(qctx->client);
11847 }
11848
11849 qctx->detach_client = true;
11850
11851 return qctx->result;
11852
11853 cleanup:
11854 /*
11855 * We'd only get here if one of the hooks above
11856 * (NS_QUERY_DONE_BEGIN or NS_QUERY_DONE_SEND) returned
11857 * NS_HOOK_RETURN. Some housekeeping may be needed.
11858 */
11859 qctx_clean(qctx);
11860 qctx_freedata(qctx);
11861 if (!qctx->async) {
11862 qctx->detach_client = true;
11863 query_error(qctx->client, DNS_R_SERVFAIL, __LINE__);
11864 }
11865 return result;
11866 }
11867
11868 static void
11869 log_tat(ns_client_t *client) {
11870 char namebuf[DNS_NAME_FORMATSIZE];
11871 char clientbuf[ISC_NETADDR_FORMATSIZE];
11872 char classbuf[DNS_RDATACLASS_FORMATSIZE];
11873 isc_netaddr_t netaddr;
11874 char *tags = NULL;
11875 size_t taglen = 0;
11876
11877 if (!isc_log_wouldlog(ns_lctx, ISC_LOG_INFO)) {
11878 return;
11879 }
11880
11881 if ((client->query.qtype != dns_rdatatype_null ||
11882 !dns_name_istat(client->query.qname)) &&
11883 (client->keytag == NULL ||
11884 client->query.qtype != dns_rdatatype_dnskey))
11885 {
11886 return;
11887 }
11888
11889 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
11890 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
11891 isc_netaddr_format(&netaddr, clientbuf, sizeof(clientbuf));
11892 dns_rdataclass_format(client->view->rdclass, classbuf,
11893 sizeof(classbuf));
11894
11895 if (client->query.qtype == dns_rdatatype_dnskey) {
11896 uint16_t keytags = client->keytag_len / 2;
11897 size_t len = taglen = sizeof("65000") * keytags + 1;
11898 char *cp = tags = isc_mem_get(client->manager->mctx, taglen);
11899 int i = 0;
11900
11901 INSIST(client->keytag != NULL);
11902 if (tags != NULL) {
11903 while (keytags-- > 0U) {
11904 int n;
11905 uint16_t keytag;
11906 keytag = (client->keytag[i * 2] << 8) |
11907 client->keytag[i * 2 + 1];
11908 n = snprintf(cp, len, " %u", keytag);
11909 if (n > 0 && (size_t)n <= len) {
11910 cp += n;
11911 len -= n;
11912 i++;
11913 } else {
11914 break;
11915 }
11916 }
11917 }
11918 }
11919
11920 isc_log_write(ns_lctx, NS_LOGCATEGORY_TAT, NS_LOGMODULE_QUERY,
11921 ISC_LOG_INFO, "trust-anchor-telemetry '%s/%s' from %s%s",
11922 namebuf, classbuf, clientbuf, tags != NULL ? tags : "");
11923 if (tags != NULL) {
11924 isc_mem_put(client->manager->mctx, tags, taglen);
11925 }
11926 }
11927
11928 static void
11929 log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) {
11930 char namebuf[DNS_NAME_FORMATSIZE];
11931 char typebuf[DNS_RDATATYPE_FORMATSIZE];
11932 char classbuf[DNS_RDATACLASS_FORMATSIZE];
11933 char onbuf[ISC_NETADDR_FORMATSIZE];
11934 char ecsbuf[NS_CLIENT_ECS_FORMATSIZE] = { 0 };
11935 char flagsbuf[NS_CLIENT_FLAGS_FORMATSIZE] = { 0 };
11936 dns_rdataset_t *rdataset;
11937 int level = ISC_LOG_INFO;
11938
11939 if (!isc_log_wouldlog(ns_lctx, level)) {
11940 return;
11941 }
11942
11943 rdataset = ISC_LIST_HEAD(client->query.qname->list);
11944 INSIST(rdataset != NULL);
11945 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
11946 dns_rdataclass_format(rdataset->rdclass, classbuf, sizeof(classbuf));
11947 dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf));
11948 isc_netaddr_format(&client->destaddr, onbuf, sizeof(onbuf));
11949
11950 if (HAVEECS(client)) {
11951 ns_client_log_ecs(client, ecsbuf, sizeof(ecsbuf));
11952 }
11953 ns_client_log_flags(client, flags, extflags, flagsbuf,
11954 sizeof(flagsbuf));
11955
11956 ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY, level,
11957 "query: %s %s %s %s (%s)%s", namebuf, classbuf, typebuf,
11958 flagsbuf, onbuf, ecsbuf);
11959 }
11960
11961 static void
11962 log_queryerror(ns_client_t *client, isc_result_t result, int line, int level) {
11963 char namebuf[DNS_NAME_FORMATSIZE];
11964 char typebuf[DNS_RDATATYPE_FORMATSIZE];
11965 char classbuf[DNS_RDATACLASS_FORMATSIZE];
11966 const char *namep, *typep, *classp, *sep1, *sep2;
11967 dns_rdataset_t *rdataset;
11968
11969 if (!isc_log_wouldlog(ns_lctx, level)) {
11970 return;
11971 }
11972
11973 namep = typep = classp = sep1 = sep2 = "";
11974
11975 /*
11976 * Query errors can happen for various reasons. In some cases we cannot
11977 * even assume the query contains a valid question section, so we should
11978 * expect exceptional cases.
11979 */
11980 if (client->query.origqname != NULL) {
11981 dns_name_format(client->query.origqname, namebuf,
11982 sizeof(namebuf));
11983 namep = namebuf;
11984 sep1 = " for ";
11985
11986 rdataset = ISC_LIST_HEAD(client->query.origqname->list);
11987 if (rdataset != NULL) {
11988 dns_rdataclass_format(rdataset->rdclass, classbuf,
11989 sizeof(classbuf));
11990 classp = classbuf;
11991 dns_rdatatype_format(rdataset->type, typebuf,
11992 sizeof(typebuf));
11993 typep = typebuf;
11994 sep2 = "/";
11995 }
11996 }
11997
11998 ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS, NS_LOGMODULE_QUERY,
11999 level, "query failed (%s)%s%s%s%s%s%s at %s:%d",
12000 isc_result_totext(result), sep1, namep, sep2, classp,
12001 sep2, typep, __FILE__, line);
12002 }
12003
12004 void
12005 ns_query_start(ns_client_t *client, isc_nmhandle_t *handle) {
12006 isc_result_t result;
12007 dns_message_t *message;
12008 dns_rdataset_t *rdataset;
12009 dns_rdatatype_t qtype;
12010 unsigned int saved_extflags;
12011 unsigned int saved_flags;
12012
12013 REQUIRE(NS_CLIENT_VALID(client));
12014
12015 /*
12016 * Attach to the request handle
12017 */
12018 isc_nmhandle_attach(handle, &client->reqhandle);
12019
12020 message = client->message;
12021 saved_extflags = client->extflags;
12022 saved_flags = client->message->flags;
12023
12024 CTRACE(ISC_LOG_DEBUG(3), "ns_query_start");
12025
12026 /*
12027 * Ensure that appropriate cleanups occur.
12028 */
12029 client->cleanup = query_cleanup;
12030
12031 if ((message->flags & DNS_MESSAGEFLAG_RD) != 0) {
12032 client->query.attributes |= NS_QUERYATTR_WANTRECURSION;
12033 }
12034
12035 if ((client->extflags & DNS_MESSAGEEXTFLAG_DO) != 0) {
12036 client->attributes |= NS_CLIENTATTR_WANTDNSSEC;
12037 }
12038
12039 switch (client->view->minimalresponses) {
12040 case dns_minimal_no:
12041 break;
12042 case dns_minimal_yes:
12043 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
12044 NS_QUERYATTR_NOADDITIONAL);
12045 break;
12046 case dns_minimal_noauth:
12047 client->query.attributes |= NS_QUERYATTR_NOAUTHORITY;
12048 break;
12049 case dns_minimal_noauthrec:
12050 if ((message->flags & DNS_MESSAGEFLAG_RD) != 0) {
12051 client->query.attributes |= NS_QUERYATTR_NOAUTHORITY;
12052 }
12053 break;
12054 }
12055
12056 if (client->view->cachedb == NULL || !client->view->recursion) {
12057 /*
12058 * We don't have a cache. Turn off cache support and
12059 * recursion.
12060 */
12061 client->query.attributes &= ~(NS_QUERYATTR_RECURSIONOK |
12062 NS_QUERYATTR_CACHEOK);
12063 client->attributes |= NS_CLIENTATTR_NOSETFC;
12064 } else if ((client->attributes & NS_CLIENTATTR_RA) == 0 ||
12065 (message->flags & DNS_MESSAGEFLAG_RD) == 0)
12066 {
12067 /*
12068 * If the client isn't allowed to recurse (due to
12069 * "recursion no", the allow-recursion ACL, or the
12070 * lack of a resolver in this view), or if it
12071 * doesn't want recursion, turn recursion off.
12072 */
12073 client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK;
12074 client->attributes |= NS_CLIENTATTR_NOSETFC;
12075 }
12076
12077 /*
12078 * Check for multiple question queries, since edns1 is dead.
12079 */
12080 if (message->counts[DNS_SECTION_QUESTION] > 1) {
12081 query_error(client, DNS_R_FORMERR, __LINE__);
12082 return;
12083 }
12084
12085 /*
12086 * Get the question name.
12087 */
12088 result = dns_message_firstname(message, DNS_SECTION_QUESTION);
12089 if (result != ISC_R_SUCCESS) {
12090 query_error(client, result, __LINE__);
12091 return;
12092 }
12093 dns_message_currentname(message, DNS_SECTION_QUESTION,
12094 &client->query.qname);
12095 client->query.origqname = client->query.qname;
12096 result = dns_message_nextname(message, DNS_SECTION_QUESTION);
12097 if (result != ISC_R_NOMORE) {
12098 if (result == ISC_R_SUCCESS) {
12099 /*
12100 * There's more than one QNAME in the question
12101 * section.
12102 */
12103 query_error(client, DNS_R_FORMERR, __LINE__);
12104 } else {
12105 query_error(client, result, __LINE__);
12106 }
12107 return;
12108 }
12109
12110 if ((client->manager->sctx->options & NS_SERVER_LOGQUERIES) != 0) {
12111 log_query(client, saved_flags, saved_extflags);
12112 }
12113
12114 /*
12115 * Check for meta-queries like IXFR and AXFR.
12116 */
12117 rdataset = ISC_LIST_HEAD(client->query.qname->list);
12118 INSIST(rdataset != NULL);
12119 client->query.qtype = qtype = rdataset->type;
12120 dns_rdatatypestats_increment(client->manager->sctx->rcvquerystats,
12121 qtype);
12122
12123 log_tat(client);
12124
12125 if (dns_rdatatype_ismeta(qtype)) {
12126 switch (qtype) {
12127 case dns_rdatatype_any:
12128 break; /* Let the query logic handle it. */
12129 case dns_rdatatype_ixfr:
12130 case dns_rdatatype_axfr:
12131 if (isc_nm_is_http_handle(handle)) {
12132 /*
12133 * We cannot use DoH for zone transfers.
12134 * According to RFC 8484 a DoH request contains
12135 * exactly one DNS message (see Section 6:
12136 * Definition of the "application/dns-message"
12137 * Media Type).
12138 *
12139 * This makes DoH unsuitable for zone transfers
12140 * as often (and usually!) these need more than
12141 * one DNS message, especially for larger zones.
12142 * As zone transfers over DoH are not (yet)
12143 * standardised, nor discussed in RFC 8484,
12144 * the best thing we can do is to return "not
12145 * implemented".
12146 */
12147 query_error(client, DNS_R_NOTIMP, __LINE__);
12148 return;
12149 }
12150 if (isc_nm_socket_type(handle) ==
12151 isc_nm_streamdnssocket)
12152 {
12153 /*
12154 * Currently this code is here for DoT, which
12155 * has more complex requirements for zone
12156 * transfers compared to other stream
12157 * protocols. See RFC 9103 for details.
12158 */
12159 switch (isc_nm_xfr_checkperm(handle)) {
12160 case ISC_R_SUCCESS:
12161 break;
12162 case ISC_R_DOTALPNERROR:
12163 query_error(client, DNS_R_NOALPN,
12164 __LINE__);
12165 return;
12166 default:
12167 query_error(client, DNS_R_REFUSED,
12168 __LINE__);
12169 return;
12170 }
12171 }
12172 ns_xfr_start(client, rdataset->type);
12173 return;
12174 case dns_rdatatype_maila:
12175 case dns_rdatatype_mailb:
12176 query_error(client, DNS_R_NOTIMP, __LINE__);
12177 return;
12178 case dns_rdatatype_tkey:
12179 result = dns_tkey_processquery(
12180 client->message, client->manager->sctx->tkeyctx,
12181 client->view->dynamickeys);
12182 if (result == ISC_R_SUCCESS) {
12183 query_send(client);
12184 } else {
12185 query_error(client, result, __LINE__);
12186 }
12187 return;
12188 default: /* TSIG, etc. */
12189 query_error(client, DNS_R_FORMERR, __LINE__);
12190 return;
12191 }
12192 }
12193
12194 /*
12195 * Turn on minimal response for (C)DNSKEY and (C)DS queries.
12196 */
12197 if (dns_rdatatype_iskeymaterial(qtype) || qtype == dns_rdatatype_ds) {
12198 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
12199 NS_QUERYATTR_NOADDITIONAL);
12200 } else if (qtype == dns_rdatatype_ns) {
12201 /*
12202 * Always turn on additional records for NS queries.
12203 */
12204 client->query.attributes &= ~(NS_QUERYATTR_NOAUTHORITY |
12205 NS_QUERYATTR_NOADDITIONAL);
12206 }
12207
12208 /*
12209 * Maybe turn on minimal responses for ANY queries.
12210 */
12211 if (qtype == dns_rdatatype_any && client->view->minimal_any &&
12212 !TCP(client))
12213 {
12214 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
12215 NS_QUERYATTR_NOADDITIONAL);
12216 }
12217
12218 /*
12219 * Turn on minimal responses for EDNS/UDP bufsize 512 queries.
12220 */
12221 if (client->ednsversion >= 0 && client->udpsize <= 512U && !TCP(client))
12222 {
12223 client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
12224 NS_QUERYATTR_NOADDITIONAL);
12225 }
12226
12227 /*
12228 * If the client has requested that DNSSEC checking be disabled,
12229 * allow lookups to return pending data and instruct the resolver
12230 * to return data before validation has completed.
12231 *
12232 * We don't need to set DNS_DBFIND_PENDINGOK when validation is
12233 * disabled as there will be no pending data.
12234 */
12235 if ((message->flags & DNS_MESSAGEFLAG_CD) != 0 ||
12236 qtype == dns_rdatatype_rrsig)
12237 {
12238 client->query.dboptions |= DNS_DBFIND_PENDINGOK;
12239 client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
12240 } else if (!client->view->enablevalidation) {
12241 client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
12242 }
12243
12244 if (client->view->qminimization) {
12245 client->query.fetchoptions |= DNS_FETCHOPT_QMINIMIZE |
12246 DNS_FETCHOPT_QMIN_SKIP_IP6A;
12247 if (client->view->qmin_strict) {
12248 client->query.fetchoptions |= DNS_FETCHOPT_QMIN_STRICT;
12249 }
12250 }
12251
12252 /*
12253 * Allow glue NS records to be added to the authority section
12254 * if the answer is secure.
12255 */
12256 if ((message->flags & DNS_MESSAGEFLAG_CD) != 0) {
12257 client->query.attributes &= ~NS_QUERYATTR_SECURE;
12258 }
12259
12260 /*
12261 * Set NS_CLIENTATTR_WANTAD if the client has set AD in the query.
12262 * This allows AD to be returned on queries without DO set.
12263 */
12264 if ((message->flags & DNS_MESSAGEFLAG_AD) != 0) {
12265 client->attributes |= NS_CLIENTATTR_WANTAD;
12266 }
12267
12268 /*
12269 * This is an ordinary query.
12270 */
12271 result = dns_message_reply(message, true);
12272 if (result != ISC_R_SUCCESS) {
12273 query_next(client, result);
12274 return;
12275 }
12276
12277 /*
12278 * Assume authoritative response until it is known to be
12279 * otherwise.
12280 *
12281 * If "-T noaa" has been set on the command line don't set
12282 * AA on authoritative answers.
12283 */
12284 if ((client->manager->sctx->options & NS_SERVER_NOAA) == 0) {
12285 message->flags |= DNS_MESSAGEFLAG_AA;
12286 }
12287
12288 /*
12289 * Set AD. We must clear it if we add non-validated data to a
12290 * response.
12291 */
12292 if (WANTDNSSEC(client) || WANTAD(client)) {
12293 message->flags |= DNS_MESSAGEFLAG_AD;
12294 }
12295
12296 /*
12297 * Start global outgoing query count.
12298 */
12299 result = isc_counter_create(client->manager->mctx,
12300 client->view->max_queries,
12301 &client->query.qc);
12302 if (result != ISC_R_SUCCESS) {
12303 query_next(client, result);
12304 return;
12305 }
12306
12307 query_setup(client, qtype);
12308 }
12309