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