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